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:
parent
e3d998492a
commit
eb99c73e04
1 changed files with 104 additions and 105 deletions
|
@ -781,65 +781,68 @@ 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 {
|
|
||||||
ty::Tuple(ref fs) => {
|
match self {
|
||||||
fs.into_iter().map(|t| t.expect_ty()).map(Pat::wildcard_from_ty).collect()
|
Single | Variant(_) => match ty.kind {
|
||||||
}
|
ty::Tuple(ref fs) => {
|
||||||
ty::Slice(ty) | ty::Array(ty, _) => match *self {
|
fs.into_iter().map(|t| t.expect_ty()).map(Pat::wildcard_from_ty).collect()
|
||||||
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![],
|
ty::Ref(_, rty, _) => vec![Pat::wildcard_from_ty(rty)],
|
||||||
_ => bug!("bad slice pattern {:?} {:?}", self, ty),
|
ty::Adt(adt, substs) => {
|
||||||
},
|
if adt.is_box() {
|
||||||
ty::Ref(_, rty, _) => vec![Pat::wildcard_from_ty(rty)],
|
// Use T as the sub pattern type of Box<T>.
|
||||||
ty::Adt(adt, substs) => {
|
vec![Pat::wildcard_from_ty(substs.type_at(0))]
|
||||||
if adt.is_box() {
|
} else {
|
||||||
// Use T as the sub pattern type of Box<T>.
|
let variant = &adt.variants[self.variant_index_for_adt(cx, adt)];
|
||||||
vec![Pat::wildcard_from_ty(substs.type_at(0))]
|
let is_non_exhaustive =
|
||||||
} else {
|
variant.is_field_list_non_exhaustive() && !cx.is_local(ty);
|
||||||
let variant = &adt.variants[self.variant_index_for_adt(cx, adt)];
|
variant
|
||||||
let is_non_exhaustive =
|
.fields
|
||||||
variant.is_field_list_non_exhaustive() && !cx.is_local(ty);
|
.iter()
|
||||||
variant
|
.map(|field| {
|
||||||
.fields
|
let is_visible = adt.is_enum()
|
||||||
.iter()
|
|| field.vis.is_accessible_from(cx.module, cx.tcx);
|
||||||
.map(|field| {
|
let is_uninhabited = cx.is_uninhabited(field.ty(cx.tcx, substs));
|
||||||
let is_visible =
|
match (is_visible, is_non_exhaustive, is_uninhabited) {
|
||||||
adt.is_enum() || field.vis.is_accessible_from(cx.module, cx.tcx);
|
// Treat all uninhabited types in non-exhaustive variants as
|
||||||
let is_uninhabited = cx.is_uninhabited(field.ty(cx.tcx, substs));
|
// `TyErr`.
|
||||||
match (is_visible, is_non_exhaustive, is_uninhabited) {
|
(_, true, true) => cx.tcx.types.err,
|
||||||
// Treat all uninhabited types in non-exhaustive variants as
|
// Treat all non-visible fields as `TyErr`. They can't appear
|
||||||
// `TyErr`.
|
// in any other pattern from this match (because they are
|
||||||
(_, true, true) => cx.tcx.types.err,
|
// private), so their type does not matter - but we don't want
|
||||||
// Treat all non-visible fields as `TyErr`. They can't appear in
|
// to know they are uninhabited.
|
||||||
// any other pattern from this match (because they are private), so
|
(false, ..) => cx.tcx.types.err,
|
||||||
// their type does not matter - but we don't want to know they are
|
(true, ..) => {
|
||||||
// uninhabited.
|
let ty = field.ty(cx.tcx, substs);
|
||||||
(false, ..) => cx.tcx.types.err,
|
match ty.kind {
|
||||||
(true, ..) => {
|
// If the field type returned is an array of an unknown
|
||||||
let ty = field.ty(cx.tcx, substs);
|
// size return an TyErr.
|
||||||
match ty.kind {
|
ty::Array(_, len)
|
||||||
// If the field type returned is an array of an unknown
|
if len
|
||||||
// size return an TyErr.
|
.try_eval_usize(cx.tcx, cx.param_env)
|
||||||
ty::Array(_, len)
|
.is_none() =>
|
||||||
if len
|
{
|
||||||
.try_eval_usize(cx.tcx, cx.param_env)
|
cx.tcx.types.err
|
||||||
.is_none() =>
|
}
|
||||||
{
|
_ => ty,
|
||||||
cx.tcx.types.err
|
|
||||||
}
|
}
|
||||||
_ => ty,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
})
|
.map(Pat::wildcard_from_ty)
|
||||||
.map(Pat::wildcard_from_ty)
|
.collect()
|
||||||
.collect()
|
}
|
||||||
}
|
}
|
||||||
}
|
_ => 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 {
|
||||||
ty::Tuple(ref fs) => fs.len() as u64,
|
Single | Variant(_) => match ty.kind {
|
||||||
ty::Slice(..) | ty::Array(..) => match *self {
|
ty::Tuple(ref fs) => fs.len() as u64,
|
||||||
FixedLenSlice(length) => length,
|
ty::Slice(..) | ty::Array(..) => bug!("bad slice pattern {:?} {:?}", self, ty),
|
||||||
VarLenSlice(prefix, suffix) => prefix + suffix,
|
ty::Ref(..) => 1,
|
||||||
ConstantValue(..) => 0,
|
ty::Adt(adt, _) => {
|
||||||
_ => bug!("bad slice pattern {:?} {:?}", self, ty),
|
adt.variants[self.variant_index_for_adt(cx, adt)].fields.len() as u64
|
||||||
|
}
|
||||||
|
_ => 0,
|
||||||
},
|
},
|
||||||
ty::Ref(..) => 1,
|
FixedLenSlice(length) => *length,
|
||||||
ty::Adt(adt, _) => {
|
VarLenSlice(prefix, suffix) => prefix + suffix,
|
||||||
adt.variants[self.variant_index_for_adt(cx, adt)].fields.len() as u64
|
ConstantValue(..) | ConstantRange(..) => 0,
|
||||||
}
|
|
||||||
_ => 0,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -886,53 +889,49 @@ 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 {
|
|
||||||
ty::Adt(..) | ty::Tuple(..) => {
|
|
||||||
let subpatterns = subpatterns
|
|
||||||
.enumerate()
|
|
||||||
.map(|(i, p)| FieldPat { field: Field::new(i), pattern: p })
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
if let ty::Adt(adt, substs) = ty.kind {
|
let pat = match self {
|
||||||
if adt.is_enum() {
|
Single | Variant(_) => match ty.kind {
|
||||||
PatKind::Variant {
|
ty::Adt(..) | ty::Tuple(..) => {
|
||||||
adt_def: adt,
|
let subpatterns = subpatterns
|
||||||
substs,
|
.enumerate()
|
||||||
variant_index: self.variant_index_for_adt(cx, adt),
|
.map(|(i, p)| FieldPat { field: Field::new(i), pattern: p })
|
||||||
subpatterns,
|
.collect();
|
||||||
|
|
||||||
|
if let ty::Adt(adt, substs) = ty.kind {
|
||||||
|
if adt.is_enum() {
|
||||||
|
PatKind::Variant {
|
||||||
|
adt_def: adt,
|
||||||
|
substs,
|
||||||
|
variant_index: self.variant_index_for_adt(cx, adt),
|
||||||
|
subpatterns,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
PatKind::Leaf { subpatterns }
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
PatKind::Leaf { subpatterns }
|
PatKind::Leaf { subpatterns }
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
PatKind::Leaf { subpatterns }
|
|
||||||
}
|
}
|
||||||
}
|
ty::Ref(..) => PatKind::Deref { subpattern: subpatterns.nth(0).unwrap() },
|
||||||
|
ty::Slice(_) | ty::Array(..) => bug!("bad slice pattern {:?} {:?}", self, ty),
|
||||||
ty::Ref(..) => PatKind::Deref { subpattern: subpatterns.nth(0).unwrap() },
|
|
||||||
|
|
||||||
ty::Slice(_) | ty::Array(..) => match self {
|
|
||||||
FixedLenSlice(_) => {
|
|
||||||
PatKind::Slice { prefix: subpatterns.collect(), slice: None, suffix: vec![] }
|
|
||||||
}
|
|
||||||
VarLenSlice(prefix_len, _suffix_len) => {
|
|
||||||
let prefix = subpatterns.by_ref().take(*prefix_len as usize).collect();
|
|
||||||
let suffix = subpatterns.collect();
|
|
||||||
let wild = Pat::wildcard_from_ty(ty);
|
|
||||||
PatKind::Slice { prefix, slice: Some(wild), suffix }
|
|
||||||
}
|
|
||||||
_ => bug!("bad slice pattern {:?} {:?}", self, ty),
|
|
||||||
},
|
|
||||||
|
|
||||||
_ => 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)),
|
|
||||||
hi: ty::Const::from_bits(cx.tcx, hi, ty::ParamEnv::empty().and(ty)),
|
|
||||||
end,
|
|
||||||
}),
|
|
||||||
_ => PatKind::Wild,
|
_ => PatKind::Wild,
|
||||||
},
|
},
|
||||||
|
FixedLenSlice(_) => {
|
||||||
|
PatKind::Slice { prefix: subpatterns.collect(), slice: None, suffix: vec![] }
|
||||||
|
}
|
||||||
|
&VarLenSlice(prefix_len, _) => {
|
||||||
|
let prefix = subpatterns.by_ref().take(prefix_len as usize).collect();
|
||||||
|
let suffix = subpatterns.collect();
|
||||||
|
let wild = Pat::wildcard_from_ty(ty);
|
||||||
|
PatKind::Slice { prefix, slice: Some(wild), suffix }
|
||||||
|
}
|
||||||
|
&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)),
|
||||||
|
hi: ty::Const::from_bits(cx.tcx, hi, ty::ParamEnv::empty().and(ty)),
|
||||||
|
end,
|
||||||
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
Pat { ty, span: DUMMY_SP, kind: Box::new(pat) }
|
Pat { ty, span: DUMMY_SP, kind: Box::new(pat) }
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue