Cleanup of some pattern related code

This commit is contained in:
Vadim Petrochenkov 2016-06-11 18:47:47 +03:00
parent d3c94b25cb
commit ba419a78f3
5 changed files with 95 additions and 214 deletions

View File

@ -945,52 +945,41 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
/// The core driver for walking a pattern; `match_mode` must be
/// established up front, e.g. via `determine_pat_move_mode` (see
/// also `walk_irrefutable_pat` for patterns that stand alone).
fn walk_pat(&mut self,
cmt_discr: mc::cmt<'tcx>,
pat: &hir::Pat,
match_mode: MatchMode) {
debug!("walk_pat cmt_discr={:?} pat={:?}", cmt_discr,
pat);
fn walk_pat(&mut self, cmt_discr: mc::cmt<'tcx>, pat: &hir::Pat, match_mode: MatchMode) {
debug!("walk_pat cmt_discr={:?} pat={:?}", cmt_discr, pat);
let tcx = &self.tcx();
let mc = &self.mc;
let infcx = self.mc.infcx;
let delegate = &mut self.delegate;
return_if_err!(mc.cat_pattern(cmt_discr.clone(), pat, |mc, cmt_pat, pat| {
match pat.node {
PatKind::Binding(bmode, _, _) => {
debug!("binding cmt_pat={:?} pat={:?} match_mode={:?}",
cmt_pat,
pat,
match_mode);
if let PatKind::Binding(bmode, _, _) = pat.node {
debug!("binding cmt_pat={:?} pat={:?} match_mode={:?}", cmt_pat, pat, match_mode);
// pat_ty: the type of the binding being produced.
let pat_ty = return_if_err!(infcx.node_ty(pat.id));
// pat_ty: the type of the binding being produced.
let pat_ty = return_if_err!(infcx.node_ty(pat.id));
// Each match binding is effectively an assignment to the
// binding being produced.
if let Ok(binding_cmt) = mc.cat_def(pat.id, pat.span, pat_ty,
tcx.expect_def(pat.id)) {
delegate.mutate(pat.id, pat.span, binding_cmt, MutateMode::Init);
// Each match binding is effectively an assignment to the
// binding being produced.
if let Ok(binding_cmt) = mc.cat_def(pat.id, pat.span, pat_ty,
tcx.expect_def(pat.id)) {
delegate.mutate(pat.id, pat.span, binding_cmt, MutateMode::Init);
}
// It is also a borrow or copy/move of the value being matched.
match bmode {
hir::BindByRef(m) => {
if let ty::TyRef(&r, _) = pat_ty.sty {
let bk = ty::BorrowKind::from_mutbl(m);
delegate.borrow(pat.id, pat.span, cmt_pat, r, bk, RefBinding);
}
}
// It is also a borrow or copy/move of the value being matched.
match bmode {
hir::BindByRef(m) => {
if let ty::TyRef(&r, _) = pat_ty.sty {
let bk = ty::BorrowKind::from_mutbl(m);
delegate.borrow(pat.id, pat.span, cmt_pat,
r, bk, RefBinding);
}
}
hir::BindByValue(..) => {
let mode = copy_or_move(infcx, &cmt_pat, PatBindingMove);
debug!("walk_pat binding consuming pat");
delegate.consume_pat(pat, cmt_pat, mode);
}
hir::BindByValue(..) => {
let mode = copy_or_move(infcx, &cmt_pat, PatBindingMove);
debug!("walk_pat binding consuming pat");
delegate.consume_pat(pat, cmt_pat, mode);
}
}
_ => {}
}
}));
@ -999,72 +988,23 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
// to the above loop's visit of than the bindings that form
// the leaves of the pattern tree structure.
return_if_err!(mc.cat_pattern(cmt_discr, pat, |mc, cmt_pat, pat| {
match pat.node {
PatKind::Struct(..) | PatKind::TupleStruct(..) |
PatKind::Path(..) | PatKind::QPath(..) => {
match tcx.expect_def(pat.id) {
Def::Variant(enum_did, variant_did) => {
let downcast_cmt =
if tcx.lookup_adt_def(enum_did).is_univariant() {
cmt_pat
} else {
let cmt_pat_ty = cmt_pat.ty;
mc.cat_downcast(pat, cmt_pat, cmt_pat_ty, variant_did)
};
match tcx.expect_def_or_none(pat.id) {
Some(Def::Variant(enum_did, variant_did)) => {
let downcast_cmt = if tcx.lookup_adt_def(enum_did).is_univariant() {
cmt_pat
} else {
let cmt_pat_ty = cmt_pat.ty;
mc.cat_downcast(pat, cmt_pat, cmt_pat_ty, variant_did)
};
debug!("variant downcast_cmt={:?} pat={:?}",
downcast_cmt,
pat);
delegate.matched_pat(pat, downcast_cmt, match_mode);
}
Def::Struct(..) | Def::TyAlias(..) => {
// A struct (in either the value or type
// namespace; we encounter the former on
// e.g. patterns for unit structs).
debug!("struct cmt_pat={:?} pat={:?}",
cmt_pat,
pat);
delegate.matched_pat(pat, cmt_pat, match_mode);
}
Def::Const(..) | Def::AssociatedConst(..) => {
// This is a leaf (i.e. identifier binding
// or constant value to match); thus no
// `matched_pat` call.
}
def => {
// An enum type should never be in a pattern.
// Remaining cases are e.g. Def::Fn, to
// which identifiers within patterns
// should not resolve. However, we do
// encouter this when using the
// expr-use-visitor during typeck. So just
// ignore it, an error should have been
// reported.
if !tcx.sess.has_errors() {
span_bug!(pat.span,
"Pattern has unexpected def: {:?} and type {:?}",
def,
cmt_pat.ty);
}
}
}
debug!("variant downcast_cmt={:?} pat={:?}", downcast_cmt, pat);
delegate.matched_pat(pat, downcast_cmt, match_mode);
}
PatKind::Wild | PatKind::Tuple(..) | PatKind::Box(..) |
PatKind::Ref(..) | PatKind::Lit(..) | PatKind::Range(..) |
PatKind::Vec(..) | PatKind::Binding(..) => {
// Each of these cases does not
// correspond to an enum variant or struct, so we
// do not do any `matched_pat` calls for these
// cases either.
Some(Def::Struct(..)) | Some(Def::TyAlias(..)) | Some(Def::AssociatedTy(..)) => {
debug!("struct cmt_pat={:?} pat={:?}", cmt_pat, pat);
delegate.matched_pat(pat, cmt_pat, match_mode);
}
_ => {}
}
}));
}

View File

@ -1050,9 +1050,8 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
}
// FIXME(#19596) This is a workaround, but there should be a better way to do this
fn cat_pattern_<F>(&self, cmt: cmt<'tcx>, pat: &hir::Pat, op: &mut F)
-> McResult<()>
where F : FnMut(&MemCategorizationContext<'a, 'gcx, 'tcx>, cmt<'tcx>, &hir::Pat),
fn cat_pattern_<F>(&self, cmt: cmt<'tcx>, pat: &hir::Pat, op: &mut F) -> McResult<()>
where F : FnMut(&MemCategorizationContext<'a, 'gcx, 'tcx>, cmt<'tcx>, &hir::Pat)
{
// Here, `cmt` is the categorization for the value being
// matched and pat is the pattern it is being matched against.
@ -1099,21 +1098,14 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
// step out of sync again. So you'll see below that we always
// get the type of the *subpattern* and use that.
debug!("cat_pattern: {:?} cmt={:?}",
pat,
cmt);
debug!("cat_pattern: {:?} cmt={:?}", pat, cmt);
(*op)(self, cmt.clone(), pat);
let opt_def = self.tcx().expect_def_or_none(pat.id);
if opt_def == Some(Def::Err) {
return Err(());
}
op(self, cmt.clone(), pat);
// Note: This goes up here (rather than within the PatKind::TupleStruct arm
// alone) because struct patterns can refer to struct types or
// to struct variants within enums.
let cmt = match opt_def {
// alone) because PatKind::Struct can also refer to variants.
let cmt = match self.tcx().expect_def_or_none(pat.id) {
Some(Def::Err) => return Err(()),
Some(Def::Variant(enum_did, variant_did))
// univariant enums do not need downcasts
if !self.tcx().lookup_adt_def(enum_did).is_univariant() => {
@ -1123,68 +1115,35 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
};
match pat.node {
PatKind::Wild => {
// _
}
PatKind::TupleStruct(_, ref subpats, ddpos) => {
match opt_def {
Some(Def::Variant(enum_def, def_id)) => {
// variant(x, y, z)
let expected_len = self.tcx().lookup_adt_def(enum_def)
.variant_with_id(def_id).fields.len();
for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) {
let subpat_ty = self.pat_ty(&subpat)?; // see (*2)
let subcmt =
self.cat_imm_interior(
pat, cmt.clone(), subpat_ty,
InteriorField(PositionalField(i)));
self.cat_pattern_(subcmt, &subpat, op)?;
}
let expected_len = match self.tcx().expect_def(pat.id) {
Def::Variant(enum_def, def_id) => {
self.tcx().lookup_adt_def(enum_def).variant_with_id(def_id).fields.len()
}
Some(Def::Struct(..)) => {
let expected_len = match self.pat_ty(&pat)?.sty {
Def::Struct(..) => {
match self.pat_ty(&pat)?.sty {
ty::TyStruct(adt_def, _) => {
adt_def.struct_variant().fields.len()
}
ref ty => {
span_bug!(pat.span, "tuple struct pattern unexpected type {:?}", ty);
}
};
}
}
def => {
span_bug!(pat.span, "tuple struct pattern didn't resolve \
to variant or struct {:?}", def);
}
};
for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) {
let subpat_ty = self.pat_ty(&subpat)?; // see (*2)
let cmt_field =
self.cat_imm_interior(
pat, cmt.clone(), subpat_ty,
InteriorField(PositionalField(i)));
self.cat_pattern_(cmt_field, &subpat, op)?;
}
}
Some(Def::Const(..)) | Some(Def::AssociatedConst(..)) => {
for subpat in subpats {
self.cat_pattern_(cmt.clone(), &subpat, op)?;
}
}
_ => {
span_bug!(
pat.span,
"enum pattern didn't resolve to enum or struct {:?}",
opt_def);
}
for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) {
let subpat_ty = self.pat_ty(&subpat)?; // see (*2)
let subcmt = self.cat_imm_interior(pat, cmt.clone(), subpat_ty,
InteriorField(PositionalField(i)));
self.cat_pattern_(subcmt, &subpat, op)?;
}
}
PatKind::Path(..) | PatKind::QPath(..) | PatKind::Binding(_, _, None) => {
// Lone constant, or unit variant or identifier: ignore
}
PatKind::Binding(_, _, Some(ref subpat)) => {
self.cat_pattern_(cmt, &subpat, op)?;
}
PatKind::Struct(_, ref field_pats, _) => {
// {f1: p1, ..., fN: pN}
for fp in field_pats {
@ -1194,6 +1153,10 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
}
}
PatKind::Binding(_, _, Some(ref subpat)) => {
self.cat_pattern_(cmt, &subpat, op)?;
}
PatKind::Tuple(ref subpats, ddpos) => {
// (p1, ..., pN)
let expected_len = match self.pat_ty(&pat)?.sty {
@ -1202,10 +1165,8 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
};
for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) {
let subpat_ty = self.pat_ty(&subpat)?; // see (*2)
let subcmt =
self.cat_imm_interior(
pat, cmt.clone(), subpat_ty,
InteriorField(PositionalField(i)));
let subcmt = self.cat_imm_interior(pat, cmt.clone(), subpat_ty,
InteriorField(PositionalField(i)));
self.cat_pattern_(subcmt, &subpat, op)?;
}
}
@ -1215,25 +1176,26 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
// PatKind::Ref since that information is already contained
// in the type.
let subcmt = self.cat_deref(pat, cmt, 0, None)?;
self.cat_pattern_(subcmt, &subpat, op)?;
self.cat_pattern_(subcmt, &subpat, op)?;
}
PatKind::Vec(ref before, ref slice, ref after) => {
let context = InteriorOffsetKind::Pattern;
let elt_cmt = self.cat_index(pat, cmt, context)?;
for before_pat in before {
self.cat_pattern_(elt_cmt.clone(), &before_pat, op)?;
}
if let Some(ref slice_pat) = *slice {
self.cat_pattern_(elt_cmt.clone(), &slice_pat, op)?;
}
for after_pat in after {
self.cat_pattern_(elt_cmt.clone(), &after_pat, op)?;
}
let context = InteriorOffsetKind::Pattern;
let elt_cmt = self.cat_index(pat, cmt, context)?;
for before_pat in before {
self.cat_pattern_(elt_cmt.clone(), &before_pat, op)?;
}
if let Some(ref slice_pat) = *slice {
self.cat_pattern_(elt_cmt.clone(), &slice_pat, op)?;
}
for after_pat in after {
self.cat_pattern_(elt_cmt.clone(), &after_pat, op)?;
}
}
PatKind::Lit(_) | PatKind::Range(_, _) => {
/*always ok*/
PatKind::Path(..) | PatKind::QPath(..) | PatKind::Binding(_, _, None) |
PatKind::Lit(..) | PatKind::Range(..) | PatKind::Wild => {
// always ok
}
}

View File

@ -784,18 +784,14 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: &Pat,
left_ty: Ty, max_slice_length: usize) -> Vec<Constructor> {
let pat = raw_pat(p);
match pat.node {
PatKind::Struct(..) | PatKind::TupleStruct(..) | PatKind::Path(..) =>
PatKind::Struct(..) | PatKind::TupleStruct(..) | PatKind::Path(..) | PatKind::QPath(..) =>
match cx.tcx.expect_def(pat.id) {
Def::Const(..) | Def::AssociatedConst(..) =>
span_bug!(pat.span, "const pattern should've \
been rewritten"),
Def::Struct(..) | Def::TyAlias(..) => vec![Single],
Def::Variant(_, id) => vec![Variant(id)],
def => span_bug!(pat.span, "pat_constructors: unexpected \
definition {:?}", def),
Def::Struct(..) | Def::TyAlias(..) | Def::AssociatedTy(..) => vec![Single],
Def::Const(..) | Def::AssociatedConst(..) =>
span_bug!(pat.span, "const pattern should've been rewritten"),
def => span_bug!(pat.span, "pat_constructors: unexpected definition {:?}", def),
},
PatKind::QPath(..) =>
span_bug!(pat.span, "const pattern should've been rewritten"),
PatKind::Lit(ref expr) =>
vec![ConstantValue(eval_const_expr(cx.tcx, &expr))],
PatKind::Range(ref lo, ref hi) =>
@ -899,7 +895,7 @@ pub fn specialize<'a, 'b, 'tcx>(
PatKind::Binding(..) | PatKind::Wild =>
Some(vec![dummy_pat; arity]),
PatKind::Path(..) => {
PatKind::Path(..) | PatKind::QPath(..) => {
match cx.tcx.expect_def(pat_id) {
Def::Const(..) | Def::AssociatedConst(..) =>
span_bug!(pat_span, "const pattern should've \
@ -934,10 +930,6 @@ pub fn specialize<'a, 'b, 'tcx>(
}
}
PatKind::QPath(_, _) => {
span_bug!(pat_span, "const pattern should've been rewritten")
}
PatKind::Struct(_, ref pattern_fields, _) => {
let adt = cx.tcx.node_id_to_type(pat_id).ty_adt_def().unwrap();
let variant = constructor.variant_for_adt(adt);

View File

@ -13,7 +13,7 @@ use hair::cx::Cx;
use rustc_data_structures::indexed_vec::Idx;
use rustc_const_eval as const_eval;
use rustc::hir::def::Def;
use rustc::hir::pat_util::{EnumerateAndAdjustIterator, pat_is_resolved_const};
use rustc::hir::pat_util::EnumerateAndAdjustIterator;
use rustc::ty::{self, Ty};
use rustc::mir::repr::*;
use rustc::hir::{self, PatKind};
@ -76,9 +76,7 @@ impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> {
PatternKind::Range { lo: lo, hi: hi }
},
PatKind::Path(..) | PatKind::QPath(..)
if pat_is_resolved_const(&self.cx.tcx.def_map.borrow(), pat) =>
{
PatKind::Path(..) | PatKind::QPath(..) => {
match self.cx.tcx.expect_def(pat.id) {
Def::Const(def_id) | Def::AssociatedConst(def_id) => {
let tcx = self.cx.tcx.global_tcx();
@ -104,11 +102,9 @@ impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> {
}
}
}
def =>
span_bug!(
pat.span,
"def not a constant: {:?}",
def),
_ => {
self.variant_or_leaf(pat, vec![])
}
}
}
@ -199,10 +195,6 @@ impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> {
}
}
PatKind::Path(..) => {
self.variant_or_leaf(pat, vec![])
}
PatKind::TupleStruct(_, ref subpatterns, ddpos) => {
let pat_ty = self.cx.tcx.node_id_to_type(pat.id);
let adt_def = match pat_ty.sty {
@ -253,10 +245,6 @@ impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> {
self.variant_or_leaf(pat, subpatterns)
}
PatKind::QPath(..) => {
span_bug!(pat.span, "unexpanded macro or bad constant etc");
}
};
Pattern {
@ -325,7 +313,7 @@ impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> {
}
}
Def::Struct(..) | Def::TyAlias(..) => {
Def::Struct(..) | Def::TyAlias(..) | Def::AssociatedTy(..) => {
PatternKind::Leaf { subpatterns: subpatterns }
}

View File

@ -436,7 +436,6 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
}
}
hir::ExprPath(..) => {
if let Def::Struct(..) = self.tcx.expect_def(expr.id) {
let expr_ty = self.tcx.expr_ty(expr);
let def = match expr_ty.sty {