Skip to content

Commit 4a5d2a5

Browse files
add diagram to explain the MIR structure
1 parent c7d1c9b commit 4a5d2a5

File tree

1 file changed

+53
-0
lines changed
  • compiler/rustc_mir_build/src/build

1 file changed

+53
-0
lines changed

compiler/rustc_mir_build/src/build/block.rs

+53
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,59 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
132132
// failure in pattern matching.
133133
// For this reason, we declare those storages as live but we do not schedule
134134
// any drop yet- they are scheduled later after the pattern matching.
135+
// The generated MIR will have `StorageDead` whenever the control flow breaks out
136+
// of the parent scope, regardless of the result of the pattern matching.
137+
// However, the drops are inserted in MIR only when the control flow breaks out of
138+
// the scope of the remainder scope associated with this `let .. else` statement.
139+
// Pictorial explanation of the scope structure:
140+
// ┌─────────────────────────────────┐
141+
// │ Scope of the enclosing block, │
142+
// │ or the last remainder scope │
143+
// │ ┌───────────────────────────┐ │
144+
// │ │ Scope for <else> block │ │
145+
// │ └───────────────────────────┘ │
146+
// │ ┌───────────────────────────┐ │
147+
// │ │ Remainder scope of │ │
148+
// │ │ this let-else statement │ │
149+
// │ │ ┌─────────────────────┐ │ │
150+
// │ │ │ <expr> scope │ │ │
151+
// │ │ └─────────────────────┘ │ │
152+
// │ │ extended temporaries in │ │
153+
// │ │ <expr> lives in this │ │
154+
// │ │ scope │ │
155+
// │ │ ┌─────────────────────┐ │ │
156+
// │ │ │ Scopes for the rest │ │ │
157+
// │ │ └─────────────────────┘ │ │
158+
// │ └───────────────────────────┘ │
159+
// └─────────────────────────────────┘
160+
// Generated control flow:
161+
// │ let Some(x) = y() else { return; }
162+
// │
163+
// ┌────────▼───────┐
164+
// │ evaluate y() │
165+
// └────────┬───────┘
166+
// │ ┌────────────────┐
167+
// ┌────────▼───────┐ │Drop temporaries│
168+
// │Test the pattern├──────►in y() │
169+
// └────────┬───────┘ │because breaking│
170+
// │ │out of <expr> │
171+
// ┌────────▼───────┐ │scope │
172+
// │Move value into │ └───────┬────────┘
173+
// │binding x │ │
174+
// └────────┬───────┘ ┌───────▼────────┐
175+
// │ │Drop extended │
176+
// ┌────────▼───────┐ │temporaries in │
177+
// │Drop temporaries│ │<expr> because │
178+
// │in y() │ │breaking out of │
179+
// │because breaking│ │remainder scope │
180+
// │out of <expr> │ └───────┬────────┘
181+
// │scope │ │
182+
// └────────┬───────┘ ┌───────▼────────┐
183+
// │ │Enter <else> ├────────►
184+
// ┌────────▼───────┐ │block │ return;
185+
// │Continue... │ └────────────────┘
186+
// └────────────────┘
187+
135188
let ignores_expr_result = matches!(pattern.kind, PatKind::Wild);
136189
this.block_context.push(BlockFrame::Statement { ignores_expr_result });
137190

0 commit comments

Comments
 (0)