1
Fork 0

Process bindings and ascriptions in MatchPair::new()

This commit is contained in:
Nadrieril 2024-02-20 22:36:48 +01:00
parent a181bdc065
commit b1a0607e10
4 changed files with 77 additions and 90 deletions

View file

@ -1054,7 +1054,7 @@ struct Ascription<'tcx> {
#[derive(Debug, Clone)]
enum TestCase<'pat, 'tcx> {
Irrefutable,
Irrefutable { binding: Option<Binding<'tcx>>, ascription: Option<Ascription<'tcx>> },
Variant { adt_def: ty::AdtDef<'tcx>, variant_index: VariantIdx },
Constant { value: mir::Const<'tcx> },
Range(&'pat PatRange<'tcx>),

View file

@ -15,9 +15,7 @@
use crate::build::expr::as_place::PlaceBuilder;
use crate::build::matches::{Ascription, Binding, Candidate, MatchPair, TestCase};
use crate::build::Builder;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_middle::thir::{self, *};
use rustc_middle::ty;
use rustc_middle::thir::{Pat, PatKind};
use std::mem;
@ -128,79 +126,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
ascriptions: &mut Vec<Ascription<'tcx>>,
match_pairs: &mut Vec<MatchPair<'pat, 'tcx>>,
) -> Result<(), MatchPair<'pat, 'tcx>> {
// Collect bindings and ascriptions.
match match_pair.pattern.kind {
PatKind::AscribeUserType {
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) {
ascriptions.push(Ascription {
annotation: annotation.clone(),
source,
variance,
});
}
if let TestCase::Irrefutable { binding, ascription } = match_pair.test_case {
if let Some(binding) = binding {
bindings.push(binding);
}
PatKind::Binding {
name: _,
mutability: _,
mode,
var,
ty: _,
subpattern: _,
is_primary: _,
} => {
if let Some(source) = match_pair.place.try_to_place(self) {
bindings.push(Binding {
span: match_pair.pattern.span,
source,
var_id: var,
binding_mode: mode,
});
}
if let Some(ascription) = ascription {
ascriptions.push(ascription);
}
PatKind::InlineConstant { subpattern: ref pattern, def } => {
// Apply a type ascription for the inline constant to the value at `match_pair.place`
if let Some(source) = match_pair.place.try_to_place(self) {
let span = match_pair.pattern.span;
let parent_id = self.tcx.typeck_root_def_id(self.def_id.to_def_id());
let args = ty::InlineConstArgs::new(
self.tcx,
ty::InlineConstArgsParts {
parent_args: ty::GenericArgs::identity_for_item(self.tcx, parent_id),
ty: self.infcx.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::MiscVariable,
span,
}),
},
)
.args;
let user_ty =
self.infcx.canonicalize_user_type_annotation(ty::UserType::TypeOf(
def.to_def_id(),
ty::UserArgs { args, user_self_ty: None },
));
let annotation = ty::CanonicalUserTypeAnnotation {
inferred_ty: pattern.ty,
span,
user_ty: Box::new(user_ty),
};
ascriptions.push(Ascription {
annotation,
source,
variance: ty::Contravariant,
});
}
}
_ => {}
}
if let TestCase::Irrefutable = match_pair.test_case {
// Simplifiable pattern; we replace it with its subpairs.
match_pairs.append(&mut match_pair.subpairs);
Ok(())

View file

@ -60,7 +60,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
TestCase::Or { .. } => bug!("or-patterns should have already been handled"),
TestCase::Irrefutable => span_bug!(
TestCase::Irrefutable { .. } => span_bug!(
match_pair.pattern.span,
"simplifiable pattern found: {:?}",
match_pair.pattern

View file

@ -1,8 +1,9 @@
use crate::build::expr::as_place::{PlaceBase, PlaceBuilder};
use crate::build::matches::{MatchPair, TestCase};
use crate::build::Builder;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_middle::mir::*;
use rustc_middle::thir::*;
use rustc_middle::thir::{self, *};
use rustc_middle::ty;
use rustc_middle::ty::TypeVisitableExt;
@ -116,14 +117,15 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
place = place.project(ProjectionElem::OpaqueCast(pattern.ty));
}
let default_irrefutable = || TestCase::Irrefutable { binding: None, ascription: None };
let mut subpairs = Vec::new();
let test_case = match pattern.kind {
PatKind::Never | PatKind::Wild | PatKind::Error(_) => TestCase::Irrefutable,
PatKind::Never | PatKind::Wild | PatKind::Error(_) => default_irrefutable(),
PatKind::Or { .. } => TestCase::Or,
PatKind::Range(ref range) => {
if range.is_full_range(cx.tcx) == Some(true) {
TestCase::Irrefutable
default_irrefutable()
} else {
TestCase::Range(range)
}
@ -131,33 +133,86 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
PatKind::Constant { value } => TestCase::Constant { value },
PatKind::AscribeUserType { ref subpattern, .. } => {
PatKind::AscribeUserType {
ascription: thir::Ascription { ref annotation, variance },
ref subpattern,
..
} => {
// Apply the type ascription to the value at `match_pair.place`
let ascription = place.try_to_place(cx).map(|source| super::Ascription {
annotation: annotation.clone(),
source,
variance,
});
subpairs.push(MatchPair::new(place.clone(), subpattern, cx));
TestCase::Irrefutable
TestCase::Irrefutable { ascription, binding: None }
}
PatKind::Binding { ref subpattern, .. } => {
PatKind::Binding {
name: _,
mutability: _,
mode,
var,
ty: _,
ref subpattern,
is_primary: _,
} => {
let binding = place.try_to_place(cx).map(|source| super::Binding {
span: pattern.span,
source,
var_id: var,
binding_mode: mode,
});
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));
}
TestCase::Irrefutable
TestCase::Irrefutable { ascription: None, binding }
}
PatKind::InlineConstant { subpattern: ref pattern, .. } => {
PatKind::InlineConstant { subpattern: ref pattern, def, .. } => {
// Apply a type ascription for the inline constant to the value at `match_pair.place`
let ascription = place.try_to_place(cx).map(|source| {
let span = pattern.span;
let parent_id = cx.tcx.typeck_root_def_id(cx.def_id.to_def_id());
let args = ty::InlineConstArgs::new(
cx.tcx,
ty::InlineConstArgsParts {
parent_args: ty::GenericArgs::identity_for_item(cx.tcx, parent_id),
ty: cx.infcx.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::MiscVariable,
span,
}),
},
)
.args;
let user_ty = cx.infcx.canonicalize_user_type_annotation(ty::UserType::TypeOf(
def.to_def_id(),
ty::UserArgs { args, user_self_ty: None },
));
let annotation = ty::CanonicalUserTypeAnnotation {
inferred_ty: pattern.ty,
span,
user_ty: Box::new(user_ty),
};
super::Ascription { annotation, source, variance: ty::Contravariant }
});
subpairs.push(MatchPair::new(place.clone(), pattern, cx));
TestCase::Irrefutable
TestCase::Irrefutable { ascription, binding: None }
}
PatKind::Array { ref prefix, ref slice, ref suffix } => {
cx.prefix_slice_suffix(&mut subpairs, &place, prefix, slice, suffix);
TestCase::Irrefutable
default_irrefutable()
}
PatKind::Slice { ref prefix, ref slice, ref suffix } => {
cx.prefix_slice_suffix(&mut subpairs, &place, prefix, slice, suffix);
if prefix.is_empty() && slice.is_some() && suffix.is_empty() {
TestCase::Irrefutable
default_irrefutable()
} else {
TestCase::Slice {
len: prefix.len() + suffix.len(),
@ -182,7 +237,7 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
}) && (adt_def.did().is_local()
|| !adt_def.is_variant_list_non_exhaustive());
if irrefutable {
TestCase::Irrefutable
default_irrefutable()
} else {
TestCase::Variant { adt_def, variant_index }
}
@ -190,13 +245,13 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
PatKind::Leaf { ref subpatterns } => {
subpairs = cx.field_match_pairs(place.clone(), subpatterns);
TestCase::Irrefutable
default_irrefutable()
}
PatKind::Deref { ref subpattern } => {
let place_builder = place.clone().deref();
subpairs.push(MatchPair::new(place_builder, subpattern, cx));
TestCase::Irrefutable
default_irrefutable()
}
};