修复opApply重载
对opApply
特化,旧实现用Type.covariant
来抑制过度歧义
错误.延迟检查歧义至循环体上推断属性后,允许如对@safe/@system
闭包用@safe/@system
不同属性的opApply
重载.
示例:
struct Collection {
/* A. */ int opApply(int delegate(int) @safe dg) @safe;
/* B. */ int opApply(int delegate(int) @system dg) @system;
}
void main() @safe {
Collection col;
foreach (entry; col) {} // 解析为A.
}
前面代码检查之前选择的opApply
和当前重载是否在某
方向上是协变
的(即A.covariant(B)
或B.协变(A)
).
本实现
建立在即示例中的opApply
函数是协变的有缺陷
的假设上,但它们不是(由于Type.covariant
中的错误而错误
报告).
考虑opApply
重载类型
A: int function(int delegate(int) @safe dg) @safe;
B: int function(int delegate(int) @system dg) @system;
A/B
都不是另一个合适的替代品:
由于opApply
的属性,A<=B
是无效的.A
的@system
函数可能不会在@safe
函数中出现.
由于参数类型(dg属性
),A=>B
无效.
可能不会按接受@system
回调函数对待期待@safe
闭包的函数
.否则可默默地执行@safe
函数中禁止的@system
回调.
注意,示例中回调用函数
而不是闭包
时,Type.covariant
已拒绝协变.
新实现不依赖于Type.covariant
的易错行为.它检查两个不同方面来延迟解析opApply
:
opApply
函数上的不同属性
接收foreach
主体回调的协变
因为matchParamsToOpApply
拒绝不匹配参数类型,(2)
应处理foreach
主体上不同的限定符
.
此补丁
使我们可不破坏现有代码
修复上述错误.它还允许尽管有效但也没啥用的在测试用例
中加代码.