​Martin​​:​​LDC​​已准备好​​下个主要版本​​.

改变​​extern(D)​​调用约定,不再​​反​形式参数.直到最近,​​DRuntime​​和​​编译器​​间还有​​相互依赖​​.当有人修复​​矮人​​发射时,尤其有问题.

一个问题是,带​​多个参数​​​并假定​​参数​​​在特定​​寄存器或栈槽​​​中的裸​​asm​​​函数会​​中断​​​.必须改变​​Phobos​​​,使​​LDC​​​的​​Phobos​​​和上游​​Phobos​​​间有差异.如果​​DMD​​可效仿,那就更容易了.

伊恩

弃用

​Iain​​一直在结束​​已弃用和遗忘​​弃用期,并为没有的​​弃用功能​添加​结束日期​​.他重复了几个示例,其中一些现在是错误的.​​Walter​​查询了​​复类型​​的状态.​​Iain​​说已弃用他们了,但现在还有一个日期.

在这次讨论中,​​Iain​​记得他想在​​std.complex​​中加​​toNative​​.尽管​​库实现与C类型​​是二进制兼容的,但具​​两个双精​​结构可能不像​​C复类型​​那样​​按参数​​传递.这时,该​​toNative​​函数可确保兼容.

域结构

​Iain​​​在迭代弃用功能中提到​​区间接口​​​.这导致了​​域构​​​和​​域类​​​类型的对话.在实例级​​scope foo=new Foo​​​成为公开强制​​栈分配​​​前,它开始作为​​类型声明​​​的一项特征,如,​​域 类 Foo{}​​​,含义是所有​​Foo​​实例都在栈上分配.

这有​​组合​​​问题(如果​​类型​​​成员是​​scope​​​类型,则该​​类型​​​也是​​域类型​​​).最终,每个人都同意弃用​​域类型​​​.(从那时起,已经合并了两个​​PR​​​,它们不赞成​​struct/union​​​和​​enum​​​声明及类声明的域,​​这里​​​,与​​这里​​).

​Martin​​​查询​​Iain​​​在上游提交的一系列​​PR​​​,​​Iain​​​回答说他一直在​​测试​​​各种目标(​​BigEndian​​​目标,​​严格对齐​​​目标等),导致他在​​DRuntime​​​中发现了一些​​回归​​.

更改​​DMD​​词法分析器

​Razvan​​​召集了几个学生,致力于将​​DMD​​​集成为​​dscanner​​​的库.​​替换​​​出现的​​libdparse​​​,但表明他们需要​​修改​​​前端,来提供与使用​​libdparse​​​的工具所期望的​​接口相匹配的接口​​.

第一个变化是为​​词法​​​分析器创建​​区间接口​​​.​​Walter​​​要求移动​​区间接口​​​到​​新模块​​​,而不是对​​词法分析器​​​搞侵入性的更改.​​Razvan​​​说这不是问题,但确实需要更改​​词法分析器​​​.具体来说,​​DMD​​​会删除​​空格,换行符和注释​​​,但​​libdparse​​​不会,因此需要​添加​​代码到词法分析器中,以便​​DMD​​​用作库时不会删除它们.​​Walter​​​建议尽量为​​新代码​​​前端创建​​libdparse​​​模块,以避免​​加版本化块​​​到​​词法分析器​​​.拉兹万​​同意​​.

​​DIP1008​​和火卫一

在他的​​SAOC2021​​​项目(用​​模板​​​替换​​DRuntime​​​勾挂)中,​​TeodorDutu​​​遇到了​​有时​​​替换​​抛出异常​​​的勾挂会​​导致​​​链接器错误(这与混合使用​​不同开关​​​编译对象时的​​模板发射​​​有关).前进的唯一方法是使用​​-dip1008​​​编译​​d运行时和d标准库​​​.可惜,​​DIP1008​​​要求在抓到​​异常​​​在时不能逃出​​catch​​​块,但​​Phobos​​​有时通过保存​​异常​​​到​​变量​​​或​​返回异常​​​来完成.这避免了用​​-dip1008​​编译.

​Razvan​​​说如何解决,不明显.​​克隆异常​​​要求用户​​释放内存​​​,不好.​​-dip1008​​​此外,当启用​​分配栈跟踪​​​时,​​DRuntime​​​仍用​​GC​​​分配异常(正如​​Razvan​​​在他于​​2019​​​年提交,现已关闭的​​PR​​​中首次发现默认启用​​-dip1008​​​,​​这里​​).

