亚当
独立静态构造器
首先,背景.在6月
月度会议上,讨论了,导入
其他模块时,即使静态构造器
自身没有依赖
关系,也可能会进入循环依赖
,执行也会因"检测到循环
"错误而中止.
Adam
建议引入可在静态
构造器上使用的新注解
,以告诉编译器它没有依赖项
.然后,在关闭
检查循环依赖项的单独列表
中,编译器可添加
进它们.
Walter
说,已有了pragma(crt_constructor)
编译指示的机制,指定启动时C运行时
执行的函数.亚当提醒沃尔特,上次讨论过该问题.
问题是CRT
构造器是在初化D运行时
之前执行的,因此依赖D运行时
的静态构造器都不能是CRT
构造器.
沃尔特问如何实现.亚当说,实现已在D运行时
中.Steve
澄清说,编译器有时候可决定单独
的静态构造器不参与检测循环
.
不需要按指定
顺序运行这些构造器
,这样来分开处理.这就是亚当
所指的.因为已有让编译器标记独立静态构造器的方法
,只是要求用户可按独立
标记构造静态器
以进入同一列表
的方法.
Walter
说,他过去曾向人们建议,避免静态
构造器上的循环检测的方法是,无需
额外导入,把它们放在自己
模块中.然后它们将是独立的.
亚当说这是不现实的.沃尔特说,他对亚当想法的抵制源于不愿意改变
语言来做其他
方式可完成的,也许不完美,但至少合理.
另外,是否可在不向语言
添加新功能时就完成?
沃尔特还指出,允许这样会给语言增加不安全感
.他们可能会误认为静态
构造器是否有依赖项
.它可能在A系统上工作,而在B系统上中断,因为无法保证
它的运行顺序.
构造器排序背后的整个想法是不必了解按什么顺序运行.
至少,此功能必须隐式@system
.则是否有其他方法?是否合理?
Walter
接着问Adam
有多少次发现程序
中明显需要独立
的构造器.亚当引用了他的"JNI
互操作".它生成其他静态
构造器,来向Java
运行时注册类
.
这是独立
的,但因为它是由mixin
完成的,所以它不能在自己的模块
中启动.因此,如果可按独立
标记,则可避免循环检测
.
Walter
想知道为什么不能在单独
模块中放置mixin
.除此外,Steve
强调,为了避免循环检测
,到处都是这些小模块
会使代码更难读,并让语言
更难吸引人.
在这一点上,静态
构造器似乎无用.
最后,Walter
说他想保留意见,直到能看到一些示例代码
.
Adam
提到的mixin
旨在在类内
实现静态
构造器,而不是在模块
域内,这样就无法在独立模块中放置它们
.
长期版本
现在变化
是除非
真的必要,不会弃用
.表明会继续支持旧事物
.目标是不用更改
及烦人的消息,所有库
都可使用新的DMD
编译.
他一直在稳步发布PR
,来恢复
一些给人们带来麻烦的弃用
.计划恢复过去故意
破坏的清单.想法是,一旦一个库
在D中工作且已调试好,除非是重大
错误,它就会继续在D中工作.
沃尔特说,这就是未来
计划.它合理地解决了像GrimMaple
那样的不能编译投诉,且不需要LTS
.LTS
在如何修复
编译器中确实破坏
现有代码的严重错误方面也存在问题.
这是个难题.有想要修复
但又不想破坏
现有代码的错误时,LTS
和head
版本也面临
同样决定.
沃尔特认为这是合理
的方法.表明可能不需要LTS
版本,解决人们在编译器的每个新版本
中因代码
中断而遇见的问题.不想再这样
做了.
我提到Walter
为此添加了-wo
开关,这样你想知道代码基
是否在使用过时
功能时,可打开它.还注意到,上周季度会议上,讨论
了提供更精细
控制,以便可为代码基
而不是依赖项
打开警告.
这样,可查看是否正在使用过时
功能,而不会因依赖项
的警告而使输出
混乱,且这一切都是选入
的.当然,仍会有弃用
.
沃尔特说,想法
是为了长期
支持不再需要
的功能.如果用户
想要升级
他们的包,且有时间按他们
的而不是我们的时间表更新
,可打开-wo
开关以查看他们应该及时步进
的所有事情的列表.
尼克
对-wo
开关有一些评论.他说,这很好.但是,因为默认
没有指示代码是否使用了过时
的功能,如果人们可养成使用
新开关的习惯,那就太好了.这是文化.
沃尔特同意这应该是文化的.他在(GCC)
中注意到了这一点.C
有些非常糟糕的特性,但GCC
默认不会警告它们.
用户必须
打开警告.对他来说似乎没问题,而且对GCC
这似乎工作.
我注意到,如果要使-wo
开关细粒度化
,也应该对-d,-de
和-dw
同样.沃尔特问人们是否真关心它是细粒度
的.
我提醒他,来自Ahrefs
的Igor
在一周前的季度会议上提出了该问题.约翰
指出,这很重要,因为当有第三方
的依赖树时,当他们做一些旧的,过时的和垃圾
的事情时,你不会想进入
,并改变它们.
你不会强迫
他们改变.你确实
想编译器告诉你代码中的部分,且不想被干扰
.
沃尔特说,他想过给开关
加个只针对命令行上传递的文件发出这些警告的限定器.仅针对根模块
,而不是导入
的.
这样,可导入其他人的库,他们不会打扰
你,但你会得到关于你正在积极编译
的东西的警告
.这就足够了.John
说,这方便构建
系统整合.沃尔特说这是个非常简单
的想法.
史蒂夫说,他看到的唯一问题
是,如果你依赖一个也想为该库
启用警告的库,你构建库,然后进入你的代码,且代码使用了该库中的模板.
是否有警告
?因为你没有在命令行
上传递该模块,只是导入
它以使用其模板.Walter
说,如果警告是来自非根模块
模板的结果,你不会收到警告
.
史蒂夫说,他只是想看到警告
,但不能.Walter
说编译器已对弃用
类似做了.如,如果为同样
已弃用的模板
生成弃用
消息,则不会看到该模板
的内部弃用.只会在使用模板
时看到弃用
.
史蒂夫
在上一次月度会议上,他谈到了编译时
关联数组初化到编译器中.运行时部分
已工作了,只需要有人
来处理编译器方面.
在和丹尼斯讨论之后,丹尼斯提出了替代方法的公关.
沃尔特说,他看到用户抱怨DMD
已在Mac
上停止工作.他知道ldc
已解决它.
史蒂夫说他只是报告
并测试了它,其他人已修复
了它.他说这与Mac
上的链接器
突然对目标节
布局更严格有关.
沃尔特说,DMD
不在Mac
上工作是不可接受的,并查询丹尼斯是否可盯着它.丹尼斯说他对Mac
一无所知,史蒂夫说有很多Mac
用户可帮助测试或构建.
如果需要,他提出可远程
访问他的旧x86Mac
.沃尔特说,他感谢这方面的帮助.
LDC
的修复.
拉兹万,BetterC
链接器错误
拉兹万提出了过去会议上讨论过的话题.
错误
跟踪器中有一些使用BetterC
时的链接器错误
相关问题.一般,实例化运行时勾挂
或从D运行时
导入内容
时,如果从运行时
推测环境,及从BetterC
代码使用相同参数
实例化模板,则可能不会发出模板
.然后得到链接器错误
.
解决方法是使用-allinst
编译.Razvan
说他已提出了一个拉取请求
来解决该问题,这样现在使用-betterc
编译就隐式表明有-allinst
.但会导致一些项目的编译
速度变慢.公关,马丁这没有问题,但拉兹万想知道会议中是否有人觉得不好.
Walter
问为什么不能告诉人们,把-betterc
和-allinst
一起使用.Razvan
说,即使这样,人们也不会知道这件事,所以会以同样没有信息
的链接器错误结束.
沃尔特承认这点,但他说如果把两者
结合起来,则有一天人们会问没有allinst
的-betterc
.
Steve
建议可有一个-allinst
版本,允许指定应该只实例化指定
模块的模板
.如根模块
,或核心
等.沃尔特说这是有可能的.
Walter
另外建议不要让D运行时
实例化自己的模板
.让它使用不同
模板.然后编译器会认为它们没有被D运行时
使用.
它应该只是少数
模板.罗伯特认为这不行.史蒂夫说这不仅是运行时
.模块
都可能这样,即使是那些不直接
导入的模块.
如,模块
不是公共API
的一部分,但在私有内部API
中,它恰好
实例化模板.很难回答何时实例化
及编译器决定不发出它的原因
.
沃尔特说,拉兹万应该继续他的方法.他想有个更好
的方法,但这是目前唯一
的方法.
Steve
说,公平地说,BetterC
是指定不链接运行时
的开关.它也可说它不会从那里
实例化模板,因为它没有与它链接.
Dennis
指出,BetterC
用户想要越来越多
的东西与BetterC
一起工作.可告诉他们,它应该是为了用现有的C
整合项目
新代码及一些利基
微架构,但他们仍只是想在BetterC
中可以比较数组
.
Walter
认为他已修复
串比较,所以现在应该可工作了.
Razvan
说:在BetterC
中,编译器只为运行时勾挂
假设-allinst
.这有效,但似乎有点笨拙.
沃尔特开玩笑说,-allinst
自身也有点笨拙
.然后他说拉兹万的最初想法是正确的,拉兹万应该继续他的公关.
丹尼斯
安全错误和-wo
丹尼斯首先指出,沃尔特一直在-wo
开关后面移动
安全错误.他发现这有点麻烦,因为安全错误
并没有过时.告诉用户,如果想要适当
内存安全,必须启用过时警告
检查听起来很混乱.
1
2
丹尼斯说,他知道当前默认
弃用泛滥很烦人,但如果想默认达到DIP1000
,它需要.否则,为什么仍要DIP1000
和内存安全?
Walter
说,在第一个链接中,有一个来自dlang-tour/core
的BuildKite
错误,这是关于弃用域
消息的暴风雪.
不必打开-preview=dip1000
.它们默认.问题是,人们现有的工作
代码,他们添加了域
,现在已破坏了他们所有
的代码.
丹尼斯说它没有坏,这只是个弃用
信息.沃尔特说,dlang-tour
已坏了好几个星期,还没有修复.这正是-wo
要解决:人们使用的库破坏
了,但没人愿意修复库.
丹尼斯说它并没有因此而破坏.这只是个警告
.因为超链接
不管用,它才破坏了.Walter
说,他看到的只是赋值域
参数给非域
参数的各种消息.
丹尼斯说,这并没有破坏构建
.破坏构建
的是一个未正确解析md链接PR
.这就是它失败的原因.
沃尔特说他明白了.重点仍是仍存在弃用消息
暴风雪问题,并说未来不会编译
此代码.丹尼斯说这是事实,并问是否不想步进DIP1000
.
Walter
回答说,确实想继续使用DIP1000
,但也想编译较旧
的代码.他强调,他了解丹尼斯的来历,两三个月前就会完全同意他的观点.
但是他现在认为,即使正确,现在只是破坏
了人们使用域
的现有代码.是的,他想默认移动
到DIP1000
,但他不想破坏现有代码.这就是-wo
的目的.
编译器会接受在现代D
中不可接受的代码,因此仍可用旧代码
.在曾经工作并且正确
的旧库上,没人愿意看到满屏
弃用消息或彻底错误.
只因为编译器想要更严格
标准.沃尔特认为需要放宽
这些标准.
史蒂夫说,弃用消息暴风雪的部分
问题是,其中很多都是很简单
的.如,此模板
现在按@safe
推导,但默认启用DIP1000
后,它按@system
推导.
因此,可能并没有真正
从安全代码
调用它.因此,即使稍后会按@system
推导,但不会影响项目
的编译.
Walter
谈到了推导安全
的实现细节,然后说人们使用域
并期望它起作用.它管用了.只是随着D的现代
版本和想要前进
的方向,这是个问题.
但是为了支持
较旧代码,需要行为
方式与一直默认
的相同,以便使用这些构造
时不会干扰不安全
.这就是重点,停止破坏
用户代码.
John
说,还有D
无法构建,或人们编写D无法创建封装
代码.考虑你未来要继续
使用的C库.C
库喜欢公开
相对有限的接口,但内部,可做各种疯狂
的事情.
但是你可相信该接口
,因为它已经过调试
.因此,对它打开新的警告标志
很烦人.但是在D中,模板
和mixin
方向不同,而内省更全面.
人们可构建一个库,调试
它,且用户
未来可信任
它.虽然他支持-wo
开关,但这稍微削弱了它的论据.
如,如果依赖项
未遵循DIP1000
的规则,则表明你可能未遵循规则
.如果传递类型
给模板,然后相应再传递给另一个
模板等,则很容易这样.
沃尔特说他理解约翰的意思.Walter
说-wo
是为那些对正在编写
代码有更高
标准人准备的.如果使用它,编译器会告诉你你正在导入
库的所有错误,你可决定如何处理它.
是否要使用10
年前的该库,即使编译器也无法保证
它是内存安全的,让用户做出选择.约翰承认只能这样了.
Walter
指出,不这样做时,C
编译器会为你隐式
声明一个函数
.这太可怕了,因为它默认带某些参数和返回值
.
所有这些都是隐式
的,即使它可能只是拼写错误
.编译器仍会毫无怨言
地编译它,因为人们有很多他们不想修复的旧C代码
,但他们确实想按过去方式来编译
并工作.D
需要同样.
我仍在试了解当DIP1000
成为默认值时会怎样.他正在恢复其他弃用,并放在-wo
的后面,因为它们是删除.
而没有删除域
.这是过渡,警告DIP1000
为默认时,行为
变化了.真的默认
时,这突然
是个错误,会破坏所有旧代码
.
要把DIP1000
放在-wo
后面吗?
沃尔特说他没有看到其他方法.它会放在-wo
上.我说那样,就不是默认的.约翰说这听起来很像语言版本,我同意.沃尔特说,想要安全
的人会启用-wo
,而那些不想要安全
的人不会.
Dennis
说目前还可用-preview
和-revert
.他觉得现在很多
事情只是改变
消息颜色,改变是否是默认
的.
如果来回这样做,它只会一团糟.首先,你需要-preview=dip1000
,然后你需要-wo
,然后当人们想要默认
的内存安全
时会怎样?我同意在没有硬边界
时,很难默认获得DIP1000
.正如约翰所说,需要版本
等,因为变化简直是惊天动地
的.
John
问为什么假设关于过时
功能的警告应该选入
来打开它们,而不是选出
以让编译器闭嘴
.我说这是因为收到了很多关于弃用
消息的抱怨,现在,你必须选出
.
John
问是否考虑过这是否与它们是弃用
消息的事实有关,所以编译器告诉你"当心,必须改变它,否则会破坏
你的代码",而不是"嘿,这里有一堆错误方式,但你可忽略它们".
因为弃用消息
,是你知道不应忽略
它.而未来会破坏
.
马丁一直在抱怨Symmetry
代码基的域弃用
问题,因为在Symmetry
代码外的依赖项中有很多域
.
这是阻止升级到较新
编译器版本的原因之一.丹尼斯说,这可通过过滤
模式为弃用
和警告开关
来解决.
约翰说,有时候这就足够了.
Walter
说他记得Sociomantic
花了大约10
年的时间来从D1
升级代码.他们投入大量精力编译旧代码
.
他不想再这样了.如果无法升级
到最新
编译器,则不必强迫.
丹尼斯说这就是-preview
和-revert
的用法.
我提醒大家,并不是完全
丢掉弃用.域
是个应该保留它的完美示例.只要有像-d
此类过滤弃用开关
,则用户可为自己
的代码打开
弃用,而对特定包
关闭它.
Mathias
说,Sociomantic
之所以在D1
上停留的时间最长,并不是因为暴风雪般
弃用,而是因为从D1
到D2
没有明确的升级路径.
这只是个艰难
突破.他们必须过渡.他们确实移植Tango
到D2
,因此不得不从运行时中分离出Tango
来.
他们必须编译D1
和D2
代码.
沃尔特说他不想再有类似事情发生.
弃用域
当然是侵入
性的,但许多其他弃用
不是.他过去曾建议分组
弃用,如每两年
只发布一个弃用
版本.
但冻结
语言只是在消亡.甚至Rust
每年也会更改一次语言.
Walter
说他被告知Rust
仍会编译旧代码.我说理解是Rust
有"时代
"的,想法
是,需要升级
的新功能集之间有明确的界限
,但仍可编译旧代码
这里.
我说,需要定义
并记录
如何处理弃用
,如何处理过时
功能及如何处理像DIP1000
等巨大突破性转换
的清晰路径.
马蒂亚斯说,这已很清楚了.弃用
持续十个版本.一些弃用
持续时间更长.如,body
弃用是二十个
版本,因为它非常有影响力.
但从不硬性
破坏,或至少
非常努力避免它.因此当决定需要用DIP1000
前移时,Dennis
做了默认DIP1000
打开时,把看到的未来
错误转换为弃用
消息的有影响力的工作.
因为否则,无法默认
启用DIP1000
.如果不允许
这样,则不能默认
打开预览
开关.
我说弃用域
只是过渡,需要为该类事情制定策略
,以便可知道在做什么.
拉兹万说,最近不弃用
不是正确
的方向.是的,发出太多弃用消息
不好,但没人说再也不弃用
.
弃用
过程是正确的.主要是弃用
了太多,但该过程自身是有效的.也许应该限制
给定时间段内弃用
次数.因为如果冻结
语言,这会是一个大问题
.
沃尔特说这些都是好点,但他强调并不打算永远
不弃用.想做的是逐个
查看,并决定是否真的需要弃用
它.
如,消除逗号式
的原理,是可有合理元组语法
.弃用它,没关系.但是还有其他,比如body
关键字,弃用了它,转而支持do
.
但表明,可在语言中按环境关键字
保留它,且效果
很好.即使不是语言
的官方部分,也可永远
支持它.然后-wo
可告诉你,嘿,为什么不改变
代码中的body
为do
?或用分号
弃用空语句
.
在这方面破坏代码
不是好主意.把它留在里面不是问题,所以他有个PR
来重新启用它.唯一困难是DIP1000
.
我说我完全支持他恢复所有这些,但恢复域
是错误的.沃尔特说,还应该考虑到DIP1000
还不完美.它仍有错误.
是否真想在解决
所有错误前开始弃用
它,且可自信地说应该在所有代码上使用DIP1000
?也许当DIP1000
更完美时,可重新
审视这一点.
与此同时,他想继续两个把域
的东西放在-wo
后的PR
.与域
构造器一样.他发现必须这样做时,知道这有破坏性
,因此他预先为DMD
中的所有构造器
添加了域
.
但是为用户
启用此功能
对他们来说是非常有破坏性
的.
丹尼斯说他明白了.他不介意说有点预先
,暂时关闭弃用,更好
状态时重新打开
它们.问题是把它们放在-wo
后面.
这没用,如果根据DMD
版本及使用标志
,收到警告和弃用或错误
,只会在版本
间切换
状态时造成混乱.
所以宁愿暂时禁止弃用
,而不是放在-wo
后面,也许在它更好
状态时启用它.否则只会收到用户
对混乱开关
的抱怨.
史蒂夫说,他一直在通过构建vibe.d
来处理域
相关弃用消息
.他看到消息说因为调用了标准库
深处的另一个函数
,不能叫该函数
安全.这不应该.
在标准库
支持它前,不应启用
它.沃尔特同意了.他说标准库应该与DIP1000
完美配合.这很明显.
因此,问题是,是否只是像Dennis
建议的那样暂时禁止域弃用
消息,还是像Walter
想要的那样把它们放在-wo
后面.
史蒂文同意应该禁止
.沃尔特说,把它们放在-wo
后面是禁止
它们的好方法.丹尼斯不同意,说这没有意义
,因为它不是过时
的功能.
沃尔特说丹尼斯在语义
上是正确的,但务实
地,这很好.丹尼斯说,用户过去曾抱怨开关
做其他古怪
的事情.
空初化布尔值
丹尼斯还没有说完.他的最后一项是他提交的PR
这里,该PR
在系统变量预览下,按@system
标记,布尔值或包含布尔值的空初化
.
如果使用bool
索引,编译器喜欢避免
检查边界,因为它知道它只能是0
或1
,但是当按void
初化bool
时,可能会比这更大,且可能会破坏内存
.
他说,有一些不同
意见.一个是每个void
初化都要@system
,但这是个更大
的突破性变化,不大会这样.
或按有不安全
位模式类型对待bool
.沃尔特说他要考虑一下,并感谢丹尼斯提出来.
Iain
说,在GDC
方面,直到最近,都按1掩码所有读布尔
.他已撤回了它,现在仅当是联
内部某个
字段的读取布尔
时,才这样.
Dennis
同意这是DMD
有时候的另一个选择,但它的性能较差.如果想要高性能且安全
的布尔值,最好处理void
初化.伊恩说,性能
也是他撤回它的原因.
沃尔特重复说他必须考虑一下.
沃尔特
除此外,他还专注于错误修复
,浏览弃用列表
,并研究在DMD
后端添加对ENDBR
指令的支持.
我问Walter
,他在支持DLL
和文档方面是否有进展?.在六月的月度会议上,他说在调查编译器中DLL
支持的当前状态,并写了一篇文章来记录
他的发现,并试完成缺少的内容.
沃尔特说,他有个与DLL
相关的停滞中的公关,所以转向了其他事情.但是,他在网站上发布了一篇文章,他打算在实现
上可有更多进展
后扩展.