`&mut []` 的生命周期是否在 Rust 的生命周期分析期间被特别处理?

Zhi*_* Ma 7 rust

下面的示例代码有些精心设计,但说明了我的主要关注点。代码编译完美。

struct SliceWrapper<'a>(&'a mut[i32]);

impl<'a> SliceWrapper<'a> {
    fn clear(&mut self) {
        self.0 = &mut [];
    }
}

fn main() {
    let slice = &mut [1, 2, 3];
    let mut wrapper = SliceWrapper(slice);
    wrapper.clear();
}
Run Code Online (Sandbox Code Playgroud)

该行self.0 = &mut [];有效,但如果我们查看它们的生命周期,则非常奇怪:对局部变量的引用被分配给self.0,它存在于方法调用之外clear()

更令人困惑的是,如果我将该行更改为self.0 = &mut [0];,那么编译器会向我抛出一个错误:创建一个临时文件,该临时文件在仍在使用时被释放。

所以我猜 Rust 编译器对待生命周期的方式&mut []不同。真的吗?什么是精确的生命周期规则&mut []

Cer*_*rus 5

空数组确实是编译器的特殊情况。

这个答案描述了类似但不同的情况,共享对 constexpr 值的引用。对于这种情况,有一个 RFC可以使这个 constexpt 值“提升为静态”,即分配在静态内存中而不是堆栈中,以便它们将存在于它们定义的函数之外。

并且,在这个 RFC 中,我们有以下声明:

编译器已经将一小部分 rvalue const 表达式的特殊情况特化为具有静态生命周期——即空数组表达式:

let x: &'static [u8] = &[];
Run Code Online (Sandbox Code Playgroud)

至于可变的 - 或者,在这里更相关,独占或唯一的引用,RFC声明如下:

&'static mut只要存在引用类型为零大小的附加约束,就可以扩展对引用的支持。
...
零大小限制是因为别名可变引用仅对零大小类型是安全的(因为您永远不会取消对它们的指针的引用)。

这部分似乎没有实现,因为这段代码是无效的:

fn main() {
    let _: &'static mut [()] = &mut [()]; // fail, reference to local
}
Run Code Online (Sandbox Code Playgroud)

虽然[(); 1]是 ZST,但可以通过std::mem::size_of.