From ba419a78f3b2addd44339611cda2ddd8835af4e6 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 11 Jun 2016 18:47:47 +0300 Subject: [PATCH] Cleanup of some pattern related code --- src/librustc/middle/expr_use_visitor.rs | 136 ++++++---------------- src/librustc/middle/mem_categorization.rs | 128 +++++++------------- src/librustc_const_eval/check_match.rs | 20 +--- src/librustc_mir/hair/cx/pattern.rs | 24 +--- src/librustc_privacy/lib.rs | 1 - 5 files changed, 95 insertions(+), 214 deletions(-) diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index c8b8c5dbdbb..6551e0129f8 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -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); } + _ => {} } })); } diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index a70829347f1..3776a904923 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -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_(&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_(&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 } } diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index a5a9dea61ad..33c778f8725 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -784,18 +784,14 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: &Pat, left_ty: Ty, max_slice_length: usize) -> Vec { 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); diff --git a/src/librustc_mir/hair/cx/pattern.rs b/src/librustc_mir/hair/cx/pattern.rs index b5da5079276..654108c14df 100644 --- a/src/librustc_mir/hair/cx/pattern.rs +++ b/src/librustc_mir/hair/cx/pattern.rs @@ -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 } } diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 85a6f732dd5..acaf9b9b2fa 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -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 {