@@ -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