​Martin​​​指出,​​跟踪拆解​​​时也用​​GC​​​.对此,​​Walter​​​最终要求​​Razvan​​​确保存在与​​Razvan​​​的​​PR​​​相关联的​​Bugzilla​​问题链接.

引用计数

通过旧的​​DRuntime​​​拉取请求,​​Razvan​​​发现几个​​PR​​​添加了​​引用计数​​​的东西(​​RCArray,RCPointer​​​等),当时​​引用计数​​​是​​D社区​​​的热门话题.​​D​​​中​​引用计数​​​的问题在​​限定符的传递性​​​(如,不能​​引用计数​​​不变对象).​​Razvan​​​记得他为​​存储类​​​起草了​​DIP__metadata​​​,​​这里​​.

在关于​​DIP​​​的论坛讨论中,​​TimonGehr​​​指出了它的两个基本问题,​​这里​​​.最终,​​Razvan​​​的进展停滞了,未提交​​DIP​​.

会议上,说想听听社区现在对该​​DIP​​​的看法,但想先知道这是否​​仍然重要​​​.涉及​​引用计数​​​和​​不变​​​的各个方面讨论:更严格形式的​​C++​​​的​​mutable​​​(以类似​​__metadata​​​的形式:不是​​类型|对象状态​​​的一部分,可能​​存储​​​对象指针前等),为什么允许从​​pragma(crt_constructor)​​​修改​​不变变量​​​是不好,用​​extern(C) shared static this​​​替换​​pragma(crt_constructor)​​​的利弊(反之,在没有​​DRuntime​​​时允许​​初化​​不变).

使​​malloc​​和​​calloc​​为​​@trusted​​

​Razvan​​​接着提出了两年前的​​DRuntimePR​​​,​​这里​​​,用于使​​malloc​​​和​​calloc​​​为​​@trusted​​​.本打算合并它,但​​Iain​​​删除了​​automerge​​​标签.​​Razvan​​​问为什么不能合并.​​Iain​​​说最后一次​​评论和应用​​​自动合并之间有​​20​​​个月的时间.​​PR​​​有很多讨论,所以​​Iain​​​想给它一些时间来消化它,并在​​必要​​​时重新开始讨论,以防止问题,但​​两周​​后发现有问题.

于是​​伊恩​​在会议上​​触发​​了新的讨论:​​malloc​​真的值得信任吗?对此有很多意见:从中得到了什么?两者都需要​​不安全​​的​​无类型​​内存换;​​calloc​​更强,因为它初化了内存;​​malloc​​特定情况下可能是​​安全​​的,如在​​原位​​时;或无​​类型​​时可能不是,因为它不带​​类型信息​​等等.

最后,​​Andrei​​断言​​malloc​​和​​calloc​​是不安全的,因为他们使用​​无类型内存​​且无法绕过它.​​Walter​​建议添加​Andrei​​的答案到​​PR​​讨论中,并且​​PR​​已关闭.​​Andrei​​提议在​​PR​​线程中陈述该论点,但不关闭它,以便有人可提供​​引人注目的代码​​示例来展示如何使​​malloc​​可信任.

​Razvan​​这样做了,触发了更多讨论:

​讨论​

最后,沃尔特做出了最终决定:

​决定​

丹尼斯,科佩尔

​Dennis​​要求澄清几个​​相互矛盾​​的​​PR​​规范,这些​​PR​​旨在澄清过大的移位(如,移动​​33​​位​​32​​位值)会怎样.

​沃尔特​​解释说,这不是​​未定义​​行为(可能导致"发射核导弹"或其他东西),但​​比这更软​​.它要么会变成​​0​​,要么会​​包装​​,所以它应该是"​​实现定义​​".

丹尼斯问马丁这时​​LDC(LLVM)​​​优化器做了什么(基于​​C​​​).​​Martin​​​说​​LLVM​​​文档指定其为​​毒值​​​,在相同的​​文档​​​中定义,有时可能导致​​未定义行为​​​.​​Walter​​​指出,​​编译器​​​可选择​​删除​​​指定为​​未定义​​​行为的代码,对​​过度移位​​,这不对.

普遍认为"​​实现定义​​"是要走的路.

带域的栈上数组

在许多情况下,​​Mathias​​​都希望可用​​scope​​​来在栈上分配​​动态数组​​​,就像使用它在栈上​​分配类​​​一样,如,​​scope c=new MyClass​​​.他按​​类型安全​​​的​​可变​​​参数函数包装​​分配​​​,但你不能​​连接​​​它们.沃尔特说很合理.​​Dennis​​​已打开了​​Bugzilla​​​,​​这里​​.

​Mathias​​说,如果他有时间,可考虑实施它.

-preview=in

