1
Fork 0

Match constructor first in Constructor methods

This makes it easier to add new non-standard constructors, and this also
ensures that we don't forget cases when adding a new constructor.
This commit is contained in:
Nadrieril 2019-11-12 10:36:56 +00:00
parent e3d998492a
commit eb99c73e04

View file

@ -781,18 +781,12 @@ impl<'tcx> Constructor<'tcx> {
ty: Ty<'tcx>, ty: Ty<'tcx>,
) -> Vec<Pat<'tcx>> { ) -> Vec<Pat<'tcx>> {
debug!("wildcard_subpatterns({:#?}, {:?})", self, ty); debug!("wildcard_subpatterns({:#?}, {:?})", self, ty);
match ty.kind {
match self {
Single | Variant(_) => match ty.kind {
ty::Tuple(ref fs) => { ty::Tuple(ref fs) => {
fs.into_iter().map(|t| t.expect_ty()).map(Pat::wildcard_from_ty).collect() fs.into_iter().map(|t| t.expect_ty()).map(Pat::wildcard_from_ty).collect()
} }
ty::Slice(ty) | ty::Array(ty, _) => match *self {
FixedLenSlice(length) => (0..length).map(|_| Pat::wildcard_from_ty(ty)).collect(),
VarLenSlice(prefix, suffix) => {
(0..prefix + suffix).map(|_| Pat::wildcard_from_ty(ty)).collect()
}
ConstantValue(..) => vec![],
_ => bug!("bad slice pattern {:?} {:?}", self, ty),
},
ty::Ref(_, rty, _) => vec![Pat::wildcard_from_ty(rty)], ty::Ref(_, rty, _) => vec![Pat::wildcard_from_ty(rty)],
ty::Adt(adt, substs) => { ty::Adt(adt, substs) => {
if adt.is_box() { if adt.is_box() {
@ -806,17 +800,17 @@ impl<'tcx> Constructor<'tcx> {
.fields .fields
.iter() .iter()
.map(|field| { .map(|field| {
let is_visible = let is_visible = adt.is_enum()
adt.is_enum() || field.vis.is_accessible_from(cx.module, cx.tcx); || field.vis.is_accessible_from(cx.module, cx.tcx);
let is_uninhabited = cx.is_uninhabited(field.ty(cx.tcx, substs)); let is_uninhabited = cx.is_uninhabited(field.ty(cx.tcx, substs));
match (is_visible, is_non_exhaustive, is_uninhabited) { match (is_visible, is_non_exhaustive, is_uninhabited) {
// Treat all uninhabited types in non-exhaustive variants as // Treat all uninhabited types in non-exhaustive variants as
// `TyErr`. // `TyErr`.
(_, true, true) => cx.tcx.types.err, (_, true, true) => cx.tcx.types.err,
// Treat all non-visible fields as `TyErr`. They can't appear in // Treat all non-visible fields as `TyErr`. They can't appear
// any other pattern from this match (because they are private), so // in any other pattern from this match (because they are
// their type does not matter - but we don't want to know they are // private), so their type does not matter - but we don't want
// uninhabited. // to know they are uninhabited.
(false, ..) => cx.tcx.types.err, (false, ..) => cx.tcx.types.err,
(true, ..) => { (true, ..) => {
let ty = field.ty(cx.tcx, substs); let ty = field.ty(cx.tcx, substs);
@ -840,6 +834,15 @@ impl<'tcx> Constructor<'tcx> {
} }
} }
_ => vec![], _ => vec![],
},
FixedLenSlice(_) | VarLenSlice(..) => match ty.kind {
ty::Slice(ty) | ty::Array(ty, _) => {
let arity = self.arity(cx, ty);
(0..arity).map(|_| Pat::wildcard_from_ty(ty)).collect()
}
_ => bug!("bad slice pattern {:?} {:?}", self, ty),
},
ConstantValue(..) | ConstantRange(..) => vec![],
} }
} }
@ -850,19 +853,19 @@ impl<'tcx> Constructor<'tcx> {
/// A struct pattern's arity is the number of fields it contains, etc. /// A struct pattern's arity is the number of fields it contains, etc.
fn arity<'a>(&self, cx: &MatchCheckCtxt<'a, 'tcx>, ty: Ty<'tcx>) -> u64 { fn arity<'a>(&self, cx: &MatchCheckCtxt<'a, 'tcx>, ty: Ty<'tcx>) -> u64 {
debug!("Constructor::arity({:#?}, {:?})", self, ty); debug!("Constructor::arity({:#?}, {:?})", self, ty);
match ty.kind { match self {
Single | Variant(_) => match ty.kind {
ty::Tuple(ref fs) => fs.len() as u64, ty::Tuple(ref fs) => fs.len() as u64,
ty::Slice(..) | ty::Array(..) => match *self { ty::Slice(..) | ty::Array(..) => bug!("bad slice pattern {:?} {:?}", self, ty),
FixedLenSlice(length) => length,
VarLenSlice(prefix, suffix) => prefix + suffix,
ConstantValue(..) => 0,
_ => bug!("bad slice pattern {:?} {:?}", self, ty),
},
ty::Ref(..) => 1, ty::Ref(..) => 1,
ty::Adt(adt, _) => { ty::Adt(adt, _) => {
adt.variants[self.variant_index_for_adt(cx, adt)].fields.len() as u64 adt.variants[self.variant_index_for_adt(cx, adt)].fields.len() as u64
} }
_ => 0, _ => 0,
},
FixedLenSlice(length) => *length,
VarLenSlice(prefix, suffix) => prefix + suffix,
ConstantValue(..) | ConstantRange(..) => 0,
} }
} }
@ -886,7 +889,9 @@ impl<'tcx> Constructor<'tcx> {
pats: impl IntoIterator<Item = Pat<'tcx>>, pats: impl IntoIterator<Item = Pat<'tcx>>,
) -> Pat<'tcx> { ) -> Pat<'tcx> {
let mut subpatterns = pats.into_iter(); let mut subpatterns = pats.into_iter();
let pat = match ty.kind {
let pat = match self {
Single | Variant(_) => match ty.kind {
ty::Adt(..) | ty::Tuple(..) => { ty::Adt(..) | ty::Tuple(..) => {
let subpatterns = subpatterns let subpatterns = subpatterns
.enumerate() .enumerate()
@ -908,31 +913,25 @@ impl<'tcx> Constructor<'tcx> {
PatKind::Leaf { subpatterns } PatKind::Leaf { subpatterns }
} }
} }
ty::Ref(..) => PatKind::Deref { subpattern: subpatterns.nth(0).unwrap() }, ty::Ref(..) => PatKind::Deref { subpattern: subpatterns.nth(0).unwrap() },
ty::Slice(_) | ty::Array(..) => bug!("bad slice pattern {:?} {:?}", self, ty),
ty::Slice(_) | ty::Array(..) => match self { _ => PatKind::Wild,
},
FixedLenSlice(_) => { FixedLenSlice(_) => {
PatKind::Slice { prefix: subpatterns.collect(), slice: None, suffix: vec![] } PatKind::Slice { prefix: subpatterns.collect(), slice: None, suffix: vec![] }
} }
VarLenSlice(prefix_len, _suffix_len) => { &VarLenSlice(prefix_len, _) => {
let prefix = subpatterns.by_ref().take(*prefix_len as usize).collect(); let prefix = subpatterns.by_ref().take(prefix_len as usize).collect();
let suffix = subpatterns.collect(); let suffix = subpatterns.collect();
let wild = Pat::wildcard_from_ty(ty); let wild = Pat::wildcard_from_ty(ty);
PatKind::Slice { prefix, slice: Some(wild), suffix } PatKind::Slice { prefix, slice: Some(wild), suffix }
} }
_ => bug!("bad slice pattern {:?} {:?}", self, ty), &ConstantValue(value, _) => PatKind::Constant { value },
}, &ConstantRange(lo, hi, ty, end, _) => PatKind::Range(PatRange {
_ => match *self {
ConstantValue(value, _) => PatKind::Constant { value },
ConstantRange(lo, hi, ty, end, _) => PatKind::Range(PatRange {
lo: ty::Const::from_bits(cx.tcx, lo, ty::ParamEnv::empty().and(ty)), lo: ty::Const::from_bits(cx.tcx, lo, ty::ParamEnv::empty().and(ty)),
hi: ty::Const::from_bits(cx.tcx, hi, ty::ParamEnv::empty().and(ty)), hi: ty::Const::from_bits(cx.tcx, hi, ty::ParamEnv::empty().and(ty)),
end, end,
}), }),
_ => PatKind::Wild,
},
}; };
Pat { ty, span: DUMMY_SP, kind: Box::new(pat) } Pat { ty, span: DUMMY_SP, kind: Box::new(pat) }