原文
总结
替换D的逃逸分析
Rikki说,他一个月前曾与Dennis讨论过简化D的逃逸分析,但没有结果.在BeerConf上,他再次提起了它,Dennis说他一直在考虑它.
Rikki也与Walter谈过这件事,Walter曾说过DIP1000并没有完全如期工作,且有点太复杂了.
因此,Rikki想讨论按D逃逸分析方法替换DIP1000的可能性.在做出可靠的决定前,第一步是确保它完全在预览开关之下.丹尼斯证实当前是这样.
Rikki说,下一步是考虑切换它及它可能的样子.他请求建议.
Dennis说,在决定如何切换它前,应该首先说明当前设计原因及切换的目标.他说他有一些问题.一个是缺乏传递域.
另一个问题是,即使结构有多个成员,它们也只有一个生命期.他一直在考虑允许按域注解结构字段,但他还没有具体的提议.
Walter说,他遇见的困难不是DIP1000复杂,而是语言复杂.必须适配语言的各种构造.引用类型工作原理或隐式类类型或懒参数构造器这就是复杂性的来源.
他给出了成员函数的隐式本参数的示例.如果有人想了解如何在构造器或成员函数中使用DIP1000,他一遍遍地解释说,则只需要按显式参数一样,把它写出来.
然后就能看到它应该是如何操作的.但人们发现这无休止地困惑.
简化它的提案还必须证明它如何可能比现在的DIP1000更简单,因为DIP1000很复杂,因为语言很复杂.它必须支持每个语言结构.
Rikki说,逃逸分析分为三个不同级.最基本级是"这是一个而它帮助输出的输出".然后你就有了语言可推导出的东西.
然后就有了你可添加的可证明的东西.现在真没有那个规模,所以现在当事情太宽泛时,没有逃避的机会.
walter重申,DIP1000的复杂性是因为语言的复杂性,而不是概念自身,这非常简单.如果用指针写出来,一切都会很清晰和简单.
当你添加像auto ref此东西时,它开始复杂.他从来不喜欢auto ref,也从没用过它,因为它太怪了.
他说,如果Rikki能想出更好方法来完成,他会支持.DIP1000是他最好的机会.
Timon说,DIP1000可以说已承担了一些可注解不同级间接的复杂度成本,但一般禁止这样.应有更好的权衡.
Walter说有两种间接:指针和引用.这使得DIP1000的复杂性增加了一倍.Timon同意,但表示即DIP1000不是你在按指针转换所有内容时得到的结果.
DIP1000比这更进一步,因为实际上每个指针都有两级间接性,但不是按正交限制它.根据构造注解任一间接级.
Walter同意,并说这是因为引用有隐式的间接性,而指针则没有.他问可做些什么.
Rikki让每个人都说他们的想法.
Quirin说,他理解DIP1000的目标是你可取局部变量的地址,比如静态数组等,且按域限定指针且无法逃逸.
因此,在DIP1000为默认值的未来版本中,可能会有个编译器开关来禁止它,这样禁止取局部变量的地址.
他说他遇见的问题是,如果有系统函数,但实际上没有按@系统注解它,然后有域注解,编译器会认为你正确处理了域操作.
但如果你不是,你就完蛋了.而意外很容易发生.
这是DIP1000的一个问题.你可在系统代码中坑自己.如果不是在安全代码中做对了,但如果是初学者,没有用@安全注解某些东西,然后使用了它,如,是隐式域的-preview=in,就会遇见麻烦.
所以可有选项禁止它们,但在代码中允许像@安全一样的所有域检查等会很好.
沃尔特说,@系统关闭了所有检查,因为有时需要做一些烦人事情.初学者不应编写@系统代码.Quirin说,如果不使用@safe,DIP1000会使该语言更加危险.
这就是有些人搞不来的原因.
Walter认为最大的问题是人们不喜欢写注解.只在没有函数体时,它们是必需的.如果只是取本地地址,编译器会说,“好的,现在是域指针了”.
它会自动这样.困难在于有两个地方需要添加注解:没有函数体时和在虚函数中.这时,编译器无法自动这样.
Walter说,语言最近有了变化,允许对局部变量使用引用.这允许无需注解,更高的安全性.这是一件好事.它通过减少原始指针的需求来改进语言.
下一步是允许构字段上的引用.必须弄清楚它的语义,但是越能改进语言以减少使用原始指针,它自身就越安全,问题就会越少.
Adam说有人建议不要在打开DIP1000时构建Phobosv3.他有点同意该观点.他前曾告诉Walter,DIP1000不值得.
Rikki想说明,如果没有引用计数,基本上不可能每秒处理100,000个请求.这是由Walter在物主逃逸分析方面的工作所控制的,而这反之又以逃逸分析为主题的.
所以他在这方面被阻塞了,因此想要排序逃逸分析.
Walter说,ROI如此之低的原因是,因为栈中的错误指针,人们很少在程序中遇见易错漏洞.Mathias问为什么花这么多时间在上面.
沃尔特比作飞机失事:它们很少见,但一旦发生,就会造成灾难性的后果.你不可能既是内存安全的语言,又这样.
Mathias说,DIP1000使他不想使用D,因为当他使用vibe.d允许D时,他得到了大量的弃用.这太可怕了.他希望默认不打开.
当谈到DIP自身时,他说该组合就是不管用.需要他在类型定义中使用域注解他的类或结构的设计在到达时都死了.
他说,很多人把它与常比较,这是错误的比较.常是由外到内,但域是由内到外.因此,如果你的外层是常且你组合了一个有多个层的类型,则你的所有层都是常.
对域,情况正好相反.无法在语言中表示域的深度.这在语法上是不可能的.它就是无法工作的.
更新:稍后开会并决定需要做两件事来向前步进:编制一份失败的DIP1000案例列表,看看是否可解决它们;并考虑如何默认推导.
把std.math移动到core.math
Martin说他多年来一直想将std.math移动到core.math.很久以前,在GitHubPR中与Walter的讨论中提到了它,他记得Walter也同意它.
最近,再次试使编译器测试包独立于Phobos.现在,现在DMD和运行时在同一个仓库中,因此所有make目标都是不依赖Phobos而独立的,这样运行编译器测试,那就太好了.
他做了实验,发现测试用例中的大多数Phobos导入都是std.math.一个常见原因是幂符号^^.还有一些测试测试了数学内置函数.
CTFE的编译器使用混杂的函数名,检测到调用标准数学函数.这已是个问题,因为当更改std.math中的属性时,因为新混杂名,也需要更新编译器.
因此,测试了所有这些方法是否有效,而CTFE数学结果符合期望.因此,有隐性依赖Phobos.
Phobos会导入所有内容并转发到core.math,它已在运行时中存在.它当前有大约五个函数.
LDC已转发了一些数学函数.std.math是为数不多的LDC和GDC只是为了可使用内联函数,而有一些修改的Phobos模块之一.
移动进运行时会更好,因为可最小化或清除,Phobos分叉的需求.
Walter说std.math类似一个包含很多东西的手提袋.他建议将应该是core.math的内容移动到d运行时中并转发到这里,然后按使用core.math更改测试包.
他想保存std.math.仍有很多编译器测试包中不需要的数学函数,可在那里保存它们.
Jonathan说,过去当决定真想要在d运行时中导入Phobos中的东西,但真想人们导入Phobos时,就把该东西移到了core.internal.
如,std.traits导入了core.internal.traits以避免重复d运行时中使用的特征,用户仍可通过std.traits来取它.
实际上,std.math中的大多数函数都是由编译器检测到的.
据他所知,std.math是相当孤立的,不依赖Phobos中的其他东西.他会仔细检查,但他确信,所以可把它移过来.
他真不想分开它.如果它在运行时,则直接从那里包含是合乎逻辑的,从某个特定的编译器版本开始,并保存它,在PhobosAPI中呆一段时间以实现后向兼容.
所以最终位置将在core.math中.
Walter说,很简单:如果想在编译器测试包中放置它,它需要进入运行时.Martin说他需要检查,但这会是大部分函数.
Mathias认为尽管不能解决Martin的问题,但应该去掉幂符号.Martin说,移动它到运行时,可清除在未导入std.math时试用它时出错的特例.
沃尔特同意马蒂亚斯的意见,认为应该淘汰它.这是丑陋的.
Adam说,Phobos3是改变的绝佳机会.这是自然的分界线.可保持标准库2的原样并长期支持它,但Martin可在标准库3中为所欲为.
Adam已在看std.math并思考他有多害怕移植它.因此,如果Martin想出其他东西并告诉他如何让它有效,他就会让它有效.
主要类型语法DIP
Quirin和一起讨论了他的.1及2.
基本思想是,不更改语义等修改语法.它为了确保可由错误消息表示的任意类型,(如)也可在代码中表示,且你不会收到解析错误.
Quirin说他已为该提案提供了实现,且按期望实现引用.他已试了很久,并真正试突破了一些极限.他没有发现问题.
他说,同样问题也适合链接.像一个带extern(C)链接的函数指针.
他说也许Quirin已解决了它,但要求他检查一下语法和括号问题,并确保提案没有这些问题.
Walter说,在编译器测试包上试它将很好.奎林同意.
“让printf安全的DIP”
Iain说,现在是2024年,人们仍在发明新的CPU.他说中国人发明了他们自己的MIPSCPU,他们不得不把旧的GDC版本拖出来,并移植到他们的CPU上,只是为了让LDC和DMD可正常工作.
这是另一个崭露头角的现代芯片(龙芯).让这些人对拥有现代版本的D编译器而不是C++编译器满意,这样他们就可跳到最新版本.
因此,较旧的bootstrap版本完全无价值.
沃尔特说好.确保D编译器源码的安全并不重要.这只是他想做的事情.但是,如果会导致很多下游问题,则当然,我们还能做什么?
Iain说必须让文档非常响亮和显式.GDC在这方面做得很好,它解释了如果从给定版本的编译器开始,你必须做什么,因为某些版本的GDC是使用特定的C++标准编写的.
要取得最新版本,必须从起点开始浏览这些版本.也应该同意,对DMD同样.
Rikki说明,Elias已完成了LDC的新docker版镜像,该镜像完成了从LTS版本到最新版本的引导.他说应该可按C++代码基转储编译器,然后用来引导相同编译器版本.
他已考虑了很久了.这在今天不是问题,但未来会变成一个问题.
使用printf真很简单.这只是一个调用函数:在栈上压几个参数,调用一个函数,完成.
Dennis问,是否为DMD创建了writeln的最小模板版本,因为DMD大多只连接串,偶尔会构成一个整数.Walter说可编写自己的printf,但C标准库中的那个是经过实战检验,调试和优化最多的.
Dennis强调只需要连接串.
Johanthan建议把它包装起来.
他同意Walter所说的writeln有问题,因为它是模板的暴风雪.但他不断从人们那里听到不应删除这些模板.
Walter重申printf受到了很大的恶意,但它是历史上调试,优化最多的函数.也许可实现一个只是调用安全转发到printf的writeln.
它有它的问题,因此提交安全printf提案.
他说Jonathan是完全正确的,模板给writeln带来了很多好处.他不是在反对它.但是在试调试编译器时,处理writeln是个巨大的痛苦.
因此他总是回到printf的原因.他不想编译器依赖writeln,因为那样无法引导编译器.
Jonathan同意不想DMD依赖标准库.此时,也许用带串并按C串的东西转换它来包装printf是可行的.
Walter说这就是安全printf提案的作用,它只是让编译器覆盖printf式以使其内存安全.Jonathan说可避免直接使用包装器调用printf.
总之,编译器与一般情况不同.
空初化一个引用变量
Dennis问大家是否都同意空初化引用变量应该是一个错误.DIP没有具体说明,它没用例.沃尔特说那是个错误.没人反对,这里.
域和自动引用
Dennis问大家是否都同意变量上的auto ref关键字必须放在一起,而不是与不同域内的关键字一起使用,如auto { ref int x = 3; }沃尔特说是的,干掉它.
Quirin说他注意到,在查看语法时,动和引用并不总是需要彼此相邻.如,可在参数列表中编写ref const auto foo.他建议应该禁止这样.沃尔特说应该弃用它.











![[x86 ubuntu22.04]投影模式选择“只使用外部”,外部edp屏幕无背光](https://i-blog.csdnimg.cn/img_convert/cb1c194defe86e2e7bf832b8c441fbcb.png)






