Skip to content

Commit 7a09809

Browse files
NadrierilZalathar
authored andcommitted
Move lower_match_tree
1 parent b90b346 commit 7a09809

File tree

1 file changed

+64
-65
lines changed
  • compiler/rustc_mir_build/src/build/matches

1 file changed

+64
-65
lines changed

compiler/rustc_mir_build/src/build/matches/mod.rs

Lines changed: 64 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -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

12911226
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+
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

Comments
 (0)