Rust 为什么参数;借用;价值呢?

Rust 为什么参数;借用;价值呢?,rust,borrow-checker,Rust,Borrow Checker,以下是一个示例: struct X(u32); impl X { fn f(&mut self, v: u32) {} } fn main() { let mut x = X(42); // works let v = x.0; x.f(v); // cannot use `x.0` because it was mutably borrowed x.f(x.0); } () error[E0503]:无法使用'x.0',

以下是一个示例:

struct X(u32);

impl X {
    fn f(&mut self, v: u32) {}
}

fn main() {
    let mut x = X(42);

    // works
    let v = x.0;
    x.f(v);

    // cannot use `x.0` because it was mutably borrowed
    x.f(x.0);
}
()

error[E0503]:无法使用'x.0',因为它是可变借用的
-->src/main.rs:16:9
|
16 | x.f(x.0);
|-^^^借用的`x的用法`
|     |
|“x”的借词出现在这里
x.f(x.0)
不起作用的原因是什么
x.0
作为参数传递,绑定到
v
参数,类型为
u32
:函数体绝对不可能通过参数访问
x.0

此外,我觉得很奇怪:

f(something);
不起作用,而:

v = something;
f(v);
起作用。

当您执行
x.f(x.0)
时,在再次尝试借用
x
以获取
x.0
的参考之前,您已经借用了
x
以提供
&mut self
f
。不能同时参考
x.0
两次。也就是说,方法
f
不能同时具有通过
和mut self
(包括
x.0
)对
x
的可变访问权限和对
x.0
的看似不变的引用

当使用临时变量时,实际上会得到该值的副本;这意味着您不再
在X
中引用该int,而是
42
。那是允许的


关于“非词汇生命期”注释:由于
f
采用了一个好的旧u32而不是引用它,
x.f(x.0)
基本上应该等同于
x.f(42)
,因为编译器可以在从
x.0
中获取值后释放
x
,然后再次mut借用
x
,以将
和mut self
提供给
f
。但是,编译器在编译过程中很早就确定了生命周期及其要求;因此,目前的寿命比必须的要长<由于
x.0
参数,code>rustc当前无法确定
x
上的借用在
&mut self
的借用
x
之前已结束。目前正在修复此问题。

这是借用检查器的一个已知缺陷,使用临时变量是一个解决方法。谷歌非词汇生存期了解更多细节。谢谢你的提示。最相关的文章是关于“嵌套方法调用”:为什么编译器不首先计算参数,这样当它在
x.0
中借用
x
时,它还没有在
x.f
中借用
x
?这是预期的求值顺序,不是吗?因为当编译器确定生命周期时,它对程序的实际结构一无所知:生命周期目前由它们的“词法范围”决定,最基本的是由文本的编写方式决定。请参阅,以获得一个很好的示例,说明这会导致疣体。@rom1v关于
foo().f(bar())
?如果
foo
bar
是有副作用的函数,您希望先发生哪一个?那么
X::f(foo(),bar())
x.f(x.0)
是一个“正确”行为显而易见的例子,但在不产生歧义、引入任意限制或破坏向后兼容性的情况下对其进行概括绝非易事。@user2722968谢谢,这解释了当前实现的工作方式。但现在,在我看来,由于@trentcl给出的例子,这个问题更为普遍。注意,
let(a,b)=(&mut x,x.0)也会出现同样的问题
(与
let(b,a)=(x.0,&mut x);
@trentcl将
x(Y)
视为等同于
{let(a=x;let(b=Y;_a(_b)}
,这似乎解决了过度严格的借用问题,只要需要手动执行相同的操作,并且不改变行为(除非我对当前的
X
Y
的求值顺序有误解)。Niko Matsaki通过“改变方法调用的去糖方式”解决了这个问题,但仍然倾向于更一般的方法,不幸的是没有解释。