d放松不变

1参考
timon原dip
更新dip
用它来实现通用引用计数.主要问题是如何引用计数不变/常量对象.Timon最初提议按不影响基于纯优化方式实现__metadata.可这样:
应用至相同不变参数时,强纯函数(返回无间接类型)返回相同结果.
通过重写:

auto a = foo(arg)   // foo -> 强纯
auto b = foo(arg)

至:

auto a = foo(arg)
auto b = a

来修复.

安全转换强纯函数返回的引用集不变或共享.这不受引入__metadata的影响.

安全地省略结果未用强纯函数.

struct S{
    private int __metadata x;
}

void foo(immutable ref S s)pure{
    s.x += 1;
}

void main(){
    immutable S s;
    foo(s); // 不必调用它.
    assert(s.x==1); // 不能依赖它,可能未调用
}

本质上,如果foo是强纯,则编译器可优化调用,并且没了引用计数.如果这样看,问题似乎无解.但是,__metadata的仅供库开发人员使用,甚至他们也应该格外小心.

因此,建议__metadata只能从定义它的聚集内部访问(private这里是指Java私),直接访问__metadata的方法也需要私有.

因为只有在调用复制构造器和赋值符号时才会更新引用.应公开这些方法,且可调用强制私有incRef,decRef.这样,必须用对象方法访问__metadata字段.这是对的,因为只有对象应该管理__metadata.

现在,如果这样,则除了赋值s,传递s给函数或从s复制构造外,foo不能访问x.但是,无论s为何值,一旦结束执行,调用点的引用计数与调用时相同.为什么?因为在强纯函数之外无法逃逸s的引用(除了返回它,但在第1点处理了).

如果有两个后续纯函数调用:foo(args1...)bar(args2...),仅在不变const数据中重叠(包括通过和不变的__mutable字段访问的数据对象),从args1args2可传递访问的数据,这两个调用可安全地交换顺序(当然,这仅适用于两个函数都不带参数时)
这不应受影响.
强纯函数总是可与相邻不纯函数交换顺序.
这不应受影响.
你怎么看?我缺少了什么吗?如果你认为这可实现,我可更新DIP并提交它.


不变和可变不能混合.不变,很可能进入只读内存,在此操作都会导致程序崩溃.引用计数不变对象也没有意义.
涉及到更改const对象数据(如引用计数)时,这是语言底层工作的低级代码.即放弃干活所需的一切.


我坚持只读内存评论.
你仍可运行时只读标记内存,可惜我不知道在编译器中如何检测到该点,并因此导致编译失败.
我仍喜欢,对类和结构的三个新重载符号方法.
opRefAdd,opRefSub,opReadOnly.
前两个就像忽略了的析构器.
最后1个告诉(不能是const)类型,进入只读内存,不可再写.如果实现了引用计数,这是必需的.
__mutable的主要区别在于它应禁止进入只读内存:编译器无法检测,但可阻止这样.这给了非常错误保证感.
而本方法,显然谁放进只读内存,及正确编写该类型,不提供保证,因此无安全感.
我觉得可在解析器有些快速而廉价测试,以确定给函数域/@安全属性.如果做得好,默认可能表明@safe!

enum __c_bitfield;
is(typeof(value.bitfield) == __c_bitfield)

只要.sizeof是考虑"空"位和对齐实际大小,这应该相当安全.它占单个指针,需要特殊反射机制来取位数+名+类型元组.

是否将"不变"数据放入只读内存中,是在知道类型的内存布局时决定的.如果有__mutable字段,就不放入只读内存.
是的,一切都在@system代码内.
现有语言规则禁止这样做,因此需要修改规范.

但是,访问__metadata应该是@system.
如,如何在纯析构器中释放内存?(由我原草案中的__mutable函数解决.)
如果析构器既是纯的又是不变的呢?
更一般,需要支持自定义分配不变内存.

posted @   zjh6  阅读(10)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示