同意启用​​-preview=in​​应该是​​默认​​行为,但应该总是暗含​​ref​​而不是让​​编译器​​决定.​​上次​

同​​extern(C++)​​工作是个问题.​​DRuntime​​中的标准​​C++​​绑定与​​DMD​​测试套件中的​​绑定​​间存在些差异,因此把内容放在​​DRuntime​​中.他指出,包含​​DRuntime​​和D​​前端​​的​​单个​​存储库会很有用.

另一个问题是​​in​​​用作​​opApply​​​中的​​闭包参数​​​,​​in​​​也必须与​​foreach​​​变量一起使用.沃尔特说​​有道理​​.

推导​​闭包参数​​的存储类

推导​​闭包参数​​​存储类,更易写代码.指出了​​Bugzilla​​​中的老问题及​链接​​的讨论线程(后面2个链接),对​​闭包参数​​​是否应推导​​ref​​​有不同意见.那些想要的,按​​C#​​​中的调用点考虑​​ref​​​,但在D中,​​不是在调用|而是在闭包​​​中的参数上使用它.​​Mathias​​​没啥用.它阻止​​传递闭包​​​给默认值为​​ref​​​来避免复制等的​​std.algorithm​​.

​这里​​​与​​这里​

​Mathias​​​很想要这个,但因为​​重载​​​时"​​有点棘手​​​"而推迟了它,但他认为这是​​应拥有​​​的.可在​​邮件列表​​中讨论.

​​-checkaction=context​​应该是默认值

让​​-checkaction=context​​​为​​默认​​​对语言有益,但目前已被破坏.可惜,最近​​一次变化​​​以​​不同​​​的方式打破了它.应为此找到​​解决方案​​​.该​​功能​​​很简单,一旦开始​​使用​​它,你就回不去了.

​Dennis​​​指出,不使用的​​一个​​​原因是,它会​​增加编译时间​​​,而​​Mathias​​说这不重要.

推导私有函数属性

​Mathias​​​认为​​推导私有​​​函数很好.当前​​阻碍​​​是​​属性推导​​​不适用于​​递归​​​函数.他认为解决方案很简单:应该假设​​函数​​​具有​​所有属性​​​;如果​​递归​​​,其余代码帮助​​推导属性​​​.沃尔特说​​有道理​​​;可​​推导​​属性越多越好.

​Andrei​​​指出,如果添加来​​可扩展​​​属性,应该小心,因为这会阻止​​它工作​​​.他还提到,由于可能的​​栈溢出​​​,关于​​递归函数​​的安全性,可能有很简单的论点.

​Martin​​​建议需要评估​​编译时成本​​​.沃尔特说这是​​合理​​​观点,但认为只能忍受它.有这么多属性,推导越多,​​用户体验​​​就越好.​​Martin​​​说,只要编译时间不​​加倍​​,就可了.

​Andrei​​​指出,已经有研究,如​​Java​​​,表明人们一般​​不编写​​​属性.更多​​推导​​是要走的路.

别名

​Mathias​​​说过早地在​​编译器​​​中​​解析别名​​​,导致丢失了​​别名赋值​​​的名字.如,在​​错误消息​​​中,你看到的是​​别名​​​,而不是​​别名自身​​​.它还会造成​​可见性​​​问题.有时想为​​私有​​​设置​​公开别名​​​,但不能这样,因为​​编译器​​​可直接看到​​别名​​.

​Walter​​​说​​可见性​​​是特性,而不是​​错误​​​.这是深思熟虑的决定.允许​​私有符号​​​的​​公开​​​别名违反了​​封装​​​.​​Mathias​​​提供了他​​公司​​​的用例,在该用例中,他们想在​​结构体​​​中隐藏私有的​​getter​​​函数​​aliasthis​​​,即允许​​子类型化​​​但禁止直接访问​​getter​​​.​​Walter​​​认为别名允许直接访问​​getter​​​,并在​​类型系统​​中创建漏洞.

​Mathias​​认为它都必须在​​同一个模块​​中完成,并且由于在模块域内​​private​​,认为不会​​破坏封装​​.

​Razvan​​建议,如果有人想在​​公开别名​​后面隐藏​​私有符号​​,他们应在​​公开​​函数中包装​​私有事物​​.​​Walter​​同意了,要求示例.

阿里

​Ali​​说他设法换他的一个程序为​​SSH​​,复制​​自身​​到服务器并像​​rsync​​一样工作.

​Ali​​的一位同事是​​Rust​​爱好者.他们要火拼.

沃尔特

ImportC

