Rust 为什么';难道不是一种从自我改变到不变的可变借用吗?
此代码使可怕的借用检查器()失败: 由于实现了非词汇生存期,因此触发错误需要这样做:Rust 为什么';难道不是一种从自我改变到不变的可变借用吗?,rust,borrow-checker,Rust,Borrow Checker,此代码使可怕的借用检查器()失败: 由于实现了非词汇生存期,因此触发错误需要这样做: fn main() { let mut dat = Data { a: 1, b: 2, c: 3 }; let aref = dat.reference_to_a(); let b = dat.get_b(); println!("{:?}, {}", aref, b); } 错误: error[E0502]:无法将'dat'作为不可变项借用,因为它也是作为可变项借用的 --
fn main() {
let mut dat = Data { a: 1, b: 2, c: 3 };
let aref = dat.reference_to_a();
let b = dat.get_b();
println!("{:?}, {}", aref, b);
}
错误:
error[E0502]:无法将'dat'作为不可变项借用,因为它也是作为可变项借用的
--> :19:20
|
18 |设aref=dat.reference_to_a();
|---可变借用发生在此处
19 | println!(“{}”,dat.get_b());
|^^^此处发生不可变借用
20 | }
|-可变借用结束于此
为什么会这样?当
reference\u to_a()
返回时,dat
的可变借用被转换为不可变借用,因为该函数只返回不可变引用。借钱的人还不够聪明吗?这是计划吗?有办法解决吗?生命周期与引用是否可变是分开的。通过代码工作:
fn reference_to_a(&mut self) -> &i32
虽然省略了寿命,但这相当于:
fn reference_to_a<'a>(&'a mut self) -> &'a i32
fn参考到i32
i、 e.输入和输出寿命相同。这是向这样的函数分配生存期的唯一方法(除非它返回了对全局数据的&'static
引用),因为您不能从无到有地弥补输出生存期
这意味着,如果通过将返回值保存在变量中使其保持活动状态,那么&mut self
也将保持活动状态
另一种思考方式是,&i32
是&mut self
的子借用,因此只在到期之前有效
正如@aSpex所指出的,这就是。为什么这是一个错误:虽然@Chris在大约2.5年前已经给出了更精确的解释,但您可以将fn reference\u to_a(&mut self)->&i32
作为一个声明来阅读:
“我想独占借用self
,然后返回一个共享/不可变引用,该引用的有效期与原始独占借用相同”()
显然
借阅检查程序还不够聪明吗?这是计划好的吗?
仍然无法表达“我想在通话期间完全借用self,并在单独的生命周期内返回一个共享引用”。正如@aSpex所指出的,截至2018年底,该公司已被列为最受欢迎的公司之一
像以前一样,我找不到解决这个问题的具体计划。允许单独读/写“终身角色”(Ref2
)的想法是,但据我所知,还没有人将其变成自己的RFC
是否有办法解决此问题?不太可能,但根据您首先需要此功能的原因,其他结构化代码的方法可能是合适的:
- 您可以返回副本/克隆,而不是引用
- 有时您可以将
分为两部分,一部分接受fn(&mut self)->&T
,另一部分返回&mut self
&T
- 就像生锈一样,重新排列结构会有所帮助
- 您可以从以下方法返回共享引用:
()fn(&mut-self)->(&self,&T)
- 您可以使fn采用共享的
引用和使用(即定义&self
中需要变异为self
或单元格
)的部分)。这可能感觉像是作弊,但实际上是适当的,例如,当你需要可变性作为目标的原因时。毕竟,我们正在制作一个方法,将RefCell
转换为&mut self
贷款的生命周期
@aSpex:啊,是的,看起来是一样的。但是文档没有提出解决方案或解决方法?哦,事实上“根据我们实际关心的引用语义,这个程序显然是正确的,但是生命周期系统太粗了,无法处理它。”。因此,唯一的解决方案是使用独立的作用域@aSpex您应该发布答案。谢谢,有解决方案或解决方法吗?非词汇生存期能解决这个问题吗?我认为除了将变异分解成一个单独的方法调用之外,没有其他解决方法。这不是一件终生难忘的事情;&i32
是从&mut self
借来的,因此它们基本上是联系在一起的。@timmm OP示例在启用NLL时按原样工作。“示例在启用NLL时按原样工作”只是因为aref
未使用。如果你使用它,比如println!(“{}{}”,aref,dat.get_b())
那么NLL将不会有任何帮助,正如@ChrisEmerson所解释的。有没有原因可以解释为什么rust不能扩展到允许这样做,或者甚至为什么很难允许这样做。例如,为什么rust不能在返回时将可变的自我借用“降级”为不变的自我借用。这样,它就可以工作了(因为您可以对同一事物进行多个不可变的借用)。
fn reference_to_a<'a>(&'a mut self) -> &'a i32