@@ -132,6 +132,59 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
132
132
// failure in pattern matching.
133
133
// For this reason, we declare those storages as live but we do not schedule
134
134
// 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
+
135
188
let ignores_expr_result = matches ! ( pattern. kind, PatKind :: Wild ) ;
136
189
this. block_context . push ( BlockFrame :: Statement { ignores_expr_result } ) ;
137
190
0 commit comments