d的更好C关闭ctfe的dup
//dmd -betterC
mixin(`void foo(){}`.idup);
//错误:`'TypeInfo'`不能与`-betterC`一起使用
这会导致mir.bitmanip和mir-cpuid中的BetterC回归
我也有类似的问题.用betterC编译时,在CTFE中phobos的大多数东西不管用(在dmd和ldc中,有同样错误)
void main() {
import std.uni : toLower;
pragma(msg,"asdfBsdf".toLower);
}
在此讨论,需要修复.
之所以有该错误,是因为在打开BetterC时已版本化了object.d中idup()的定义,所以ctfe找不到它.
对此很难.
在betterC中有idup,只是编译器拒绝运行它.
在编译时环境中执行时,不应限制betterC.
建议专门用if(__ctfe)覆盖容易算出来的betterC的检查.就像:
int* do_something() {
if(__ctfe) {
return new int;
} else {
return cast(int*) malloc(int.sizeof);
}
}
enum e = *do_something();
应该可在编译时允许运行时禁止的东西.
很好观点.CTFE很难,因为即使此时不会运行代码,它仍然需要编译.
没有进入对象符号表的函数,仅用于CTFE的编译和运行.如果在运行时引用它们,则抛错误.这是可行的.
或在betterC模式下,逆转绑定为d运行时的idup(显然这在以前是有效的).
观点是代码编译得很好.只是没有druntime链接或未生成typeinfo,或运行时依赖,因而不链接.
-betterC开关试检测这些潜在链接器错误,并在编译中提前报告它们,以获得更一致和用户友好错误.因为,
if(__ctfe)
//或
mixin
//或
pragma(msg)
等仅涉及编译时工具,从不参与生成代码,因此不应有链接器错误,编译器*应该*知道这一点,而不是导致提前编译错误.
__traits(compiles)
//或
is(typeof())
是灰色区域,也不生成代码,因此不应生成链接器错误,也不应生成betterC错误,但考虑到它的使用方式,应该假设里面内容会用来生成代码,因此此时,应返回假.
但如果拿不准,'-betterC'目标应该是给出与'-defaultlib='相同的输出,只是带编译错误而不是链接器的未定义符号错误.
但这不是问题,CTFE有部分可编译,但不编译部分,如在ctfe时,typeid(x)确实不编译.那么如何"编译"它,仅允许在编译时运行?因此这很难.
很难完美检测druntime,如,如下无编译错误,但有链接错误(使用-betterC):
import core.thread;
import core.time;
extern(C) void main()
{
Thread.sleep(1.seconds);
}
当然,__traits(compiles)会说好,所以这确实是灰色地带.
哦,刚想到一个主意.考虑一下导致问题的_dup模板.如果这样:
version(D_BetterC) extern(C) void _dup_UNAVAILABLE_IN_BETTERC();
private U[] _dup(T, U)(T[] a) // 根据后复制的pure nothrow
{
if (__ctfe)
{ /* ctfe代码*/ }
version(D_BetterC) {
_dup_UNAVAILABLE_IN_BETTERC();
return U[].init;
}
else:
// 用typeid的普通代码
}
延迟错误到链接器,但标记出问题的函数.可需要时用简单插件完成.
这是带清晰消息的编译器错误.
但这确实改变了idup,使它在__traits(compiles)时返回真.这有问题吗?没有.用(D_BetterC)版本代替__traits(compiles).
而且,它不工作.编译时使用模板会使它想链接到符号.除非能区分编译时和运行时用的啥,否则,这不工作.
在__traits(compiles)内部使用时,betterC错误似乎会终止编译.
这不会打印内容,也不会生成二进制:
extern(C) void main()
{
int[] arr;
pragma(msg, __traits(compiles, arr.idup));
}
如下问题,导致该错误.
private string makefoo() {
if(__ctfe) {
string a = "b";
a ~= "c\0";
return a;
}
assert(0);
}
enum foo = makefoo();
extern(C) int main() {
import core.stdc.stdio;
printf("%s", foo.ptr);
return 0;
}
这里的private函数,基于private'和'if(__ctfe)',显然是仅CTFE的.但编译器不知道.
或可搞个类似'pragma(ct_only)'的语句.
修复
这是权宜之计,但最好,函数不需要版本化代码来适应它们在betterC中的CTFE使用.
浙公网安备 33010602011771号