为什么在调用一个按值获取 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?

查看:28
本文介绍了为什么在调用一个按值获取 self 的方法时会借用一个移动的值,该方法的参数也调用一个方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了一个问题,该问题迫使我将一个漂亮的 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