众所周知,值如果没有被绑定到变量上,那么在当前语句结束后就会失效。 但是根据查阅Rust参考中的临时生命周期扩展,得知在某些情况下会扩展临时变量的生命周期。
但是感觉它这个描述有点乱,看半天还是搞不清到底哪些能扩展哪些不能扩展。
比如下面的示例:
use std::ops::Index;
fn main() {
let s1 = String::from("foo").trim();
// 取消注释,则上面这行报错
// println!("{s1}");
let s2 = &String::from("foo");
println!("{s2}");
let s3 = &String::from("baz")[1..2];
println!("{s3}");
let s4 = (&String::from("foo")).index(1..2);
// 取消注释,则上面这行报错
// println!("{s4}");
}
特别是s3
和s4
,按理说[]
就是index
的重载,也同样获取了一个切片,但是s3
可以,s4
就不行。
有没有大佬能简洁的解答一下
1
共 5 条评论, 1 页
评论区
写评论了解了,感谢大佬,不在这种细节上纠结了
--
👇
苦瓜小仔: 已经有 PR 了,但还没合并,在等审核,主要负责这个功能的有中国开发者。
可能会在 edition 2024 落地吧。无论如何这需要一个 edition,因为这影响了现有代码,但该提案会保证在新规则之下有方式重写回当前的 edition 2021 的行为。
edition 2021 的临时生命周期拓展行为就是你链接的 Reference 那个地方(以及 Mara 的那篇文章描写的)。
这只是一个很小的改动,因为临时生命周期只影响临时变量(最常见的是连续方法/函数调用之中的、未被 let 绑定的变量)。
对了,
let s3 = &String::from("baz")[1..2];
中存在一个索引表达式,它的确在当前 Reference 中被指定为可拓展临时生命周期。--
👇
Binwalker: 也就是说新规则的一致性更强更统一,但是目前还在提案阶段未实现,现阶段的话还是不要过于陷入这些细节是吧?
已经有 PR 了,但还没合并,在等审核,主要负责这个功能的有中国开发者。
可能会在 edition 2024 落地吧。无论如何这需要一个 edition,因为这影响了现有代码,但该提案会保证在新规则之下有方式重写回当前的 edition 2021 的行为。
edition 2021 的临时生命周期拓展行为就是你链接的 Reference 那个地方(以及 Mara 的那篇文章描写的)。
这只是一个很小的改动,因为临时生命周期只影响临时变量(最常见的是连续方法/函数调用之中的、未被 let 绑定的变量)。
对了,
let s3 = &String::from("baz")[1..2];
中存在一个索引表达式,它的确在当前 Reference 中被指定为可拓展临时生命周期。--
👇
Binwalker: 也就是说新规则的一致性更强更统一,但是目前还在提案阶段未实现,现阶段的话还是不要过于陷入这些细节是吧?
感谢大佬回复,也就是说新规则的一致性更强更统一,但是目前还在提案阶段未实现,现阶段的话还是不要过于陷入这些细节是吧?
--
👇
苦瓜小仔: 补充一点(通过从那两个链接中提取的对 OP 直接相关的部分, i.e. 重复链接到那两个链接的子标题而已,因为我知道大部分人没兴趣看全文):
temporary lifetime 有不一致的规则,具体对于 let 语句,表现为
这在 draft RFC 中有总结当前的规则,在这 Rust 2021 temporary value extension rule for variable bindings.
显然
&temprary()[...]
不在上述之列,不过也不难从结果推测它属于可拓展的情况,而&temprary().index(...)
属于temporary().f()
连续调用这种不拓展的情况。(温馨提示:其他语句(涉及 match/if-let)的情况,与这里的 let 语句也不一样。)
无论怎样,都不要依赖这些当前细节,提议的新规则才是重点,根据我的理解(说错不负责),新规则之下,let 语句时,以上 Extended 和 Not extended 都将统一成 Extended ;至于 match/if-let 语句,在 scrutinee 位置上允许拓展临时生命周期,并且中途的临时变量在进入其分支之前被 drop。
补充一点(通过从那两个链接中提取的对 OP 直接相关的部分, i.e. 重复链接到那两个链接的子标题而已,因为我知道大部分人没兴趣看全文):
temporary lifetime 有不一致的规则,具体对于 let 语句,表现为
这在 draft RFC 中有总结当前的规则,在这 Rust 2021 temporary value extension rule for variable bindings.
显然
&temprary()[...]
不在上述之列,不过也不难从结果推测它属于可拓展的情况,而&temprary().index(...)
属于temporary().f()
连续调用这种不拓展的情况。(温馨提示:其他语句(涉及 match/if-let)的情况,与这里的 let 语句也不一样。)
无论怎样,都不要依赖这些当前细节,提议的新规则才是重点,根据我的理解(说错不负责),新规则之下,let 语句时,以上 Extended 和 Not extended 都将统一成 Extended ;至于 match/if-let 语句,在 scrutinee 位置上允许拓展临时生命周期,并且中途的临时变量在进入其分支之前被 drop。
没有简洁的回答,当前临时生命周期的规则就是不一致。想详细知道更多,去看
我的总结是,基于当前规则,出错的原因是因为连续的调用之中产生的临时变量在赋值语句末尾 drop(或者说,复杂情况时,编译器不会拓展临时作用域);通过的原因是,对于简单的赋值情况,编译器选择拓展临时作用域(let s2 = &String::from("foo"); 和 &String::from("baz")[1..2] 被视为简单情况,尤其对于后者,我怀疑索引是简单的 primitive 操作,所以通过,相应的 (&String::from("foo")).index(1..2) 不是 primitive 操作,所以不行)。