• [Rust笔记] 研究变量生存期, 记录下 NLL 的一些反直觉行为


    NLL 导致的非直觉的作用域扩大

    1. NLL 完全无视词法作用域

    1.1. 是否可以认为 NLL 在fb.set(&b);处缩短了fb的起始生存期以配合b?
    1.2. 应该认为 NLL 缩短了fb 还是延长了b 的生存期?

    1. struct MyCell(T);
    2. impl MyCell {
    3. pub fn set(&mut self, t: T) {
    4. self.0 = t;
    5. }
    6. }
    7. let a = 3;
    8. let mut fb = MyCell(&a); // 将 fb 绑定到 a 的生存期
    9. let _ = {
    10. let b = 4;
    11. fb.set(&b);
    12. false
    13. // 直觉上 b 在此结束生存期
    14. };
    15. // 直觉上 fb 在此结束生存期
    16. // NLL 智能的使 b 和 fb 的生存期同时结束, 使得 fb 可以使用 b

    2. 强制延长外部变量生存期得到符合直觉的编译失败

    1. struct MyCell(T);
    2. impl MyCell {
    3. pub fn set(&mut self, t: T) {
    4. self.0 = t;
    5. }
    6. }
    7. let a = 3;
    8. let mut fb = MyCell(&a); // 将 fb 绑定到 a 的生存期
    9. let _ = {
    10. let b = 4;
    11. fb.set(&b);
    12. false
    13. // b 在此结束生存期
    14. };
    15. fb; // 强制延长 fb 生存期

    3. Drop导致隐式生存期延长而编译失败

    主代码与 1 完全相同, 与 1 相比仅多一个空Drop, 而编译失败原因同 2

    1. struct MyCell(T);
    2. impl MyCell {
    3. pub fn set(&mut self, t: T) {
    4. self.0 = t;
    5. }
    6. }
    7. impl Drop for MyCell {
    8. fn drop(&mut self) {}
    9. }
    10. let a = 3;
    11. let mut fb = MyCell(&a); // 将 fb 绑定到 a 的生存期
    12. let _ = {
    13. let b = 4;
    14. fb.set(&b);
    15. false
    16. // b 在此结束生存期
    17. };
    18. // drop 导致的隐式延长 fb 生存期

    4. 编译失败 循环使得fb生存期不能缩短

    有可能rust升级使其可通过编译

    1. struct MyCell(T);
    2. impl MyCell {
    3. pub fn set(&mut self, t: T) {
    4. self.0 = t;
    5. }
    6. }
    7. let a = 3;
    8. let mut fb = MyCell(&a); // 将 fb 绑定到 a 的生存期
    9. let _ = loop {
    10. // loop 使得 fb 必须在此有效 而不能使 b 满足此要求
    11. let b = 4;
    12. fb.set(&b);
    13. if true { break false }
    14. // b 在此结束生存期
    15. };
    16. // fb 在此结束生存期

    5. 编译成功 基本等同于 4

    NLL 过于智能的消除了 loop

    1. struct MyCell(T);
    2. impl MyCell {
    3. pub fn set(&mut self, t: T) {
    4. self.0 = t;
    5. }
    6. }
    7. let a = 3;
    8. let mut fb = MyCell(&a); // 将 fb 绑定到 a 的生存期
    9. let _ = loop {
    10. let b = 4;
    11. fb.set(&b);
    12. break false; // 过于智能的消除了 loop
    13. };

  • 相关阅读:
    Disruptor的事件处理机制
    Vue:生命周期(从出生到销毁)
    es6---es6新增的Bigint、Symbol数据类型,set、map数据结构
    notepad++编辑多个位置
    新能源电动汽车安全性能检测中采集车架号及BMS电池数据的难点
    【HCSD零代码云上开发】零代码入门微信小程序和物联网
    数据库、计算机网络,操作系统刷题笔记7
    机器视觉技术在现代汽车制造中的应用
    2022.11.8每日刷题打卡
    Linux进程概念
  • 原文地址:https://blog.csdn.net/u012067469/article/details/128030288