为什么 &14 in a = &14 只存在一个语句?

Why does &14 in a = &14 only live one statement?

我不明白为什么会这样:

let mut i = &14;

而这不是:

let mut i;
i = &14;

在这种情况下,为什么 &14 没有自动获取 i 的生命周期? "something = some new thing with lifetime of only one statement" 什么时候有用?

这是 let 行为方式和表达式行为方式之间的边缘情况。基本上,let 是这里的特例。

在第一个示例中,Rust 知道您正在引用堆栈分配的 i32

在第二种情况下,您引入了一个绑定,但随后尝试使用赋值表达式来更新该绑定。因为它只是一个正则表达式,它创建的东西会在表达式末尾超出范围,因此,14 这里只有表达式的生命周期,而不是堆栈帧。

我相信 let 有一个普通 = 还没有的特殊情况,其中直接分配给绑定的引用适用于最近的封闭块(大约值在下一个 } 时被销毁),而不是像通常那样只销毁最近的封闭语句(大约,该值在下一个 ; 时被销毁)。这解释了当前的错误消息:

<anon>:3:10: 3:12 error: borrowed value does not live long enough
<anon>:3     i = &14;
                  ^~
<anon>:2:14: 4:2 note: reference must be valid for the block suffix following statement 0 at 2:13...
<anon>:2     let mut i;
<anon>:3     i = &14;
<anon>:4 }
<anon>:3:5: 3:13 note: ...but borrowed value is only valid for the statement at 3:4
<anon>:3     i = &14;
             ^~~~~~~~
<anon>:3:5: 3:13 help: consider using a `let` binding to increase its lifetime
<anon>:3     i = &14;
             ^~~~~~~~

也就是说,这也与新的析构函数更改相互作用,其中数据声明的精确排序对于确保引用安全很重要。 &14 表达式当前表示 let tmp = 14; &tmp,因此进行脱糖会得到

fn main() {
    let mut i;
    let tmp = 14;
    i = &tmp;
}

无法使用

编译
<anon>:4:10: 4:13 error: `tmp` does not live long enough
<anon>:4     i = &tmp;
                  ^~~
<anon>:2:14: 5:2 note: reference must be valid for the block suffix following statement 0 at 2:13...
<anon>:2     let mut i;
<anon>:3     let tmp = 14;
<anon>:4     i = &tmp;
<anon>:5 }
<anon>:3:17: 5:2 note: ...but borrowed value is only valid for the block suffix following statement 1 at 3:16
<anon>:3     let tmp = 14;
<anon>:4     i = &tmp;
<anon>:5 }

The RFC 包含很多细节,但是,总而言之,为了确保泛型析构函数的安全,任何带有引用的数据都必须指向严格比自身长寿的东西,其中 "outlives" 被认为是在语句级别。在这种情况下,tmp 是在 i 之后声明的,因此 i 包含指向它的指针是非法的。

顺便说一下,有些更改可能会导致此代码无法编译。 14 是常量数据,所以它可以放在静态内存中,这意味着 &14 可以是 &'static i32 而不仅仅是 &'short_stack_lifetime i32。代码的两个版本都是有效的。这是RFC issue #827.