首先,我不是在问&mutref mut之间有什么区别.

我这么问是因为我想:

let ref mut a = MyStruct

let a = &mut MyStruct

考虑从一个函数返回一个特征对象.你可以退Box<Trait>&Trait.如果您想对其方法进行可变访问,是否可以返回&mut Trait

举个例子:

trait Hello {
    fn hello(&mut self);
}

struct English;
struct Spanish;

impl Hello for English {
    fn hello(&mut self) {
        println!("Hello!");
    }
}

impl Hello for Spanish {
    fn hello(&mut self) {
        println!("Hola!");
    }
}

出于演示目的,该方法接收可变引用.

这不会编译:

fn make_hello<'a>() -> &'a mut Hello {
    &mut English
}

这也不是:

fn make_hello<'a>() -> &'a mut Hello {
    let b = &mut English;
    b
}

但这将编译并运行:

fn make_hello<'a>() -> &'a mut Hello {
    let ref mut b = English;
    b
}

My theory

本例将使用不可变引用(不必将其分配给变量,只需返回&English),但不使用可变引用.我认为这是由于一条规则,即只能有一个可变引用,或者可以有任意多个不可变引用.

在不可变引用的情况下,创建一个对象并将其作为返回表达式borrow ;它的引用不会因为被borrow 而消亡.

在可变引用的情况下,如果试图创建一个对象,并将其作为返回表达式可变地borrow ,则有两个可变引用(创建的对象及其可变引用).因为不能对同一个对象有两个可变引用,所以它不会执行第二个引用,因此变量的生命周期 不够长.我认为当你写let mut ref b = English并返回b时,你就是可变引用,因为它被一个模式捕获了.

所有这些都是对自己解释它为什么有效的拙劣try ,但我没有基本原理来证明它.

为什么会这样?

我也有cross-posted this question to Reddit个.

推荐答案

This is a bug.我在下面最初的分析完全忽略了一个事实,即它返回了mutable个引用.关于晋升的部分只有在immutable个价值观的背景下才有意义.


这是允许的,因为rules governing temporaries的细微差别(强调):

在大多数左值上下文中使用右值时,会创建并使用一个临时的未命名左值,if not promoted to 100.

参考文献继续:

当可以在不更改运行时行为的情况下,将右值表达式提升到'static槽时,会将该表达式写入常量、borrow 并取消引用该borrow ,而该borrow 是最初编写的表达式.也就是说,可以在编译时对提升的表达式求值,结果值不包含内部可变或析构函数(这些属性在可能的情况下基于值确定,例如&None始终具有类型&'static Option<_>,因为它不包含任何不允许的内容).

您的第三个 case 可以改写为"证明"'static促销正在进行:

fn make_hello_3<'a>() -> &'a mut Hello {
    let ref mut b = English;
    let c: &'static mut Hello = b;
    c
}

至于为什么ref mut允许这样做,而&mut不允许这样做,我最好的猜测是'static促销是在尽最大努力的基础上进行的,而&mut只是没有被任何判断所发现.你可能会寻找或提交一个描述情况的问题.

Rust相关问答推荐

从特征实现调用函数的Rust惯用方法

关于如何初始化弱 struct 字段的语法问题

在Rust中是否可以使用Rc自动化约束传播

如何修复数组中NewType导致的运行时开销

当发送方分配给静态时,Tokio MPSC关闭通道

获取与父字符串相关的&;str的原始片段

使用关联类型重写时特征的实现冲突

在运行特定测试时,如何 suppress cargo test 的空输出?

对reqwest提供的这种嵌套JSON struct 进行反序列化

为什么不';t(&;mut-iter).take(n)取得iter的所有权?

闭包返回类型的生命周期规范

如何保存指向持有引用数据的指针?

Rust 中的 Option as_ref 和 as_deref 有什么不同

使用 rust 在 google cloud run (docker) 中访问环境变量的适当方法

`use std::error::Error` 声明中断编译

我如何将 google_gmail1::Gmail> 传递给线程生成?

我如何将特征作为 struct 的拥有字段?

使用 `.` 将 T 转换为 &mut T?

为什么 Rust 标准库同时为 Thing 和 &Thing 实现特征?

为什么 Rust 中的关联类型需要明确的生命周期注释?