@@ -383,71 +383,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
383
383
. collect ( )
384
384
}
385
385
386
- /// Create the decision tree for the match expression, starting from `block`.
387
- ///
388
- /// Modifies `candidates` to store the bindings and type ascriptions for
389
- /// that candidate.
390
- fn lower_match_tree < ' pat > (
391
- & mut self ,
392
- block : BasicBlock ,
393
- scrutinee_span : Span ,
394
- scrutinee_place_builder : & PlaceBuilder < ' tcx > ,
395
- match_start_span : Span ,
396
- candidates : & mut [ & mut Candidate < ' pat , ' tcx > ] ,
397
- ) {
398
- // See the doc comment on `match_candidates` for why we have an
399
- // otherwise block. Match checking will ensure this is actually
400
- // unreachable.
401
- let otherwise_block = self . cfg . start_new_block ( ) ;
402
-
403
- // This will generate code to test scrutinee_place and
404
- // branch to the appropriate arm block
405
- self . match_candidates ( match_start_span, scrutinee_span, block, otherwise_block, candidates) ;
406
-
407
- let source_info = self . source_info ( scrutinee_span) ;
408
-
409
- // Matching on a `scrutinee_place` with an uninhabited type doesn't
410
- // generate any memory reads by itself, and so if the place "expression"
411
- // contains unsafe operations like raw pointer dereferences or union
412
- // field projections, we wouldn't know to require an `unsafe` block
413
- // around a `match` equivalent to `std::intrinsics::unreachable()`.
414
- // See issue #47412 for this hole being discovered in the wild.
415
- //
416
- // HACK(eddyb) Work around the above issue by adding a dummy inspection
417
- // of `scrutinee_place`, specifically by applying `ReadForMatch`.
418
- //
419
- // NOTE: ReadForMatch also checks that the scrutinee is initialized.
420
- // This is currently needed to not allow matching on an uninitialized,
421
- // uninhabited value. If we get never patterns, those will check that
422
- // the place is initialized, and so this read would only be used to
423
- // check safety.
424
- let cause_matched_place = FakeReadCause :: ForMatchedPlace ( None ) ;
425
-
426
- if let Some ( scrutinee_place) = scrutinee_place_builder. try_to_place ( self ) {
427
- self . cfg . push_fake_read (
428
- otherwise_block,
429
- source_info,
430
- cause_matched_place,
431
- scrutinee_place,
432
- ) ;
433
- }
434
-
435
- self . cfg . terminate ( otherwise_block, source_info, TerminatorKind :: Unreachable ) ;
436
-
437
- // Link each leaf candidate to the `pre_binding_block` of the next one.
438
- let mut previous_candidate: Option < & mut Candidate < ' _ , ' _ > > = None ;
439
-
440
- for candidate in candidates {
441
- candidate. visit_leaves ( |leaf_candidate| {
442
- if let Some ( ref mut prev) = previous_candidate {
443
- assert ! ( leaf_candidate. false_edge_start_block. is_some( ) ) ;
444
- prev. next_candidate_start_block = leaf_candidate. false_edge_start_block ;
445
- }
446
- previous_candidate = Some ( leaf_candidate) ;
447
- } ) ;
448
- }
449
- }
450
-
451
386
/// Lower the bindings, guards and arm bodies of a `match` expression.
452
387
///
453
388
/// The decision tree should have already been created
@@ -1289,6 +1224,70 @@ pub(crate) struct ArmHasGuard(pub(crate) bool);
1289
1224
// Main matching algorithm
1290
1225
1291
1226
impl < ' a , ' tcx > Builder < ' a , ' tcx > {
1227
+ /// The entrypoint of the matching algorithm. Create the decision tree for the match expression,
1228
+ /// starting from `block`.
1229
+ ///
1230
+ /// Modifies `candidates` to store the bindings and type ascriptions for
1231
+ /// that candidate.
1232
+ fn lower_match_tree < ' pat > (
1233
+ & mut self ,
1234
+ block : BasicBlock ,
1235
+ scrutinee_span : Span ,
1236
+ scrutinee_place_builder : & PlaceBuilder < ' tcx > ,
1237
+ match_start_span : Span ,
1238
+ candidates : & mut [ & mut Candidate < ' pat , ' tcx > ] ,
1239
+ ) {
1240
+ // See the doc comment on `match_candidates` for why we have an
1241
+ // otherwise block. Match checking will ensure this is actually
1242
+ // unreachable.
1243
+ let otherwise_block = self . cfg . start_new_block ( ) ;
1244
+
1245
+ // This will generate code to test scrutinee_place and branch to the appropriate arm block
1246
+ self . match_candidates ( match_start_span, scrutinee_span, block, otherwise_block, candidates) ;
1247
+
1248
+ let source_info = self . source_info ( scrutinee_span) ;
1249
+
1250
+ // Matching on a `scrutinee_place` with an uninhabited type doesn't
1251
+ // generate any memory reads by itself, and so if the place "expression"
1252
+ // contains unsafe operations like raw pointer dereferences or union
1253
+ // field projections, we wouldn't know to require an `unsafe` block
1254
+ // around a `match` equivalent to `std::intrinsics::unreachable()`.
1255
+ // See issue #47412 for this hole being discovered in the wild.
1256
+ //
1257
+ // HACK(eddyb) Work around the above issue by adding a dummy inspection
1258
+ // of `scrutinee_place`, specifically by applying `ReadForMatch`.
1259
+ //
1260
+ // NOTE: ReadForMatch also checks that the scrutinee is initialized.
1261
+ // This is currently needed to not allow matching on an uninitialized,
1262
+ // uninhabited value. If we get never patterns, those will check that
1263
+ // the place is initialized, and so this read would only be used to
1264
+ // check safety.
1265
+ let cause_matched_place = FakeReadCause :: ForMatchedPlace ( None ) ;
1266
+
1267
+ if let Some ( scrutinee_place) = scrutinee_place_builder. try_to_place ( self ) {
1268
+ self . cfg . push_fake_read (
1269
+ otherwise_block,
1270
+ source_info,
1271
+ cause_matched_place,
1272
+ scrutinee_place,
1273
+ ) ;
1274
+ }
1275
+
1276
+ self . cfg . terminate ( otherwise_block, source_info, TerminatorKind :: Unreachable ) ;
1277
+
1278
+ // Link each leaf candidate to the `false_edge_start_block` of the next one.
1279
+ let mut previous_candidate: Option < & mut Candidate < ' _ , ' _ > > = None ;
1280
+ for candidate in candidates {
1281
+ candidate. visit_leaves ( |leaf_candidate| {
1282
+ if let Some ( ref mut prev) = previous_candidate {
1283
+ assert ! ( leaf_candidate. false_edge_start_block. is_some( ) ) ;
1284
+ prev. next_candidate_start_block = leaf_candidate. false_edge_start_block ;
1285
+ }
1286
+ previous_candidate = Some ( leaf_candidate) ;
1287
+ } ) ;
1288
+ }
1289
+ }
1290
+
1292
1291
/// The main match algorithm. It begins with a set of candidates
1293
1292
/// `candidates` and has the job of generating code to determine
1294
1293
/// which of these candidates, if any, is the correct one. The
0 commit comments