Mat*_*wik 5 rust borrow-checker
我遇到了一个问题,迫使我将一个好的内衬分割成{}带中间层的块let。我根本不清楚这个原因。在这个最小的示例中,我能够找出问题所在:
struct AB {
a: u8,
b: u8,
}
impl AB {
fn foo(&self) -> String {
String::from("foo")
}
fn bar(self, x: String) -> String {
format!("{} - {} - {}!", x, self.a, self.b)
}
}
fn main() {
let x = AB { a: 3, b: 5 };
let result = x.bar(x.foo());
println!("{}", result);
}
Run Code Online (Sandbox Code Playgroud)
我的印象是该bar函数的参数将在调用之前进行评估bar。在执行期间foo借入x,但在返回时String借用完成,因为String这不是参考轴承x的寿命。当bar被调用时,foo就借用应该结束了。
但是,编译器不同意:
struct AB {
a: u8,
b: u8,
}
impl AB {
fn foo(&self) -> String {
String::from("foo")
}
fn bar(self, x: String) -> String {
format!("{} - {} - {}!", x, self.a, self.b)
}
}
fn main() {
let x = AB { a: 3, b: 5 };
let result = x.bar(x.foo());
println!("{}", result);
}
Run Code Online (Sandbox Code Playgroud)
我并不反对bar确实如此的事实x。我的问题是在转移发生后foo借用的陈述。x
一个简单(但难看)的修复程序:
struct AB {
a: u8,
b: u8,
}
impl AB {
fn foo(&self) -> String {
String::from("foo")
}
fn bar(self, x: String) -> String {
format!("{} - {} - {}!", x, self.a, self.b)
}
}
fn main() {
let x = AB { a: 3, b: 5 };
let y = x.foo();
let result = x.bar(y);
println!("{}", result);
}
Run Code Online (Sandbox Code Playgroud)
将x.foo()中间变量的赋值分隔开可以y很好地编译,这证实了我的期望,即借入确实foo返回了一次,但是为什么这样做有效呢?关于评估顺序,我是否不了解?为什么我不能摆脱中间体let y?
为了借用,评估顺序是从左到右。
这意味着bar调用的主题,即“移出x”提及,x在foo调用中的“借用”提及之前被考虑,因此,编译器认为该变量已从中移出。
对于外部提及是可变借用的类似情况,RFC 2025已被接受为解决方案,但尚未实现。不幸的是,该RFC似乎没有涵盖您的情况,因为外部使用是一个举动。
| 归档时间: |
|
| 查看次数: |
738 次 |
| 最近记录: |