Ana*_*kov 5 rust borrow-checker borrowing
我正在研究Rust by Example并从"Alias"页面运行代码:
struct Point {
x: i32,
y: i32,
z: i32,
}
fn main() {
let mut point = Point { x: 0, y: 0, z: 0 };
{
let borrowed_point = &point;
let another_borrow = &point;
// Data can be accessed via the references and the original owner
println!(
"Point has coordinates: ({}, {}, {})",
borrowed_point.x, another_borrow.y, point.z
);
// Error! Can't borrow point as mutable because it's currently
// borrowed as immutable.
let mutable_borrow = &mut point;
println!(
"Point has coordinates: ({}, {}, {})",
mutable_borrow.x, mutable_borrow.y, mutable_borrow.z
);
let mutable_borrow2 = &mut point;
println!(
"Point has coordinates: ({}, {}, {})",
mutable_borrow2.x, mutable_borrow2.y, mutable_borrow2.z
);
// TODO ^ Try uncommenting this line
// Immutable references go out of scope
}
{
let mutable_borrow = &mut point;
// Change data via mutable reference
mutable_borrow.x = 5;
mutable_borrow.y = 2;
mutable_borrow.z = 1;
// Error! Can't borrow `point` as immutable because it's currently
// borrowed as mutable.
//let y = &point.y;
// TODO ^ Try uncommenting this line
// Error! Can't print because `println!` takes an immutable reference.
//println!("Point Z coordinate is {}", point.z);
// TODO ^ Try uncommenting this line
// Ok! Mutable references can be passed as immutable to `println!`
println!(
"Point has coordinates: ({}, {}, {})",
mutable_borrow.x, mutable_borrow.y, mutable_borrow.z
);
// Mutable reference goes out of scope
}
// Immutable references to point are allowed again
let borrowed_point = &point;
println!(
"Point now has coordinates: ({}, {}, {})",
borrowed_point.x, borrowed_point.y, borrowed_point.z
);
}
Run Code Online (Sandbox Code Playgroud)
使用Rust编译器()的最新每晚构建在Windows上运行此代码时,我不会遇到编译错误rustc 1.31.0-nightly (f99911a4a 2018-10-23).Rust Playground 中 Rust编译器的最新每晚构建确实提供了预期的编译错误.
为什么是这样?为什么Rust编译器会破坏借用规则?如何在本地修复此问题以获得预期的错误?
当您使用Rust 1.31创建新的Cargo项目时,您将自动选择进入Rust版本2018:
[package]
name = "example"
version = "0.1.0"
authors = ["An Devloper <an.devloper@example.com>"]
edition = "2018"
Run Code Online (Sandbox Code Playgroud)
这会打开非词汇生命周期,从而实现更智能的借阅检查器形式.如果你想要旧的行为,你可以切换回2015; 这将导致您的代码产生预期的错误.不过,我鼓励您继续使用2018年版.
Rust Playground提供版本之间的切换:
Playground目前默认为2015版,在Rust 1.31稳定后,Playground将其默认值更改为2018版.
我如何更改此示例以提供预期的行为
你不能在Rust 2018中.在非词汇生命周期之前,Rust编译器只是不够智能.代码本身是安全的,但编译器无法看到.编译器现在很聪明,所以代码编译.没有理由使用编译器模式来使本质上正确的代码无法编译.
您应该通过示例提交Rust问题,让他们知道他们的示例在Rust 2018中不再有效.
解决方案是代码的前奏.
数据可以不加任意地借用,但是在不可避免地借用的情况下,原始数据不能可靠地借用.另一方面,一次只允许一次可变借入.只有在可变引用超出范围之后,才能再次借用原始数据.
这意味着,您可以随意借用一个值,但一次只能有一个可变借位(在一个范围内).
你可能想知道为什么代码编译#![feature(nll)].
原因是'nll'(非词汇生命周期)允许编译器为超出范围范围(在{和之间的所有内容})的借用创建生命周期.现在可以看出,在使用借来的印刷价值之后,它将不再被使用,因此借款的有效期就在此之后结束println!.
这不会破坏上述任何规则.你不能同时拥有可变借款,例如
let mut point = Point { x: 0, y: 0, z: 0 };
let p1 = &mut point;
let p2 = &point;
println!("Point has coordinates: ({}, {})", p1.x, p2.y);
Run Code Online (Sandbox Code Playgroud)
不行!记在脑子里.
| 归档时间: |
|
| 查看次数: |
225 次 |
| 最近记录: |