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