@@ -383,71 +383,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
383383 . collect ( )
384384 }
385385
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-
451386 /// Lower the bindings, guards and arm bodies of a `match` expression.
452387 ///
453388 /// The decision tree should have already been created
@@ -1289,6 +1224,70 @@ pub(crate) struct ArmHasGuard(pub(crate) bool);
12891224// Main matching algorithm
12901225
12911226impl < ' 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+
12921291 /// The main match algorithm. It begins with a set of candidates
12931292 /// `candidates` and has the job of generating code to determine
12941293 /// which of these candidates, if any, is the correct one. The
0 commit comments