为什么在调用一个按值获取 self 的方法时会借用一个移动的值,该方法的参数也调用一个方法? [英] 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
的 {}
块.我根本不清楚这样做的原因.我能够在这个最小的例子中隔离问题:
I ran into an issue that forces me to split a nice oneliner into a {}
block with an intermediate let
. The reason for this isn't clear to me at all. I was able to isolate the issue in this minimal example:
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
的借用应该结束.
I was under the impression that the arguments to the bar
function would be evaluated before calling bar
. foo
borrows x
during its execution, but when it returns its String
, the borrow is finished, as String
is not a reference bearing x
's lifetime. When bar
gets called, foo
's borrow should be over.
然而,编译器不同意:
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
after 移动发生的声明.
I'm not disagreeing with the fact that bar
indeed moves x
. My issue is with the statement that foo
borrows x
after the move takes place.
一个简单(但丑陋)的修复:
A simple (but ugly) fix:
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代码> 返回,但为什么这有效?我对评估顺序有什么不明白的地方吗?为什么我不能去掉中间的
let y
?
separating the assignment of x.foo()
to an intermediate variable y
compiles fine, confirming my expectation that the borrow is indeed over once foo
returns, but why does this work? Is there something I don't understand about evaluation order? Why can't I get rid of the intermediate let y
?
推荐答案
求值顺序,以借用为目的,从左到右.
Evaluation order, for the purpose of borrows, is from left to right.
这意味着 bar
调用的主题,x
的移出"提及,在 x 的借用"提及之前被考虑
在 foo
调用中,因此,编译器认为该变量已被移出.
This means that the subject of the bar
call, the "move-out" mention of x
, is considered before the "borrow" mention of x
in the foo
call, and therefore, the compiler considers the variable to have been moved from.
对于外部提及是可变借用的类似情况,RFC 2025 已被接受为解决方案,但尚未实施.不幸的是,这个 RFC 似乎没有涵盖您的情况,其中外部使用是一种移动.
For the similar case where the outer mention is a mutable borrow, RFC 2025 has been accepted as a solution, but hasn't been implemented yet. Unfortunately this RFC doesn't appear to cover your case, where the outer use is a move.
这篇关于为什么在调用一个按值获取 self 的方法时会借用一个移动的值,该方法的参数也调用一个方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!