Skip to content

Revert "Make MatchPairTree::place non-optional" #138959

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Mar 26, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions compiler/rustc_mir_build/src/builder/matches/match_pair.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,6 @@ impl<'tcx> MatchPairTree<'tcx> {
place_builder = place_builder.project(ProjectionElem::OpaqueCast(pattern.ty));
}

// Place can be none if the pattern refers to a non-captured place in a closure.
let place = place_builder.try_to_place(cx);
let mut subpairs = Vec::new();
let test_case = match pattern.kind {
Expand Down Expand Up @@ -321,7 +320,7 @@ impl<'tcx> MatchPairTree<'tcx> {
if let Some(test_case) = test_case {
// This pattern is refutable, so push a new match-pair node.
match_pairs.push(MatchPairTree {
place: place.expect("refutable patterns should always have a place to inspect"),
place,
test_case,
subpairs,
pattern_ty: pattern.ty,
Expand Down
12 changes: 10 additions & 2 deletions compiler/rustc_mir_build/src/builder/matches/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1279,7 +1279,13 @@ impl<'tcx> TestCase<'tcx> {
#[derive(Debug, Clone)]
pub(crate) struct MatchPairTree<'tcx> {
/// This place...
place: Place<'tcx>,
///
/// ---
/// This can be `None` if it referred to a non-captured place in a closure.
///
/// Invariant: Can only be `None` when `test_case` is `Or`.
/// Therefore this must be `Some(_)` after or-pattern expansion.
place: Option<Place<'tcx>>,

/// ... must pass this test...
test_case: TestCase<'tcx>,
Expand Down Expand Up @@ -2099,9 +2105,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// Extract the match-pair from the highest priority candidate
let match_pair = &candidates[0].match_pairs[0];
let test = self.pick_test_for_match_pair(match_pair);
// Unwrap is ok after simplification.
let match_place = match_pair.place.unwrap();
debug!(?test, ?match_pair);

(match_pair.place, test)
(match_place, test)
}

/// Given a test, we partition the input candidates into several buckets.
Expand Down
9 changes: 6 additions & 3 deletions compiler/rustc_mir_build/src/builder/matches/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -540,8 +540,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// than one, but it'd be very unusual to have two sides that
// both require tests; you'd expect one side to be simplified
// away.)
let (match_pair_index, match_pair) =
candidate.match_pairs.iter().enumerate().find(|&(_, mp)| mp.place == test_place)?;
let (match_pair_index, match_pair) = candidate
.match_pairs
.iter()
.enumerate()
.find(|&(_, mp)| mp.place == Some(test_place))?;

// If true, the match pair is completely entailed by its corresponding test
// branch, so it can be removed. If false, the match pair is _compatible_
Expand Down Expand Up @@ -584,7 +587,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
candidate
.match_pairs
.iter()
.any(|mp| mp.place == test_place && is_covering_range(&mp.test_case))
.any(|mp| mp.place == Some(test_place) && is_covering_range(&mp.test_case))
};
if sorted_candidates
.get(&TestBranch::Failure)
Expand Down
8 changes: 6 additions & 2 deletions compiler/rustc_mir_build/src/builder/matches/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,10 +173,14 @@ impl<'a, 'b, 'tcx> FakeBorrowCollector<'a, 'b, 'tcx> {
// }
// ```
// Hence we fake borrow using a deep borrow.
self.fake_borrow(match_pair.place, FakeBorrowKind::Deep);
if let Some(place) = match_pair.place {
self.fake_borrow(place, FakeBorrowKind::Deep);
}
} else {
// Insert a Shallow borrow of any place that is switched on.
self.fake_borrow(match_pair.place, FakeBorrowKind::Shallow);
if let Some(place) = match_pair.place {
self.fake_borrow(place, FakeBorrowKind::Shallow);
}

for subpair in &match_pair.subpairs {
self.visit_match_pair(subpair);
Expand Down
11 changes: 11 additions & 0 deletions tests/ui/closures/upvar-or-pattern-issue-138958.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//@ edition:2024
//@ check-pass

pub fn f(x: (u32, u32)) {
let _ = || {
let ((0, a) | (a, _)) = x;
a
};
}

fn main() {}
Loading