新增加的~
前几天,Niko(也就是Rust的编译器和语言两个团队的领导)发了一篇博客,提出了一种基于位置的生命周期语法标记。这篇博客主要讲的是对Rust编译器中借用检查器的一些改进。
开篇提到了Rust的核心设计精神:修改与共享互斥。简单说,就是当你通过一个变量X去修改一个值的时候,你不能同时通过变量Y去读它。这是Rust内存安全的保证。
第一步改进:通过POLONIUS这样一个新的计算机算法,用一种新的方式来解决借用检查,特别是解决条件返回引用(conditional return reference)的问题。以下面的代码为例:
1 | if let Some(v) = map.get(key) { |
这里对哈希map做了一个可变借用,但在这个作用域里,它就无法再对这个map做一些可变借用了。这是受限于当前借用检查器的限制。但实际上这个例子的代码是完全没有问题的,因为当它为None的时候,不会对这个map做修改。这个经典的case是通过新的借用检查器来解决的。
第二步改进:提出了一种新的基于位置的生命周期语法标记。它在生命周期标记的时候,可以直接指定它来自哪个变量或者哪个变量字段。例如:
'x表示借用自变量x'x.y表示借用自变量x的字段y'x.y|z表示借用自变量x的字段y或变量z
实际代码示例:
1 | fn example(name: &str) -> &'name str { ... } |
这里的'name表示这个引用借用自name变量,'self.model表示借用自self的model字段。这比之前的ABC这种标记方式更容易理解。
这种基于位置的生命周期标记也能简化第一步中提到的case。我们可以直接对返回的引用标记它借用自map就行了,无需额外的生命周期标记,看起来非常简洁易懂。
第三步:更细腻的控制。以下面的代码为例:
1 | impl Widget { |
这个代码在当前的Rust编译器中是编译不过的,因为它对cf(self.widgets)做了一个不可变的借用,但又调用了increment_counter方法,这个方法对self做了一个可变借用。当前的Rust编译器无法知道increment_counter是否会修改self的其他字段(比如widgets字段)。
引入新的基于位置的语法标记后,我们可以修改increment_counter方法,表示它只修改self的count字段:
1 | fn increment_counter(&mut'self.count self) { |
这样,这段代码就能编译通过了,实现了更细粒度的控制。
第四步:解决内部引用问题。以下面的代码为例:
1 | struct Message<'text, 'to> { |
在新的语法标记下,可以直接用'cf.text和'cf.to来标记。这样,Message就不再需要任何的生命周期类型参数了。而且从本质上说,这个Message并没有从外界借用任何东西,实际上是static的。这意味着它可以在线程之间传递,大大增强了它的能力。
从这个博客来看,这个新的语法标记并不像是一个临时起意的想法,感觉是经过长时间考虑的结果。很有可能最终会落地实施,但具体时间还不清楚。
Polonius是Rust编程语言中一个新的借用检查器(borrow checker)的实现。它是为了改进Rust的借用检查系统而开发的。以下是关于Polonius的一些关键信息:
目的:Polonius旨在使Rust的借用检查更加精确和灵活,能够接受更多合法的Rust程序。
名称来源:Polonius这个名字来自于莎士比亚的戏剧《哈姆雷特》中的一个角色。
技术基础:Polonius基于数据流分析(dataflow analysis)技术,这使得它能够更精确地推断引用的生命周期。
改进:相比于Rust现有的借用检查器,Polonius能够处理一些更复杂的借用模式,特别是在处理条件返回和非词法作用域(non-lexical lifetimes)方面表现更好。
状态:截至我最后更新的信息,Polonius仍然是一个实验性的项目,尚未完全集成到Rust的主要编译器中。
潜在影响:如果完全实施,Polonius可能会允许更多之前被拒绝的Rust代码通过编译,同时仍然保持Rust的内存安全保证。
开发过程:Polonius的开发是一个渐进的过程,Rust团队一直在进行实验和改进,以确保它能够正确处理各种复杂的Rust代码模式。
Polonius代表了Rust团队在不断优化和改进语言核心机制方面的持续努力,旨在使Rust更加强大和易用,同时保持其强大的安全性保证。
原文链接: https://dashen.tech/2018/07/02/Rust基于位置的生命周期语法/
版权声明: 转载请注明出处.