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
使用.