about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDing Xiang Fei <dingxiangfei2009@protonmail.ch>2022-09-13 22:07:16 +0800
committerDing Xiang Fei <dingxiangfei2009@protonmail.ch>2022-09-15 10:08:14 +0800
commit4a5d2a561c6f82f928d6f14fe6e8f9ad2415b9a8 (patch)
tree063a71927fa6294c9f5f5fa5e4499f1c8511be45
parentc7d1c9b66fdd1cbec64a7dc263557eee895b70ef (diff)
downloadrust-4a5d2a561c6f82f928d6f14fe6e8f9ad2415b9a8.tar.gz
rust-4a5d2a561c6f82f928d6f14fe6e8f9ad2415b9a8.zip
add diagram to explain the MIR structure
-rw-r--r--compiler/rustc_mir_build/src/build/block.rs53
1 files changed, 53 insertions, 0 deletions
diff --git a/compiler/rustc_mir_build/src/build/block.rs b/compiler/rustc_mir_build/src/build/block.rs
index 8eabd925e45..7ab7870c464 100644
--- a/compiler/rustc_mir_build/src/build/block.rs
+++ b/compiler/rustc_mir_build/src/build/block.rs
@@ -132,6 +132,59 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     // failure in pattern matching.
                     // For this reason, we declare those storages as live but we do not schedule
                     // any drop yet- they are scheduled later after the pattern matching.
+                    // The generated MIR will have `StorageDead` whenever the control flow breaks out
+                    // of the parent scope, regardless of the result of the pattern matching.
+                    // However, the drops are inserted in MIR only when the control flow breaks out of
+                    // the scope of the remainder scope associated with this `let .. else` statement.
+                    // Pictorial explanation of the scope structure:
+                    // ┌─────────────────────────────────┐
+                    // │  Scope of the enclosing block,  │
+                    // │  or the last remainder scope    │
+                    // │  ┌───────────────────────────┐  │
+                    // │  │  Scope for <else> block   │  │
+                    // │  └───────────────────────────┘  │
+                    // │  ┌───────────────────────────┐  │
+                    // │  │  Remainder scope of       │  │
+                    // │  │  this let-else statement  │  │
+                    // │  │  ┌─────────────────────┐  │  │
+                    // │  │  │ <expr> scope        │  │  │
+                    // │  │  └─────────────────────┘  │  │
+                    // │  │  extended temporaries in  │  │
+                    // │  │  <expr> lives in this     │  │
+                    // │  │  scope                    │  │
+                    // │  │  ┌─────────────────────┐  │  │
+                    // │  │  │ Scopes for the rest │  │  │
+                    // │  │  └─────────────────────┘  │  │
+                    // │  └───────────────────────────┘  │
+                    // └─────────────────────────────────┘
+                    // Generated control flow:
+                    //          │ let Some(x) = y() else { return; }
+                    //          │
+                    // ┌────────▼───────┐
+                    // │ evaluate y()   │
+                    // └────────┬───────┘
+                    //          │              ┌────────────────┐
+                    // ┌────────▼───────┐      │Drop temporaries│
+                    // │Test the pattern├──────►in y()          │
+                    // └────────┬───────┘      │because breaking│
+                    //          │              │out of <expr>   │
+                    // ┌────────▼───────┐      │scope           │
+                    // │Move value into │      └───────┬────────┘
+                    // │binding x       │              │
+                    // └────────┬───────┘      ┌───────▼────────┐
+                    //          │              │Drop extended   │
+                    // ┌────────▼───────┐      │temporaries in  │
+                    // │Drop temporaries│      │<expr> because  │
+                    // │in y()          │      │breaking out of │
+                    // │because breaking│      │remainder scope │
+                    // │out of <expr>   │      └───────┬────────┘
+                    // │scope           │              │
+                    // └────────┬───────┘      ┌───────▼────────┐
+                    //          │              │Enter <else>    ├────────►
+                    // ┌────────▼───────┐      │block           │ return;
+                    // │Continue...     │      └────────────────┘
+                    // └────────────────┘
+
                     let ignores_expr_result = matches!(pattern.kind, PatKind::Wild);
                     this.block_context.push(BlockFrame::Statement { ignores_expr_result });