为什么在调用一个方法时会借用一个移动的值,该方法使用也调用方法的参数来按值获取自我?
Why is there a borrow of a moved value when calling a method that takes self by value with an argument that also calls a method?
我 运行 遇到了一个问题,它迫使我将一个不错的 oneliner 分成一个 {}
块和一个中间 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
,但是当它 returns 其 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
returns,但为什么这个工作?关于评估顺序,我有什么不明白的吗?为什么我不能摆脱中间 let y
?
求值顺序,为了借用,从左到右。
这意味着 bar
调用的主题,"move-out" 提及 x
,在 "borrow" 提及 x
之前被考虑foo
调用,因此,编译器认为该变量已从中移出。
对于外部提及是可变借用的类似情况,RFC 2025已被接受为解决方案,但尚未实施。不幸的是,这个 RFC 似乎没有涵盖你的情况,外部使用是一个移动。
我 运行 遇到了一个问题,它迫使我将一个不错的 oneliner 分成一个 {}
块和一个中间 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
,但是当它 returns 其 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
returns,但为什么这个工作?关于评估顺序,我有什么不明白的吗?为什么我不能摆脱中间 let y
?
求值顺序,为了借用,从左到右。
这意味着 bar
调用的主题,"move-out" 提及 x
,在 "borrow" 提及 x
之前被考虑foo
调用,因此,编译器认为该变量已从中移出。
对于外部提及是可变借用的类似情况,RFC 2025已被接受为解决方案,但尚未实施。不幸的是,这个 RFC 似乎没有涵盖你的情况,外部使用是一个移动。