@@ -380,71 +380,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
380
380
. collect ( )
381
381
}
382
382
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
-
448
383
/// Lower the bindings, guards and arm bodies of a `match` expression.
449
384
///
450
385
/// The decision tree should have already been created
@@ -1275,6 +1210,70 @@ pub(crate) struct ArmHasGuard(pub(crate) bool);
1275
1210
// Main matching algorithm
1276
1211
1277
1212
impl < ' 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
+
1278
1277
/// The main match algorithm. It begins with a set of candidates
1279
1278
/// `candidates` and has the job of generating code to determine
1280
1279
/// which of these candidates, if any, is the correct one. The
0 commit comments