@@ -157,7 +157,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
157
157
/// [ 0. Pre-match ]
158
158
/// |
159
159
/// [ 1. Evaluate Scrutinee (expression being matched on) ]
160
- /// [ (fake read of scrutinee) ]
160
+ /// [ (PlaceMention of scrutinee) ]
161
161
/// |
162
162
/// [ 2. Decision tree -- check discriminants ] <--------+
163
163
/// | |
@@ -184,7 +184,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
184
184
///
185
185
/// We generate MIR in the following steps:
186
186
///
187
- /// 1. Evaluate the scrutinee and add the fake read of it ([Builder::lower_scrutinee]).
187
+ /// 1. Evaluate the scrutinee and add the PlaceMention of it ([Builder::lower_scrutinee]).
188
188
/// 2. Create the decision tree ([Builder::lower_match_tree]).
189
189
/// 3. Determine the fake borrows that are needed from the places that were
190
190
/// matched against and create the required temporaries for them
@@ -223,6 +223,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
223
223
let fake_borrow_temps = self . lower_match_tree (
224
224
block,
225
225
scrutinee_span,
226
+ & scrutinee_place,
226
227
match_start_span,
227
228
match_has_guard,
228
229
& mut candidates,
@@ -238,34 +239,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
238
239
)
239
240
}
240
241
241
- /// Evaluate the scrutinee and add the fake read of it.
242
+ /// Evaluate the scrutinee and add the PlaceMention for it.
242
243
fn lower_scrutinee (
243
244
& mut self ,
244
245
mut block : BasicBlock ,
245
246
scrutinee : & Expr < ' tcx > ,
246
247
scrutinee_span : Span ,
247
248
) -> BlockAnd < PlaceBuilder < ' tcx > > {
248
249
let scrutinee_place_builder = unpack ! ( block = self . as_place_builder( block, scrutinee) ) ;
249
- // Matching on a `scrutinee_place` with an uninhabited type doesn't
250
- // generate any memory reads by itself, and so if the place "expression"
251
- // contains unsafe operations like raw pointer dereferences or union
252
- // field projections, we wouldn't know to require an `unsafe` block
253
- // around a `match` equivalent to `std::intrinsics::unreachable()`.
254
- // See issue #47412 for this hole being discovered in the wild.
255
- //
256
- // HACK(eddyb) Work around the above issue by adding a dummy inspection
257
- // of `scrutinee_place`, specifically by applying `ReadForMatch`.
258
- //
259
- // NOTE: ReadForMatch also checks that the scrutinee is initialized.
260
- // This is currently needed to not allow matching on an uninitialized,
261
- // uninhabited value. If we get never patterns, those will check that
262
- // the place is initialized, and so this read would only be used to
263
- // check safety.
264
- let cause_matched_place = FakeReadCause :: ForMatchedPlace ( None ) ;
265
- let source_info = self . source_info ( scrutinee_span) ;
266
-
267
250
if let Some ( scrutinee_place) = scrutinee_place_builder. try_to_place ( self ) {
268
- self . cfg . push_fake_read ( block, source_info, cause_matched_place, scrutinee_place) ;
251
+ let source_info = self . source_info ( scrutinee_span) ;
252
+ self . cfg . push_place_mention ( block, source_info, scrutinee_place) ;
269
253
}
270
254
271
255
block. and ( scrutinee_place_builder)
@@ -304,6 +288,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
304
288
& mut self ,
305
289
block : BasicBlock ,
306
290
scrutinee_span : Span ,
291
+ scrutinee_place_builder : & PlaceBuilder < ' tcx > ,
307
292
match_start_span : Span ,
308
293
match_has_guard : bool ,
309
294
candidates : & mut [ & mut Candidate < ' pat , ' tcx > ] ,
@@ -331,6 +316,33 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
331
316
// otherwise block. Match checking will ensure this is actually
332
317
// unreachable.
333
318
let source_info = self . source_info ( scrutinee_span) ;
319
+
320
+ // Matching on a `scrutinee_place` with an uninhabited type doesn't
321
+ // generate any memory reads by itself, and so if the place "expression"
322
+ // contains unsafe operations like raw pointer dereferences or union
323
+ // field projections, we wouldn't know to require an `unsafe` block
324
+ // around a `match` equivalent to `std::intrinsics::unreachable()`.
325
+ // See issue #47412 for this hole being discovered in the wild.
326
+ //
327
+ // HACK(eddyb) Work around the above issue by adding a dummy inspection
328
+ // of `scrutinee_place`, specifically by applying `ReadForMatch`.
329
+ //
330
+ // NOTE: ReadForMatch also checks that the scrutinee is initialized.
331
+ // This is currently needed to not allow matching on an uninitialized,
332
+ // uninhabited value. If we get never patterns, those will check that
333
+ // the place is initialized, and so this read would only be used to
334
+ // check safety.
335
+ let cause_matched_place = FakeReadCause :: ForMatchedPlace ( None ) ;
336
+
337
+ if let Some ( scrutinee_place) = scrutinee_place_builder. try_to_place ( self ) {
338
+ self . cfg . push_fake_read (
339
+ otherwise_block,
340
+ source_info,
341
+ cause_matched_place,
342
+ scrutinee_place,
343
+ ) ;
344
+ }
345
+
334
346
self . cfg . terminate ( otherwise_block, source_info, TerminatorKind :: Unreachable ) ;
335
347
}
336
348
@@ -599,13 +611,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
599
611
}
600
612
601
613
_ => {
602
- let place_builder = unpack ! ( block = self . as_place_builder( block, initializer) ) ;
603
-
604
- if let Some ( place) = place_builder. try_to_place ( self ) {
605
- let source_info = self . source_info ( initializer. span ) ;
606
- self . cfg . push_place_mention ( block, source_info, place) ;
607
- }
608
-
614
+ let place_builder =
615
+ unpack ! ( block = self . lower_scrutinee( block, initializer, initializer. span) ) ;
609
616
self . place_into_pattern ( block, & irrefutable_pat, place_builder, true )
610
617
}
611
618
}
@@ -622,6 +629,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
622
629
let fake_borrow_temps = self . lower_match_tree (
623
630
block,
624
631
irrefutable_pat. span ,
632
+ & initializer,
625
633
irrefutable_pat. span ,
626
634
false ,
627
635
& mut [ & mut candidate] ,
@@ -1841,6 +1849,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1841
1849
let fake_borrow_temps = self . lower_match_tree (
1842
1850
block,
1843
1851
pat. span ,
1852
+ & expr_place_builder,
1844
1853
pat. span ,
1845
1854
false ,
1846
1855
& mut [ & mut guard_candidate, & mut otherwise_candidate] ,
@@ -2342,6 +2351,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
2342
2351
let fake_borrow_temps = this. lower_match_tree (
2343
2352
block,
2344
2353
initializer_span,
2354
+ & scrutinee,
2345
2355
pattern. span ,
2346
2356
false ,
2347
2357
& mut [ & mut candidate, & mut wildcard] ,
0 commit comments