Я столкнулся с проблемой, которая вынуждает меня разделить хороший пользовательский блок на {}
блок с промежуточным 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
, но почему это работает?Что-то я не понимаю в порядке оценки?Почему я не могу избавиться от промежуточного let y
?