d奇怪的dip1000问题
原文
进一步化简:
alias VErr = char*;
ref front_r(ref VErr r) { return r; }
ref front_p(VErr* p) { return *p; }
ref front_s(VErr[] s) { return s[0]; }
VErr g;
void main() @safe
{
VErr[1] _errors;
g = _errors[0]; /* .1从静态数组: ok */
g = front_r(_errors[0]); /*.2从引用复制的引用: ok */
g = front_p(&_errors[0]);
//.3从指针的引用,失败,但应工作
g = front_s(_errors[]);
//.4从切片的引用,失败,但应工作
}
.1,它们在同一个函数中,所以数据流分析可知道域地址未赋值给_错误元素.
.2,引用是头域,不会感染符*自身
.3,因为&_错误[0]是栈变量指针,它必须是域.指针有传递性域,因此符*也感染了
.4,同样,_错误[]切片包含栈变量指针,因此必须为域,与指针一样,切片也有传递性域.
我想大部分域和相关属性,的困惑在于域是不应带却带有传递性.
相反,应允许直接指定多少级间接及每个聚集字段是否总是域,及遵循域的父项(如现在),或不要域.
当前的设计从根本上是混乱和不一致的,因为大多数间接寻址链的真正根是栈指针的一些偏移,而如果显式确认为栈指针,则它必须是域.因为域是可传递的,表明大多数都应该是域,这是愚蠢的.
这确实是个很好示例来说明域,因为域是不可传递的,且不应是:
char* global;
void main() @safe
{
char* local;
scope char** p = &local;
global = *p; // ok
}
d作者回复:
1.&_errors是栈指针.
2.传递栈指针给front_p的'p'变量.
3.因为'p'未按'scope'声明,编译器假定front_p允许'p'逃逸.(对普通函数,不会推导属性.)
4.dip1000规则禁止逃逸栈指针.
编译器按期望工作.
如此,无情地化简该示例,帮助揭示真正的问题.
'front_p'确实会推导属性,因为它没有声明返回类型.
浙公网安备 33010602011771号