Skip to content

Commit

Permalink
Compute subpairs when creating match pair
Browse files Browse the repository at this point in the history
  • Loading branch information
Nadrieril committed Feb 10, 2024
1 parent 140fd08 commit 45ef29c
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 78 deletions.
101 changes: 25 additions & 76 deletions compiler/rustc_mir_build/src/build/matches/simplify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,11 +131,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
ascriptions: &mut Vec<Ascription<'tcx>>,
match_pairs: &mut Vec<MatchPair<'pat, 'tcx>>,
) -> Result<(), MatchPair<'pat, 'tcx>> {
assert!(match_pair.subpairs.is_empty(), "mustn't simplify a match pair twice");
match match_pair.pattern.kind {
PatKind::Leaf { .. }
| PatKind::Deref { .. }
| PatKind::Array { .. }
| PatKind::Never
| PatKind::Wild
| PatKind::Error(_) => {}

PatKind::AscribeUserType {
ref subpattern,
ascription: thir::Ascription { ref annotation, variance },
..
} => {
// Apply the type ascription to the value at `match_pair.place`
if let Some(source) = match_pair.place.try_to_place(self) {
Expand All @@ -145,15 +151,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
variance,
});
}

match_pairs.push(MatchPair::new(match_pair.place, subpattern, self));

Ok(())
}

PatKind::Wild | PatKind::Error(_) => {
// nothing left to do
Ok(())
}

PatKind::Binding {
Expand All @@ -162,7 +159,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
mode,
var,
ty: _,
ref subpattern,
subpattern: _,
is_primary: _,
} => {
if let Some(source) = match_pair.place.try_to_place(self) {
Expand All @@ -173,24 +170,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
binding_mode: mode,
});
}

if let Some(subpattern) = subpattern.as_ref() {
// this is the `x @ P` case; have to keep matching against `P` now
match_pairs.push(MatchPair::new(match_pair.place, subpattern, self));
}

Ok(())
}

PatKind::Never => {
// A never pattern acts like a load from the place.
// FIXME(never_patterns): load from the place
Ok(())
}

PatKind::Constant { .. } => {
// FIXME normalize patterns when possible
Err(match_pair)
}

PatKind::InlineConstant { subpattern: ref pattern, def } => {
Expand Down Expand Up @@ -225,38 +204,27 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
variance: ty::Contravariant,
});
}
match_pairs.push(MatchPair::new(match_pair.place, pattern, self));
}

Ok(())
PatKind::Constant { .. } => {
// FIXME normalize patterns when possible
return Err(match_pair);
}

PatKind::Range(ref range) => {
if let Some(true) = range.is_full_range(self.tcx) {
// Irrefutable pattern match.
return Ok(());
if range.is_full_range(self.tcx) != Some(true) {
return Err(match_pair);
}
Err(match_pair)
}

PatKind::Slice { ref prefix, ref slice, ref suffix } => {
if prefix.is_empty() && slice.is_some() && suffix.is_empty() {
// irrefutable
self.prefix_slice_suffix(match_pairs, &match_pair.place, prefix, slice, suffix);
Ok(())
} else {
self.prefix_slice_suffix(
&mut match_pair.subpairs,
&match_pair.place,
prefix,
slice,
suffix,
);
if !(prefix.is_empty() && slice.is_some() && suffix.is_empty()) {
self.simplify_match_pairs(&mut match_pair.subpairs, bindings, ascriptions);
Err(match_pair)
return Err(match_pair);
}
}

PatKind::Variant { adt_def, args, variant_index, ref subpatterns } => {
PatKind::Variant { adt_def, args, variant_index, subpatterns: _ } => {
let irrefutable = adt_def.variants().iter_enumerated().all(|(i, v)| {
i == variant_index || {
(self.tcx.features().exhaustive_patterns
Expand All @@ -268,36 +236,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
}) && (adt_def.did().is_local()
|| !adt_def.is_variant_list_non_exhaustive());
if irrefutable {
let place_builder = match_pair.place.downcast(adt_def, variant_index);
match_pairs.extend(self.field_match_pairs(place_builder, subpatterns));
Ok(())
} else {
let downcast_place = match_pair.place.clone().downcast(adt_def, variant_index); // `(x as Variant)`
match_pair.subpairs = self.field_match_pairs(downcast_place, subpatterns);
if !irrefutable {
self.simplify_match_pairs(&mut match_pair.subpairs, bindings, ascriptions);
Err(match_pair)
return Err(match_pair);
}
}

PatKind::Array { ref prefix, ref slice, ref suffix } => {
self.prefix_slice_suffix(match_pairs, &match_pair.place, prefix, slice, suffix);
Ok(())
}

PatKind::Leaf { ref subpatterns } => {
// tuple struct, match subpats (if any)
match_pairs.extend(self.field_match_pairs(match_pair.place, subpatterns));
Ok(())
}

PatKind::Deref { ref subpattern } => {
let place_builder = match_pair.place.deref();
match_pairs.push(MatchPair::new(place_builder, subpattern, self));
Ok(())
}

PatKind::Or { .. } => Err(match_pair),
PatKind::Or { .. } => return Err(match_pair),
}

// Simplifiable pattern; we replace it with its subpairs.
match_pairs.append(&mut match_pair.subpairs);
Ok(())
}
}
49 changes: 47 additions & 2 deletions compiler/rustc_mir_build/src/build/matches/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
pub(in crate::build) fn new(
mut place: PlaceBuilder<'tcx>,
pattern: &'pat Pat<'tcx>,
cx: &Builder<'_, 'tcx>,
cx: &mut Builder<'_, 'tcx>,
) -> MatchPair<'pat, 'tcx> {
// Force the place type to the pattern's type.
// FIXME(oli-obk): can we use this to simplify slice/array pattern hacks?
Expand All @@ -116,6 +116,51 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
if may_need_cast {
place = place.project(ProjectionElem::OpaqueCast(pattern.ty));
}
MatchPair { place, pattern, subpairs: Vec::new() }

let mut subpairs = Vec::new();
match pattern.kind {
PatKind::Constant { .. }
| PatKind::Range(_)
| PatKind::Or { .. }
| PatKind::Never
| PatKind::Wild
| PatKind::Error(_) => {}

PatKind::AscribeUserType { ref subpattern, .. } => {
subpairs.push(MatchPair::new(place.clone(), subpattern, cx));
}

PatKind::Binding { ref subpattern, .. } => {
if let Some(subpattern) = subpattern.as_ref() {
// this is the `x @ P` case; have to keep matching against `P` now
subpairs.push(MatchPair::new(place.clone(), subpattern, cx));
}
}

PatKind::InlineConstant { subpattern: ref pattern, .. } => {
subpairs.push(MatchPair::new(place.clone(), pattern, cx));
}

PatKind::Slice { ref prefix, ref slice, ref suffix }
| PatKind::Array { ref prefix, ref slice, ref suffix } => {
cx.prefix_slice_suffix(&mut subpairs, &place, prefix, slice, suffix);
}

PatKind::Variant { adt_def, variant_index, ref subpatterns, .. } => {
let downcast_place = place.clone().downcast(adt_def, variant_index); // `(x as Variant)`
subpairs = cx.field_match_pairs(downcast_place, subpatterns);
}

PatKind::Leaf { ref subpatterns } => {
subpairs = cx.field_match_pairs(place.clone(), subpatterns);
}

PatKind::Deref { ref subpattern } => {
let place_builder = place.clone().deref();
subpairs.push(MatchPair::new(place_builder, subpattern, cx));
}
}

MatchPair { place, pattern, subpairs }
}
}

0 comments on commit 45ef29c

Please sign in to comment.