我遇到了一个问题,该问题迫使我将一个不错的oneliner分成一个中间为{}
的{{1}}块。我根本不清楚这个原因。在这个最小的示例中,我能够找出问题所在:
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);
}
函数的参数赋值是在调用bar
之前 求值。 bar
在执行期间借用了foo
,但是当它返回其x
时,借用已完成,因为String
不是承载String
的生存期的引用。当x
被呼叫时,bar
的借用应该已经结束。
但是,编译器不同意:
foo
我不同意error[E0382]: borrow of moved value: `x`
--> src/main.rs:17:24
|
17 | let result = x.bar(x.foo());
| - ^ value borrowed here after move
| |
| value moved here
|
= note: move occurs because `x` has type `AB`, which does not implement the `Copy` trait
确实会移动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);
}
分配给中间变量x.foo()
可以很好地编译,这证实了我的期望,即一旦y
返回,借入确实已经结束了,但是为什么这样做有效?关于评估顺序,我是否不了解?为什么我不能摆脱中间的foo
?
答案 0 :(得分:4)
出于借款目的,评估顺序是从左到右。
这意味着{{1}中调用NaN
的主题,即“移出” bar
,在{{1 }}调用,因此编译器认为该变量已从中移出。
对于外部提及是可变借用的类似情况,RFC 2025已被接受为解决方案,但尚未实现。不幸的是,该RFC似乎没有涵盖您的情况,因为外部使用是一个举动。