d==导致安全方法中的类数组出错
创始人
2025-05-28 21:45:02

原文
以下代码编译:

class C { int a; this(int) @safe {} }void main()
{C c = new C(1);C[] a = [c, c, c];assert(a == [c, c, c]);
}

以下代码失败:

class C { int a; this(int) @safe {} }@safe void main()
{C c = new C(1);C[] a = [c, c, c];assert(a == [c, c, c]);
}

C[]C[3]不匹配.
这像是2.078.1的回归.显然,对象(object).__equals!(C,C).__equals函数不是@safe.但是,从2.094.1开始,此错误已更改为:错误:'C[]''C[3]'的数组比较类型不兼容.

我想要修复需要两部分:1,更改dmd以避免错误地显示不兼容类型的错误;2更改druntime,使比较安全.
这不是编译器错误.而是druntime错误[1],可见构造了druntime调用,然后试了语义.
如果有错误,编译器会简单地假设类型不兼容.这是kinke[2]中引入的,这样用户得不到指向druntime的错误.
如果在[2]中使用"expressionSemantic"而不是"trySemantic",则会得到错误说:
'core.object.opEquals'[3]不是@safe,并且因为它调用了'Object.opEquals'不能是@safe的.

事实上,仅比较两个用户未定义opEquals的类,'assert(c==c)'就会在@safe代码中发出错误:"Dmain"这个"@safe"函数无法调用opEquals"这个"@system"函数对象.
因此,根本问题是'object.opEquals'是不安全的,并且不能使其成为@safe,因为这样,类就只能限制为@safeopEquals.(是否可更改属性继承规则来绕过该问题[4]中的第6点)
1
2
3
4

刚在2.102.1中遇见了该问题.示例中,错误消息更令人吃惊:
"X[]""X[]"数组比较不兼容类型
这已帮助我猜测原因是@systemObject.opEquals.
但是整个问题,不论是'C[3]'还是'X[]',都可能让新手困惑.他们遵循@safe的最佳实践,照本宣科地比较数组,结果却遇见了错误,即甚至不能让数组与其自身比较.

考虑以下:

class C { int a; this(int) @safe {} }
class D : C {this(int a) @safe { super(a); }override bool opEquals(Object rhs) const {// 明显不安全.*(cast(int*) 0x5afe) = 0xdead5afe;return true;}
}@safe void main()
{C c = new D(1);C[] a = [c, c, c];assert(a == [c, c, c]);
}

编译器错误消息应该告诉,用'@safe'覆盖子类中的opEquals,尽管这样做仍会发出错误.

class C {int a; this(int) @safe {}override bool opEquals(Object rhs) @safe {return this is rhs;}
}@safe void main()
{C c = new C(1);C[] a = [c, c, c];assert(a == [c, c, c]);
}

所以应该允许后者,错误消息应该在禁止前者时,告诉你应该编写它.
如果比较的类的类型不覆盖opEquals等于操作,则最后调用Object.opEquals.
因为Object.opEquals@系统,@安全用户代码会发出令人困惑的比较不兼容类型.
为此,只需要检查是否正在调用Object.opEquals,并且信任它(只是在比较).
不让Object.opEquals@安全?因为会破坏大量代码.

在我看来,最初的bug是一个诊断bug,编译器没有给出有用错误消息,但行为是正确的.是系统就是这样不应从安全代码调用.

相关内容

热门资讯

酱大骨祖传秘方:家常做法步骤详... 你是否曾经想过,如何才能炖出一锅肉质软烂、骨髓鲜香的酱大骨? 在家庭聚会中,酱大骨往往是桌上最受...
白灼菜心的家常做法:步骤详细,... 你是否在节假日的聚餐中,感到肉类菜肴吃得太多,胃口变得沉重?想要寻找一款清爽解腻的蔬菜来平衡一下吗?...
家常菜秘籍:葱烧牛肉详细步骤,... 你是否曾经在家中尝试做葱烧牛肉,却发现牛肉总是嚼不动,口感柴硬?或者,你想知道如何才能让牛肉变得滑嫩...
14道高端会所造型菜 芝士焗金仓鱼 原料: 活金仓鱼,芝士粉,芝士片,柠檬叶丝,盐。 制作: 1、将金仓鱼宰杀治净,加盐...