为什么我不能从枚举中可变地借用一个原语?

lje*_*drz 8 enums rust borrow-checker

我希望能够获得对引用(包括可变和不可变)usizeBarFoo枚举:

use Foo::*;

#[derive(Debug, PartialEq, Clone)]
pub enum Foo {
    Bar(usize)
}

impl Foo {
    /* this works */
    fn get_bar_ref(&self) -> &usize {
        match *self {
            Bar(ref n) => &n
        }
    }

    /* this doesn't */
    fn get_bar_ref_mut(&mut self) -> &mut usize {
        match *self {
            Bar(ref mut n) => &mut n
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

但我无法获得可变参考,因为:

n 活得不够久

我能提供的访问的其他内容类似的功能这两个变种FooBox艾德-为何可变借(为什么只有它)失败,未装箱原始?

red*_*ime 7

您需要更换Bar(ref mut n) => &mut nBar(ref mut n) => n.

当您使用ref mut nin时Bar(ref mut n),它会创建对数据的可变引用Bar,因此类型n&mut usize.然后,你试图返回&mut n&mut &mut u32类型.

这部分很可能是不正确的.

现在deref强制开始并转换&mut n&mut *n,创建一个*n 类型的临时值usize,这个值不够长.

  • Deref胁迫*不可能*创造临时性.正在发生的事情是`&mut**&mut n`(这是deref强制将有效地导致该例子)和`&mut*n`(***工作)之间的区别.它不太可能是完整性所必需的(因为两个版本都执行*完全相同的*操作),但由于可变引用下的不变性,生命周期可能会比应该更加"收紧".现在找不到它,但之前已经报道过这个问题. (4认同)
  • 那仍然很奇怪.为什么`get_bar_ref`的行为不一样? (2认同)
  • 我不相信这与deref胁迫有任何关系. (2认同)
  • @ljedrz如果你有'Foo(ref boxed)`,那么`*boxed:Box <T>`和`**boxed:T`,所以`&**boxed:&T`.*但是*,`boxed:&Box <T>`会很高兴地强迫`&T`(通过deref强制).`&*boxed:&Box <T>`相当于简单地使用`boxed`. (2认同)

edd*_*dyb 7

这些示例显示了示例问题:

fn implicit_reborrow<T>(x: &mut T) -> &mut T {
    x
}

fn explicit_reborrow<T>(x: &mut T) -> &mut T {
    &mut *x
}

fn implicit_reborrow_bad<T>(x: &mut T) -> &mut T {
    &mut x
}

fn explicit_reborrow_bad<T>(x: &mut T) -> &mut T {
    &mut **&mut x
}
Run Code Online (Sandbox Code Playgroud)

这些explicit_版本显示了编译器通过deref强制推断的内容.
_bad版本既错误完全相同的方式,而其他两个编译.

这可能是一个错误,也可能是对编译器当前如何实现生命周期的限制.&mut Tover 的不变性T 可能与它有关,因为它导致在推理期间&mut &'a mut T不变'a,因此比共享reference()情况更具限制性&&'a T,即使在这种情况下严格性是不必要的.