为什么可变借用 self 不会变为不可变? [英] Why doesn't a mutable borrow of self change to immutable?

查看:42
本文介绍了为什么可变借用 self 不会变为不可变?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此代码无法通过可怕的借用检查器 (playground):

struct 数据 {一:i32,乙:i32,c: i32,}impl 数据 {fn reference_to_a(&mut self) ->&i32 {self.c = 1;&self.a}fn get_b(&self) ->i32 {自我.b}}fn 主(){让 mut dat = 数据{ a: 1, b: 2, c: 3 };让 aref = dat.reference_to_a();println!("{}", dat.get_b());}

由于实现了非词法生命周期,这是触发错误所必需的:

fn main() {让 mut dat = 数据 { a: 1, b: 2, c: 3 };让 aref = dat.reference_to_a();让 b = dat.get_b();println!("{:?}, {}", aref, b);}

错误:

error[E0502]: 不能借用 `dat` 作为不可变的,因为它也被借用为可变的--><匿名>:19:20|18 |让 aref = dat.reference_to_a();|--- 可变借用发生在这里19 |println!("{}", dat.get_b());|^^^ 不可变借用发生在这里20 |}|- 可变借用到此结束

这是为什么?我原以为 dat 的可变借用会在 reference_to_a() 返回时转换为不可变借用,因为该函数只返回一个不可变引用.借用检查器还不够聪明吗?这是计划好的吗?有办法解决吗?

解决方案

生命周期与引用是否可变是分开的.完成代码:

fn reference_to_a(&mut self) ->&i32

虽然生命周期已被省略,但这相当于:

fn reference_to_a<'a>(&'a mut self) ->&'a i32

即输入和输出的生命周期是一样的.这是为这样的函数分配生命周期的唯一方法(除非它返回一个对全局数据的 &'static 引用),因为你不能从零开始构成输出生命周期.

这意味着如果您通过将返回值保存在变量中来使其保持活动状态,那么您也会使 &mut self 保持活动状态.

另一种思考方式是 &i32&mut self 的子借用,因此仅在到期之前有效.>

正如@aSpex 所指出的,这是在 nomicon 中涵盖的内容.

This code fails the dreaded borrow checker (playground):

struct Data {
    a: i32,
    b: i32,
    c: i32,
}

impl Data {
    fn reference_to_a(&mut self) -> &i32 {
        self.c = 1;
        &self.a
    }
    fn get_b(&self) -> i32 {
        self.b
    }
}

fn main() {
    let mut dat = Data{ a: 1, b: 2, c: 3 };
    let aref = dat.reference_to_a();
    println!("{}", dat.get_b());
}

Since non-lexical lifetimes were implemented, this is required to trigger the error:

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:

error[E0502]: cannot borrow `dat` as immutable because it is also borrowed as mutable
  --> <anon>:19:20
   |
18 |     let aref = dat.reference_to_a();
   |                --- mutable borrow occurs here
19 |     println!("{}", dat.get_b());
   |                    ^^^ immutable borrow occurs here
20 | }
   | - mutable borrow ends here

Why is this? I would have thought that the mutable borrow of dat is converted into an immutable one when reference_to_a() returns, because that function only returns an immutable reference. Is the borrow checker just not clever enough yet? Is this planned? Is there a way around it?

解决方案

Lifetimes are separate from whether a reference is mutable or not. Working through the code:

fn reference_to_a(&mut self) -> &i32

Although the lifetimes have been elided, this is equivalent to:

fn reference_to_a<'a>(&'a mut self) -> &'a i32

i.e. the input and output lifetimes are the same. That's the only way to assign lifetimes to a function like this (unless it returned an &'static reference to global data), since you can't make up the output lifetime from nothing.

That means that if you keep the return value alive by saving it in a variable, you're keeping the &mut self alive too.

Another way of thinking about it is that the &i32 is a sub-borrow of &mut self, so is only valid until that expires.

As @aSpex points out, this is covered in the nomicon.

这篇关于为什么可变借用 self 不会变为不可变?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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