Skip to content

Commit

Permalink
Rollup merge of rust-lang#127159 - Nadrieril:hide-candidate, r=matthe…
Browse files Browse the repository at this point in the history
…wjasper

match lowering: Hide `Candidate` from outside the lowering algorithm

The internals of `Candidate` are tricky and a source of confusion. This PR makes it so we don't expose `Candidate`s outside the lowering algorithm. Now:
- false edges are handled in `lower_match_tree`;
- `lower_match_tree` takes a list of patterns as input;
- `lower_match_tree` returns a flat datastructure that contains only the necessary information.

r? `@matthewjasper`
  • Loading branch information
matthiaskrgr authored Jul 31, 2024
2 parents 82bcc42 + 08bcc01 commit 10f2ff2
Show file tree
Hide file tree
Showing 54 changed files with 971 additions and 907 deletions.
460 changes: 279 additions & 181 deletions compiler/rustc_mir_build/src/build/matches/mod.rs

Large diffs are not rendered by default.

78 changes: 14 additions & 64 deletions compiler/rustc_mir_build/src/build/matches/util.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use std::marker::PhantomData;

use rustc_data_structures::fx::FxIndexMap;
use rustc_middle::mir::*;
use rustc_middle::ty::Ty;
Expand All @@ -18,18 +16,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
&mut self,
from_block: BasicBlock,
real_target: BasicBlock,
imaginary_target: Option<BasicBlock>,
imaginary_target: BasicBlock,
source_info: SourceInfo,
) {
match imaginary_target {
Some(target) if target != real_target => {
self.cfg.terminate(
from_block,
source_info,
TerminatorKind::FalseEdge { real_target, imaginary_target: target },
);
}
_ => self.cfg.goto(from_block, source_info, real_target),
if imaginary_target != real_target {
self.cfg.terminate(
from_block,
source_info,
TerminatorKind::FalseEdge { real_target, imaginary_target },
);
} else {
self.cfg.goto(from_block, source_info, real_target)
}
}
}
Expand Down Expand Up @@ -71,10 +68,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
/// a MIR pass run after borrow checking.
pub(super) fn collect_fake_borrows<'tcx>(
cx: &mut Builder<'_, 'tcx>,
candidates: &[&mut Candidate<'_, 'tcx>],
candidates: &[Candidate<'_, 'tcx>],
temp_span: Span,
scrutinee_base: PlaceBase,
) -> Vec<(Place<'tcx>, Local, FakeBorrowKind)> {
if candidates.iter().all(|candidate| !candidate.has_guard) {
// Fake borrows are only used when there is a guard.
return Vec::new();
}
let mut collector =
FakeBorrowCollector { cx, scrutinee_base, fake_borrows: FxIndexMap::default() };
for candidate in candidates.iter() {
Expand Down Expand Up @@ -222,57 +223,6 @@ impl<'a, 'b, 'tcx> FakeBorrowCollector<'a, 'b, 'tcx> {
}
}

/// Visit all the bindings of these candidates. Because or-alternatives bind the same variables, we
/// only explore the first one of each or-pattern.
pub(super) fn visit_bindings<'tcx>(
candidates: &[&mut Candidate<'_, 'tcx>],
f: impl FnMut(&Binding<'tcx>),
) {
let mut visitor = BindingsVisitor { f, phantom: PhantomData };
for candidate in candidates.iter() {
visitor.visit_candidate(candidate);
}
}

pub(super) struct BindingsVisitor<'tcx, F> {
f: F,
phantom: PhantomData<&'tcx ()>,
}

