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通过“改变方法调用的去糖方式”解决了这个问题,但仍然倾向于更一般的方法,不幸的是没有解释。