diff options
| author | Ding Xiang Fei <dingxiangfei2009@protonmail.ch> | 2022-09-13 22:07:16 +0800 |
|---|---|---|
| committer | Ding Xiang Fei <dingxiangfei2009@protonmail.ch> | 2022-09-15 10:08:14 +0800 |
| commit | 4a5d2a561c6f82f928d6f14fe6e8f9ad2415b9a8 (patch) | |
| tree | 063a71927fa6294c9f5f5fa5e4499f1c8511be45 | |
| parent | c7d1c9b66fdd1cbec64a7dc263557eee895b70ef (diff) | |
| download | rust-4a5d2a561c6f82f928d6f14fe6e8f9ad2415b9a8.tar.gz rust-4a5d2a561c6f82f928d6f14fe6e8f9ad2415b9a8.zip | |
add diagram to explain the MIR structure
| -rw-r--r-- | compiler/rustc_mir_build/src/build/block.rs | 53 |
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 }); |