impl<'tcx, F> BindingsVisitor<'tcx, F>
where
F: FnMut(&Binding<'tcx>),
{
fn visit_candidate(&mut self, candidate: &Candidate<'_, 'tcx>) {
for binding in &candidate.extra_data.bindings {
(self.f)(binding)
}
for match_pair in &candidate.match_pairs {
self.visit_match_pair(match_pair);
}
}

fn visit_flat_pat(&mut self, flat_pat: &FlatPat<'_, 'tcx>) {
for binding in &flat_pat.extra_data.bindings {
(self.f)(binding)
}
for match_pair in &flat_pat.match_pairs {
self.visit_match_pair(match_pair);
}
}

fn visit_match_pair(&mut self, match_pair: &MatchPairTree<'_, 'tcx>) {
if let TestCase::Or { pats, .. } = &match_pair.test_case {
// All the or-alternatives should bind the same locals, so we only visit the first one.
self.visit_flat_pat(&pats[0])
} else {
for subpair in &match_pair.subpairs {
self.visit_match_pair(subpair);
}
}
}
}

#[must_use]
pub(crate) fn ref_pat_borrow_kind(ref_mutability: Mutability) -> BorrowKind {
match ref_mutability {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ fn full_tested_match() -> () {
}

bb2: {
falseEdge -> [real: bb7, imaginary: bb3];
falseEdge -> [real: bb8, imaginary: bb3];
}

bb3: {
falseEdge -> [real: bb12, imaginary: bb5];
falseEdge -> [real: bb7, imaginary: bb5];
}

bb4: {
Expand All @@ -50,26 +50,41 @@ fn full_tested_match() -> () {

bb5: {
_1 = (const 3_i32, const 3_i32);
goto -> bb13;
goto -> bb14;
}

bb6: {
goto -> bb1;
}

bb7: {
StorageLive(_9);
_9 = ((_2 as Some).0: i32);
StorageLive(_10);
_10 = _9;
_1 = (const 2_i32, move _10);
StorageDead(_10);
StorageDead(_9);
goto -> bb14;
}

bb8: {
StorageLive(_6);
_6 = &((_2 as Some).0: i32);
_3 = &fake shallow _2;
StorageLive(_7);
_7 = guard() -> [return: bb8, unwind: bb15];
_7 = guard() -> [return: bb10, unwind: bb16];
}

bb8: {
switchInt(move _7) -> [0: bb10, otherwise: bb9];
bb9: {
goto -> bb3;
}

bb9: {
bb10: {
switchInt(move _7) -> [0: bb12, otherwise: bb11];
}

bb11: {
StorageDead(_7);
FakeRead(ForMatchGuard, _3);
FakeRead(ForGuardBinding, _6);
Expand All @@ -81,44 +96,33 @@ fn full_tested_match() -> () {
StorageDead(_8);
StorageDead(_5);
StorageDead(_6);
goto -> bb13;
goto -> bb14;
}

bb10: {
goto -> bb11;
bb12: {
goto -> bb13;
}

bb11: {
bb13: {
StorageDead(_7);
StorageDead(_6);
goto -> bb3;
}

bb12: {
StorageLive(_9);
_9 = ((_2 as Some).0: i32);
StorageLive(_10);
_10 = _9;
_1 = (const 2_i32, move _10);
StorageDead(_10);
StorageDead(_9);
goto -> bb13;
goto -> bb9;
}

bb13: {
bb14: {
PlaceMention(_1);
StorageDead(_2);
StorageDead(_1);
_0 = const ();
return;
}

bb14: {
bb15: {
FakeRead(ForMatchedPlace(None), _1);
unreachable;
}

bb15 (cleanup): {
bb16 (cleanup): {
resume;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ fn full_tested_match2() -> () {
}

bb2: {
falseEdge -> [real: bb7, imaginary: bb5];
falseEdge -> [real: bb8, imaginary: bb5];
}

bb3: {
Expand All @@ -48,34 +48,43 @@ fn full_tested_match2() -> () {
_1 = (const 2_i32, move _10);
StorageDead(_10);
StorageDead(_9);
goto -> bb13;
goto -> bb14;
}

bb4: {
goto -> bb1;
}

bb5: {
falseEdge -> [real: bb12, imaginary: bb3];
falseEdge -> [real: bb7, imaginary: bb3];
}

bb6: {
goto -> bb1;
}

bb7: {
_1 = (const 3_i32, const 3_i32);
goto -> bb14;
}

bb8: {
StorageLive(_6);
_6 = &((_2 as Some).0: i32);
_3 = &fake shallow _2;
StorageLive(_7);
_7 = guard() -> [return: bb8, unwind: bb15];
_7 = guard() -> [return: bb10, unwind: bb16];
}

bb8: {
switchInt(move _7) -> [0: bb10, otherwise: bb9];
bb9: {
falseEdge -> [real: bb3, imaginary: bb5];
}

bb9: {
bb10: {
switchInt(move _7) -> [0: bb12, otherwise: bb11];
}

bb11: {
StorageDead(_7);
FakeRead(ForMatchGuard, _3);
FakeRead(ForGuardBinding, _6);
Expand All @@ -87,38 +96,33 @@ fn full_tested_match2() -> () {
StorageDead(_8);
StorageDead(_5);
StorageDead(_6);
goto -> bb13;
goto -> bb14;
}

bb10: {
goto -> bb11;
bb12: {
goto -> bb13;
}

bb11: {
bb13: {
StorageDead(_7);
StorageDead(_6);
falseEdge -> [real: bb3, imaginary: bb5];
}

bb12: {
_1 = (const 3_i32, const 3_i32);
goto -> bb13;
goto -> bb9;
}

bb13: {
bb14: {
PlaceMention(_1);
StorageDead(_2);
StorageDead(_1);
_0 = const ();
return;
}

bb14: {
bb15: {
FakeRead(ForMatchedPlace(None), _1);
unreachable;
}

bb15 (cleanup): {
bb16 (cleanup): {
resume;
}
}
Loading

0 comments on commit 10f2ff2

Please sign in to comment.