Compute subpairs when creating match pair
This commit is contained in:
parent
d936ab63d4
commit
15072766af
2 changed files with 72 additions and 78 deletions
|
@ -131,11 +131,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
ascriptions: &mut Vec<Ascription<'tcx>>,
|
ascriptions: &mut Vec<Ascription<'tcx>>,
|
||||||
match_pairs: &mut Vec<MatchPair<'pat, 'tcx>>,
|
match_pairs: &mut Vec<MatchPair<'pat, 'tcx>>,
|
||||||
) -> Result<(), 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 {
|
match match_pair.pattern.kind {
|
||||||
|
PatKind::Leaf { .. }
|
||||||
|
| PatKind::Deref { .. }
|
||||||
|
| PatKind::Array { .. }
|
||||||
|
| PatKind::Never
|
||||||
|
| PatKind::Wild
|
||||||
|
| PatKind::Error(_) => {}
|
||||||
|
|
||||||
PatKind::AscribeUserType {
|
PatKind::AscribeUserType {
|
||||||
ref subpattern,
|
|
||||||
ascription: thir::Ascription { ref annotation, variance },
|
ascription: thir::Ascription { ref annotation, variance },
|
||||||
|
..
|
||||||
} => {
|
} => {
|
||||||
// Apply the type ascription to the value at `match_pair.place`
|
// Apply the type ascription to the value at `match_pair.place`
|
||||||
if let Some(source) = match_pair.place.try_to_place(self) {
|
if let Some(source) = match_pair.place.try_to_place(self) {
|
||||||
|
@ -145,15 +151,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
variance,
|
variance,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
match_pairs.push(MatchPair::new(match_pair.place, subpattern, self));
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
PatKind::Wild | PatKind::Error(_) => {
|
|
||||||
// nothing left to do
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PatKind::Binding {
|
PatKind::Binding {
|
||||||
|
@ -162,7 +159,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
mode,
|
mode,
|
||||||
var,
|
var,
|
||||||
ty: _,
|
ty: _,
|
||||||
ref subpattern,
|
subpattern: _,
|
||||||
is_primary: _,
|
is_primary: _,
|
||||||
} => {
|
} => {
|
||||||
if let Some(source) = match_pair.place.try_to_place(self) {
|
if let Some(source) = match_pair.place.try_to_place(self) {
|
||||||
|
@ -173,24 +170,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
binding_mode: mode,
|
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 } => {
|
PatKind::InlineConstant { subpattern: ref pattern, def } => {
|
||||||
|
@ -225,38 +204,27 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
variance: ty::Contravariant,
|
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) => {
|
PatKind::Range(ref range) => {
|
||||||
if let Some(true) = range.is_full_range(self.tcx) {
|
if range.is_full_range(self.tcx) != Some(true) {
|
||||||
// Irrefutable pattern match.
|
return Err(match_pair);
|
||||||
return Ok(());
|
|
||||||
}
|
}
|
||||||
Err(match_pair)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PatKind::Slice { ref prefix, ref slice, ref suffix } => {
|
PatKind::Slice { ref prefix, ref slice, ref suffix } => {
|
||||||
if prefix.is_empty() && slice.is_some() && suffix.is_empty() {
|
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,
|
|
||||||
);
|
|
||||||
self.simplify_match_pairs(&mut match_pair.subpairs, bindings, ascriptions);
|
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)| {
|
let irrefutable = adt_def.variants().iter_enumerated().all(|(i, v)| {
|
||||||
i == variant_index || {
|
i == variant_index || {
|
||||||
(self.tcx.features().exhaustive_patterns
|
(self.tcx.features().exhaustive_patterns
|
||||||
|
@ -268,36 +236,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}) && (adt_def.did().is_local()
|
}) && (adt_def.did().is_local()
|
||||||
|| !adt_def.is_variant_list_non_exhaustive());
|
|| !adt_def.is_variant_list_non_exhaustive());
|
||||||
if irrefutable {
|
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);
|
|
||||||
self.simplify_match_pairs(&mut match_pair.subpairs, bindings, ascriptions);
|
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 } => {
|
PatKind::Or { .. } => return Err(match_pair),
|
||||||
self.prefix_slice_suffix(match_pairs, &match_pair.place, prefix, slice, suffix);
|
}
|
||||||
|
|
||||||
|
// Simplifiable pattern; we replace it with its subpairs.
|
||||||
|
match_pairs.append(&mut match_pair.subpairs);
|
||||||
Ok(())
|
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),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,7 +96,7 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
|
||||||
pub(in crate::build) fn new(
|
pub(in crate::build) fn new(
|
||||||
mut place: PlaceBuilder<'tcx>,
|
mut place: PlaceBuilder<'tcx>,
|
||||||
pattern: &'pat Pat<'tcx>,
|
pattern: &'pat Pat<'tcx>,
|
||||||
cx: &Builder<'_, 'tcx>,
|
cx: &mut Builder<'_, 'tcx>,
|
||||||
) -> MatchPair<'pat, 'tcx> {
|
) -> MatchPair<'pat, 'tcx> {
|
||||||
// Force the place type to the pattern's type.
|
// Force the place type to the pattern's type.
|
||||||
// FIXME(oli-obk): can we use this to simplify slice/array pattern hacks?
|
// FIXME(oli-obk): can we use this to simplify slice/array pattern hacks?
|
||||||
|
@ -116,6 +116,51 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
|
||||||
if may_need_cast {
|
if may_need_cast {
|
||||||
place = place.project(ProjectionElem::OpaqueCast(pattern.ty));
|
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 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue