gpt4 book ai didi

rust - 什么是非词法生命周期?

转载 作者:行者123 更新时间:2023-11-29 07:40:05 25 4
gpt4 key购买 nike

Rust 有一个 RFC与非词法生命周期相关,其中 has been approved将在很长一段时间内在语言中实现。 Recently ,Rust 对这个特性的支持已经改进了很多,算是完整的了。

我的问题是:什么是非词法生命周期?

最佳答案

通过了解什么是最容易理解什么是非词法生命周期的 lexical一生是。在出现非词法生命周期之前的 Rust 版本中,此代码将失败:

fn main() {
let mut scores = vec![1, 2, 3];
let score = &scores[0];
scores.push(4);
}
Rust 编译器看到 scoresscore借用变量,因此它不允许进一步突变 scores :
error[E0502]: cannot borrow `scores` as mutable because it is also borrowed as immutable
--> src/main.rs:4:5
|
3 | let score = &scores[0];
| ------ immutable borrow occurs here
4 | scores.push(4);
| ^^^^^^ mutable borrow occurs here
5 | }
| - immutable borrow ends here
然而,人们可以很容易地看出这个例子过于保守: score从未使用过 !问题是 scores的借用来自 scorelexical — 它一直持续到包含它的块的末尾:
fn main() {
let mut scores = vec![1, 2, 3]; //
let score = &scores[0]; //
scores.push(4); //
// <-- score stops borrowing here
}
非词法生命周期通过增强编译器来理解这个级别的细节来解决这个问题。编译器现在可以更准确地判断何时需要借用并且此代码将被编译。
非词法生命周期的一个奇妙之处在于,一旦启用,没有人会考虑它们。它将简单地变成“Rust 所做的”,并且事情(希望)会正常工作。
为什么允许词法生命周期?
Rust 旨在只允许编译已知安全的程序。然而, it is impossible只允许安全的程序并拒绝不安全的程序。为此,Rust 在保守方面犯了错误:一些安全的程序被拒绝。词法生命周期就是一个例子。
词法生命周期在编译器中更容易实现,因为块的知识是“微不足道的”,而数据流的知识则不然。编译器需要是 rewritten to introduce and make use of a "mid-level intermediate representation" (MIR) .然后借用检查器(又名“borrowck”)必须重写以使用 MIR 而不是抽象语法树(AST)。然后,必须对借用检查器的规则进行细化以使其更细粒度。
词法生命周期并不总是妨碍程序员,并且有很多方法可以解决词法生命周期的问题,即使它们很烦人。在许多情况下,这涉及添加额外的花括号或 bool 值。这使得 Rust 1.0 能够在非词法生命周期实现之前发布并使用多年。
有趣的是,某些好的模式是由于词法生命周期而发展起来的。对我来说最好的例子是 the entry pattern .此代码在非词法生命周期之前失败并使用它进行编译:
fn example(mut map: HashMap<i32, i32>, key: i32) {
match map.get_mut(&key) {
Some(value) => *value += 1,
None => {
map.insert(key, 1);
}
}
}
但是,此代码效率低下,因为它计算了两次 key 的哈希值。由于词法生命周期而创建的解决方案更短、更高效:
fn example(mut map: HashMap<i32, i32>, key: i32) {
*map.entry(key).or_insert(0) += 1;
}
“非词汇生命周期”这个名字对我来说听起来不合适
值的生命周期是值停留在特定内存地址的时间跨度(请参阅 Why can't I store a value and a reference to that value in the same struct? 以获得更长的解释)。被称为非词法生命周期的特性不会改变任何值的生命周期,因此它不能使生命周期非词法。它只会使对这些值的借用的跟踪和检查更加精确。
该功能更准确的名称可能是“非词汇借用”。一些编译器开发人员引用了底层的“基于 MIR 的借用”。
非词法生命周期本身从未打算成为“面向用户”的功能。由于我们从他们缺席中得到的小剪纸,他们在我们的脑海中变得越来越大。他们的名字主要是为了内部开发目的,为了营销目的而改变它从来都不是优先事项。
是的,但我如何使用它?
在 Rust 1.31(于 2018-12-06 发布)中,您需要在 Cargo.toml 中选择加入 Rust 2018 版本:
[package]
name = "foo"
version = "0.0.1"
authors = ["An Devloper <an.devloper@example.com>"]
edition = "2018"
从 Rust 1.36 开始,Rust 2015 版本也支持非词法生命周期。
非词法生命周期的当前实现处于“迁移模式”。如果 NLL 借用检查器通过,则编译继续。如果不是,则调用先前的借用检查器。如果旧的借用检查器允许代码,则会打印一条警告,通知您您的代码可能会在 Rust 的 future 版本中损坏,应该更新。
在 Rust 的夜间版本中,您可以通过功能标志选择加入强制破坏:
#![feature(nll)]
您甚至可以使用编译器标志 -Z polonius 来选择加入 NLL 的实验版本。 .
非词法生命周期解决的实际问题示例
  • Returning a reference from a HashMap or Vec causes a borrow to last beyond the scope it's in?
  • Why does HashMap::get_mut() take ownership of the map for the rest of the scope?
  • Cannot borrow as immutable because it is also borrowed as mutable in function arguments
  • How to update-or-insert on a Vec?
  • Is there a way to release a binding before it goes out of scope?
  • Cannot obtain a mutable reference when iterating a recursive structure: cannot borrow as mutable more than once at a time
  • When returning the outcome of consuming a StdinLock, why was the borrow to stdin retained?
  • Collaterally moved error when deconstructing a Box of pairs
  • 关于rust - 什么是非词法生命周期?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50251487/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com