​Walter​​​报告说​​ImportC​​​进展顺利,他修复了一堆​​ImportC​​​错误.可惜,有些错误是​​难以解决​​​的,可能不得不忍受它们.​​传递常​​​就是示例:​​C​​​没有它,但​​ImportC​​​有.有人在​​C标头​​​(​​可变​​​对象的​​const​​​指针)中发现了导致​​编译时​​错误案例.沃尔特不确定这是否可解决.

​ImportC​​​已发展到需要​​启动预处理器​​​地步.​​没有编译器​​​支持运行​​预处理器​​​是严重​​用户体验​​​问题.​​Iain​​​担心如果​​D编译器​​​正在调用​​C预处理器​​​,可能调用的不是​​正确的​​​.这导致了关于​​调用|拥有​​预处理器的讨论.

​Martin​​提出了​​LDC​​(等​​其他​​编译器)中​​ImportC​​的与​​ImportC​​如何处理​​C头文件​​有关的潜在问题.简而言之:​​多个D模块​​中导入相同​​标头​​声明导致​​C的重复​​.他说​​ImportC​​可以​​按D模块​​对待​​每个C标头​​.

​Iain​​提出了一个他认为​​难以解决​​的​​ImportC​​问题.沃尔特已经​​修复​​了它.​​这里​

​​Bugzilla​​中的​​DIP1000​​问题

​Walter​​已开始着手减少​​Bugzilla​​中​​DIP1000​​错误数.其中一些与需要清理的​​foreach​​循环和​​闭包​​有关.

一个默认进入​​DIP1000​​问题是如何处理​​引用 中 域​​歧义.​​Walter​​实现了半修复.已合并了一些​​PR​​,但其他一些停滞不前的​​PR​​阻碍了​​DIP1000​​,他想让那些动起来.

安德烈

​Andrei​​在电子邮件中讨论.

他先说,​​反射内置位域​​​很奇怪,你拥有​​小于8位​​​的东西,且无法使用​​指针​​​.有关​​位域​​​的提议都必须考虑到该点.​​Walter​​​的​​__traits(getMembers)​​​返回聚集的只是故事的一半.​​getter​​​和​​setter​​​呢?库解决方案有这些,但对​​内置​​​,它们是编译器​​神奇​​.

为了处理​​getter/setter​​​,​​Walter​​​认为有新的​​trait​​​可查询给定的​​成员​​​是否是​​位域​​​或其他,但他还未解决.​​另一种​​​选择是​​编译器​​​可"装配"​​getter/setter​​.

​Andrei​​​认为,必须权衡仅​​针对位域​​​的​​特殊壳反射​​​的成本与"已经在​​ImportC​​​中拥有它们,​​在D中​​​启用它们"的​​便利性​​​.他说,​​反射位域​​​是严重​​负担​​.

​Iain​​问​​位域​​是否真的是​​问题​​?为什么不有​​n位类型​​?​​Andrei​​回应说D曾经有​​位类型​​,但正是因为​​内置位域​​附带负担,它被删除了.

​Ali​​认为应该使​​库位域语法​​类似​​C位域语法​​.马丁认为意义不大.​​getMembers​​仍然返回​​模板实例​​而不是​​字段​​.

​Martin​​指出,位域优于​​库实现​​和​​Iain​​的​​n位​​类型,因为可为每个单独​​位域成员​​加注释.

​Walter​​​指出,使用​​库位域​​​对​​静初化器​​​来说是有问题的.​​Andrei​​​说这是​​有效​​​观点,但它可在​​库代码​​中解决.

​Mathias​​​建议当前​​实现​​​在定义字段时,用了​​错误​​​的方法来​​匹配​​​在​​C中用位字段​​​方式.他认为相反,应该只​​按字节对齐​​​定义​​访问器​​​.​​Andrei​​​说这是​​有效​​的替代方案,可简化代码.

相关主题(使​​库​​与​​C编译器​​的​​布局兼容​​,简化​​库语法​​,​​FPGA​​上的​​n位​​,打包​​布尔​​,标准化​​D位域布局​​,与​​C实现​​的兼容性等).太多,无法在此总结.

但​​Andrei​​确实建议​​Walter​​在继续使用​​内置​​实现前,应​​试验​​库实现.

​1个​​,​​1个​​,两个问题.


状态更新:​​引用 中 域​​​歧义现已修复​​这里​​​,及无效的​​纯域推导​​​​这里​​​和​​进出中推导​​​,​​这里​​​,目前,多数未解决的问题都与​​嵌套函数​​​有关.​​Atila​​​为域错误打印​​弃用​​​消息来恢复​​dip1000​​​,​​这里​​.