From 216f5fba043ff787ba2dd6bbf01e0e077304adf0 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 6 Mar 2016 15:54:44 +0300 Subject: [PATCH 1/3] Separate bindings from other patterns in HIR --- src/librustc/cfg/construct.rs | 4 +- src/librustc/hir/fold.rs | 4 +- src/librustc/hir/intravisit.rs | 2 +- src/librustc/hir/lowering.rs | 20 +-- src/librustc/hir/map/collector.rs | 2 +- src/librustc/hir/map/def_collector.rs | 2 +- src/librustc/hir/map/mod.rs | 2 +- src/librustc/hir/mod.rs | 10 +- src/librustc/hir/pat_util.rs | 25 ++-- src/librustc/hir/print.rs | 4 +- src/librustc/middle/expr_use_visitor.rs | 25 ++-- src/librustc/middle/mem_categorization.rs | 8 +- src/librustc/middle/region.rs | 12 +- src/librustc/ty/mod.rs | 2 +- .../borrowck/gather_loans/gather_moves.rs | 2 +- src/librustc_const_eval/check_match.rs | 107 +++++++-------- src/librustc_lint/bad_style.rs | 18 +-- src/librustc_lint/builtin.rs | 2 +- src/librustc_metadata/encoder.rs | 2 +- src/librustc_mir/build/mod.rs | 9 +- src/librustc_mir/hair/cx/pattern.rs | 10 +- src/librustc_trans/_match.rs | 101 +++++++-------- .../debuginfo/create_scope_map.rs | 122 ++++++++---------- src/librustc_trans/debuginfo/metadata.rs | 2 +- src/librustc_typeck/check/_match.rs | 10 +- src/librustc_typeck/check/mod.rs | 24 ++-- src/librustc_typeck/check/regionck.rs | 2 +- src/librustc_typeck/collect.rs | 9 +- src/librustdoc/clean/mod.rs | 2 +- 29 files changed, 237 insertions(+), 307 deletions(-) diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs index af47617ea92fd..61c0f1c1c6498 100644 --- a/src/librustc/cfg/construct.rs +++ b/src/librustc/cfg/construct.rs @@ -99,7 +99,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { fn pat(&mut self, pat: &hir::Pat, pred: CFGIndex) -> CFGIndex { match pat.node { - PatKind::Ident(_, _, None) | + PatKind::Binding(_, _, None) | PatKind::Path(..) | PatKind::QPath(..) | PatKind::Lit(..) | @@ -110,7 +110,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { PatKind::Box(ref subpat) | PatKind::Ref(ref subpat, _) | - PatKind::Ident(_, _, Some(ref subpat)) => { + PatKind::Binding(_, _, Some(ref subpat)) => { let subpat_exit = self.pat(&subpat, pred); self.add_ast_node(pat.id, &[subpat_exit]) } diff --git a/src/librustc/hir/fold.rs b/src/librustc/hir/fold.rs index 641fe5f3b4747..1e80bc3c54dd0 100644 --- a/src/librustc/hir/fold.rs +++ b/src/librustc/hir/fold.rs @@ -914,8 +914,8 @@ pub fn noop_fold_pat(p: P, folder: &mut T) -> P { id: folder.new_id(id), node: match node { PatKind::Wild => PatKind::Wild, - PatKind::Ident(binding_mode, pth1, sub) => { - PatKind::Ident(binding_mode, + PatKind::Binding(binding_mode, pth1, sub) => { + PatKind::Binding(binding_mode, Spanned { span: folder.new_span(pth1.span), node: folder.fold_name(pth1.node), diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 9b1d22436677f..4593f19daadb9 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -485,7 +485,7 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) { PatKind::Ref(ref subpattern, _) => { visitor.visit_pat(subpattern) } - PatKind::Ident(_, ref pth1, ref optional_subpattern) => { + PatKind::Binding(_, ref pth1, ref optional_subpattern) => { visitor.visit_name(pth1.span, pth1.node); walk_list!(visitor, visit_pat, optional_subpattern); } diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index ea9a76d982a3a..90dd2dad7203d 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -866,14 +866,16 @@ impl<'a> LoweringContext<'a> { PatKind::Wild => hir::PatKind::Wild, PatKind::Ident(ref binding_mode, pth1, ref sub) => { self.with_parent_def(p.id, |this| { - let name = match this.resolver.get_resolution(p.id).map(|d| d.full_def()) { - // Only pattern bindings are renamed - None | Some(Def::Local(..)) => this.lower_ident(pth1.node), - _ => pth1.node.name, - }; - hir::PatKind::Ident(this.lower_binding_mode(binding_mode), - respan(pth1.span, name), - sub.as_ref().map(|x| this.lower_pat(x))) + match this.resolver.get_resolution(p.id).map(|d| d.full_def()) { + // `None` can occur in body-less function signatures + None | Some(Def::Local(..)) => { + hir::PatKind::Binding(this.lower_binding_mode(binding_mode), + respan(pth1.span, + this.lower_ident(pth1.node)), + sub.as_ref().map(|x| this.lower_pat(x))) + } + _ => hir::PatKind::Path(hir::Path::from_name(pth1.span, pth1.node.name)) + } }) } PatKind::Lit(ref e) => hir::PatKind::Lit(self.lower_expr(e)), @@ -1868,7 +1870,7 @@ impl<'a> LoweringContext<'a> { fn pat_ident_binding_mode(&mut self, span: Span, name: Name, bm: hir::BindingMode) -> P { - let pat_ident = hir::PatKind::Ident(bm, + let pat_ident = hir::PatKind::Binding(bm, Spanned { span: span, node: name, diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index 99e5f32e263f2..692f56bde28f5 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -165,7 +165,7 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> { } fn visit_pat(&mut self, pat: &'ast Pat) { - let node = if let PatKind::Ident(..) = pat.node { + let node = if let PatKind::Binding(..) = pat.node { NodeLocal(pat) } else { NodePat(pat) diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index e783d84dc1b4a..e3b6539b8ccab 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -396,7 +396,7 @@ impl<'ast> intravisit::Visitor<'ast> for DefCollector<'ast> { fn visit_pat(&mut self, pat: &'ast hir::Pat) { let parent_def = self.parent_def; - if let hir::PatKind::Ident(_, name, _) = pat.node { + if let hir::PatKind::Binding(_, name, _) = pat.node { let def = self.create_def(pat.id, DefPathData::Binding(name.node)); self.parent_def = Some(def); } diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 2f310806a7420..41b72e569f475 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -561,7 +561,7 @@ impl<'ast> Map<'ast> { NodeVariant(v) => v.node.name, NodeLifetime(lt) => lt.name, NodeTyParam(tp) => tp.name, - NodeLocal(&Pat { node: PatKind::Ident(_,l,_), .. }) => l.node, + NodeLocal(&Pat { node: PatKind::Binding(_,l,_), .. }) => l.node, NodeStructCtor(_) => self.name(self.get_parent(id)), _ => bug!("no name for {}", self.node_to_string(id)) } diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index ea52a393da6c7..0e89dde70ee77 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -466,7 +466,7 @@ impl Pat { } match self.node { - PatKind::Ident(_, _, Some(ref p)) => p.walk_(it), + PatKind::Binding(_, _, Some(ref p)) => p.walk_(it), PatKind::Struct(_, ref fields, _) => { fields.iter().all(|field| field.node.pat.walk_(it)) } @@ -484,7 +484,7 @@ impl Pat { PatKind::Wild | PatKind::Lit(_) | PatKind::Range(_, _) | - PatKind::Ident(_, _, _) | + PatKind::Binding(..) | PatKind::Path(..) | PatKind::QPath(_, _) => { true @@ -532,7 +532,7 @@ pub enum PatKind { /// which it is. The resolver determines this, and /// records this pattern's `NodeId` in an auxiliary /// set (of "PatIdents that refer to unit patterns or constants"). - Ident(BindingMode, Spanned, Option>), + Binding(BindingMode, Spanned, Option>), /// A struct or struct variant pattern, e.g. `Variant {x, y, ..}`. /// The `bool` is `true` in the presence of a `..`. @@ -1144,7 +1144,7 @@ pub type ExplicitSelf = Spanned; impl Arg { pub fn to_self(&self) -> Option { - if let PatKind::Ident(BindByValue(mutbl), name, _) = self.pat.node { + if let PatKind::Binding(BindByValue(mutbl), name, _) = self.pat.node { if name.node.unhygienize() == keywords::SelfValue.name() { return match self.ty.node { TyInfer => Some(respan(self.pat.span, SelfKind::Value(mutbl))), @@ -1160,7 +1160,7 @@ impl Arg { } pub fn is_self(&self) -> bool { - if let PatKind::Ident(_, name, _) = self.pat.node { + if let PatKind::Binding(_, name, _) = self.pat.node { name.node.unhygienize() == keywords::SelfValue.name() } else { false diff --git a/src/librustc/hir/pat_util.rs b/src/librustc/hir/pat_util.rs index 1008ba7a6e6a0..35a7f7174cbbc 100644 --- a/src/librustc/hir/pat_util.rs +++ b/src/librustc/hir/pat_util.rs @@ -70,7 +70,6 @@ pub fn pat_is_refutable(dm: &DefMap, pat: &hir::Pat) -> bool { PatKind::Lit(_) | PatKind::Range(_, _) | PatKind::QPath(..) => true, PatKind::TupleStruct(..) | PatKind::Path(..) | - PatKind::Ident(_, _, None) | PatKind::Struct(..) => { match dm.get(&pat.id).map(|d| d.full_def()) { Some(Def::Variant(..)) => true, @@ -86,7 +85,6 @@ pub fn pat_is_variant_or_struct(dm: &DefMap, pat: &hir::Pat) -> bool { match pat.node { PatKind::TupleStruct(..) | PatKind::Path(..) | - PatKind::Ident(_, _, None) | PatKind::Struct(..) => { match dm.get(&pat.id).map(|d| d.full_def()) { Some(Def::Variant(..)) | Some(Def::Struct(..)) | Some(Def::TyAlias(..)) => true, @@ -99,7 +97,7 @@ pub fn pat_is_variant_or_struct(dm: &DefMap, pat: &hir::Pat) -> bool { pub fn pat_is_const(dm: &DefMap, pat: &hir::Pat) -> bool { match pat.node { - PatKind::Ident(_, _, None) | PatKind::Path(..) | PatKind::QPath(..) => { + PatKind::Path(..) | PatKind::QPath(..) => { match dm.get(&pat.id).map(|d| d.full_def()) { Some(Def::Const(..)) | Some(Def::AssociatedConst(..)) => true, _ => false @@ -113,7 +111,7 @@ pub fn pat_is_const(dm: &DefMap, pat: &hir::Pat) -> bool { // returned instead of a panic. pub fn pat_is_resolved_const(dm: &DefMap, pat: &hir::Pat) -> bool { match pat.node { - PatKind::Ident(_, _, None) | PatKind::Path(..) | PatKind::QPath(..) => { + PatKind::Path(..) | PatKind::QPath(..) => { match dm.get(&pat.id) .and_then(|d| if d.depth == 0 { Some(d.base_def) } else { None } ) { @@ -125,32 +123,28 @@ pub fn pat_is_resolved_const(dm: &DefMap, pat: &hir::Pat) -> bool { } } -pub fn pat_is_binding(dm: &DefMap, pat: &hir::Pat) -> bool { +pub fn pat_is_binding(_: &DefMap, pat: &hir::Pat) -> bool { match pat.node { - PatKind::Ident(..) => { - !pat_is_variant_or_struct(dm, pat) && - !pat_is_const(dm, pat) - } + PatKind::Binding(..) => true, _ => false } } -pub fn pat_is_binding_or_wild(dm: &DefMap, pat: &hir::Pat) -> bool { +pub fn pat_is_binding_or_wild(_: &DefMap, pat: &hir::Pat) -> bool { match pat.node { - PatKind::Ident(..) => pat_is_binding(dm, pat), - PatKind::Wild => true, + PatKind::Binding(..) | PatKind::Wild => true, _ => false } } /// Call `it` on every "binding" in a pattern, e.g., on `a` in /// `match foo() { Some(a) => (), None => () }` -pub fn pat_bindings(dm: &RefCell, pat: &hir::Pat, mut it: I) where +pub fn pat_bindings(_: &RefCell, pat: &hir::Pat, mut it: I) where I: FnMut(hir::BindingMode, ast::NodeId, Span, &Spanned), { pat.walk(|p| { match p.node { - PatKind::Ident(binding_mode, ref pth, _) if pat_is_binding(&dm.borrow(), p) => { + PatKind::Binding(binding_mode, ref pth, _) => { it(binding_mode, p.id, p.span, &respan(pth.span, pth.node)); } _ => {} @@ -221,7 +215,7 @@ pub fn pat_contains_bindings_or_wild(dm: &DefMap, pat: &hir::Pat) -> bool { pub fn simple_name<'a>(pat: &'a hir::Pat) -> Option { match pat.node { - PatKind::Ident(hir::BindByValue(_), ref path1, None) => { + PatKind::Binding(hir::BindByValue(..), ref path1, None) => { Some(path1.node) } _ => { @@ -241,7 +235,6 @@ pub fn necessary_variants(dm: &DefMap, pat: &hir::Pat) -> Vec { match p.node { PatKind::TupleStruct(..) | PatKind::Path(..) | - PatKind::Ident(_, _, None) | PatKind::Struct(..) => { match dm.get(&p.id) { Some(&PathResolution { base_def: Def::Variant(_, id), .. }) => { diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index a9ed83d9dc315..ceaf348117e17 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -1716,7 +1716,7 @@ impl<'a> State<'a> { // is that it doesn't matter match pat.node { PatKind::Wild => word(&mut self.s, "_")?, - PatKind::Ident(binding_mode, ref path1, ref sub) => { + PatKind::Binding(binding_mode, ref path1, ref sub) => { match binding_mode { hir::BindByRef(mutbl) => { self.word_nbsp("ref")?; @@ -2170,7 +2170,7 @@ impl<'a> State<'a> { if let Some(eself) = input.to_self() { self.print_explicit_self(&eself)?; } else { - let invalid = if let PatKind::Ident(_, name, _) = input.pat.node { + let invalid = if let PatKind::Binding(_, name, _) = input.pat.node { name.node == keywords::Invalid.name() } else { false diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index b0add5a23dc46..12517d927de46 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -935,9 +935,9 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { let def_map = &self.tcx().def_map; if pat_util::pat_is_binding(&def_map.borrow(), pat) { match pat.node { - PatKind::Ident(hir::BindByRef(_), _, _) => + PatKind::Binding(hir::BindByRef(_), _, _) => mode.lub(BorrowingMatch), - PatKind::Ident(hir::BindByValue(_), _, _) => { + PatKind::Binding(hir::BindByValue(_), _, _) => { match copy_or_move(self.mc.infcx, &cmt_pat, PatBindingMove) { Copy => mode.lub(CopyingMatch), Move(_) => mode.lub(MovingMatch), @@ -989,14 +989,14 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { // It is also a borrow or copy/move of the value being matched. match pat.node { - PatKind::Ident(hir::BindByRef(m), _, _) => { + PatKind::Binding(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); } } - PatKind::Ident(hir::BindByValue(_), _, _) => { + PatKind::Binding(hir::BindByValue(_), _, _) => { let mode = copy_or_move(infcx, &cmt_pat, PatBindingMove); debug!("walk_pat binding consuming pat"); delegate.consume_pat(pat, cmt_pat, mode); @@ -1057,8 +1057,8 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { let tcx = infcx.tcx; match pat.node { - PatKind::TupleStruct(..) | PatKind::Path(..) | PatKind::QPath(..) | - PatKind::Ident(_, _, None) | PatKind::Struct(..) => { + PatKind::Struct(..) | PatKind::TupleStruct(..) | + PatKind::Path(..) | PatKind::QPath(..) => { match def_map.get(&pat.id).map(|d| d.full_def()) { None => { // no definition found: pat is not a @@ -1094,8 +1094,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { } Some(Def::Const(..)) | - Some(Def::AssociatedConst(..)) | - Some(Def::Local(..)) => { + Some(Def::AssociatedConst(..)) => { // This is a leaf (i.e. identifier binding // or constant value to match); thus no // `matched_pat` call. @@ -1121,16 +1120,10 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { } } - PatKind::Ident(_, _, Some(_)) => { - // Do nothing; this is a binding (not an enum - // variant or struct), and the cat_pattern call - // will visit the substructure recursively. - } - PatKind::Wild | PatKind::Tuple(..) | PatKind::Box(..) | PatKind::Ref(..) | PatKind::Lit(..) | PatKind::Range(..) | - PatKind::Vec(..) => { - // Similarly, each of these cases does not + 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. diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index e933b22f60799..31e3db51f55d8 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -306,7 +306,7 @@ impl MutabilityCategory { fn from_local(tcx: TyCtxt, id: ast::NodeId) -> MutabilityCategory { let ret = match tcx.map.get(id) { ast_map::NodeLocal(p) => match p.node { - PatKind::Ident(bind_mode, _, _) => { + PatKind::Binding(bind_mode, _, _) => { if bind_mode == hir::BindByValue(hir::MutMutable) { McDeclared } else { @@ -398,7 +398,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { // *being borrowed* is. But ideally we would put in a more // fundamental fix to this conflated use of the node id. let ret_ty = match pat.node { - PatKind::Ident(hir::BindByRef(_), _, _) => { + PatKind::Binding(hir::BindByRef(_), _, _) => { // a bind-by-ref means that the base_ty will be the type of the ident itself, // but what we want here is the type of the underlying value being borrowed. // So peel off one-level, turning the &T into T. @@ -1276,11 +1276,11 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { } } - PatKind::Path(..) | PatKind::QPath(..) | PatKind::Ident(_, _, None) => { + PatKind::Path(..) | PatKind::QPath(..) | PatKind::Binding(_, _, None) => { // Lone constant, or unit variant or identifier: ignore } - PatKind::Ident(_, _, Some(ref subpat)) => { + PatKind::Binding(_, _, Some(ref subpat)) => { self.cat_pattern_(cmt, &subpat, op)?; } diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 6b2c2dfcd72b4..3efc584ae2b66 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -752,13 +752,9 @@ fn resolve_arm(visitor: &mut RegionResolutionVisitor, arm: &hir::Arm) { fn resolve_pat(visitor: &mut RegionResolutionVisitor, pat: &hir::Pat) { visitor.new_node_extent(pat.id); - // If this is a binding (or maybe a binding, I'm too lazy to check - // the def map) then record the lifetime of that binding. - match pat.node { - PatKind::Ident(..) => { - record_var_lifetime(visitor, pat.id, pat.span); - } - _ => { } + // If this is a binding then record the lifetime of that binding. + if let PatKind::Binding(..) = pat.node { + record_var_lifetime(visitor, pat.id, pat.span); } intravisit::walk_pat(visitor, pat); @@ -958,7 +954,7 @@ fn resolve_local(visitor: &mut RegionResolutionVisitor, local: &hir::Local) { /// | box P& fn is_binding_pat(pat: &hir::Pat) -> bool { match pat.node { - PatKind::Ident(hir::BindByRef(_), _, _) => true, + PatKind::Binding(hir::BindByRef(_), _, _) => true, PatKind::Struct(_, ref field_pats, _) => { field_pats.iter().any(|fp| is_binding_pat(&fp.node.pat)) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index dfb4ec739247d..24f0671ce6184 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2216,7 +2216,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { match self.map.find(id) { Some(ast_map::NodeLocal(pat)) => { match pat.node { - PatKind::Ident(_, ref path1, _) => path1.node.as_str(), + PatKind::Binding(_, ref path1, _) => path1.node.as_str(), _ => { bug!("Variable id {} maps to {:?}, not local", id, pat); }, diff --git a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs index 83322215e30ca..8682661d35a84 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs @@ -98,7 +98,7 @@ pub fn gather_move_from_pat<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, move_pat: &hir::Pat, cmt: mc::cmt<'tcx>) { let pat_span_path_opt = match move_pat.node { - PatKind::Ident(_, ref path1, _) => { + PatKind::Binding(_, ref path1, _) => { Some(MoveSpanAndPath{span: move_pat.span, name: path1.node}) }, diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index 16b61534ee9ab..46e05d218fc64 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -239,31 +239,28 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &hir::Expr) { fn check_for_bindings_named_the_same_as_variants(cx: &MatchCheckCtxt, pat: &Pat) { pat.walk(|p| { - match p.node { - PatKind::Ident(hir::BindByValue(hir::MutImmutable), name, None) => { - let pat_ty = cx.tcx.pat_ty(p); - if let ty::TyEnum(edef, _) = pat_ty.sty { - let def = cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def()); - if let Some(Def::Local(..)) = def { - if edef.variants.iter().any(|variant| - variant.name == name.node.unhygienize() - && variant.kind() == VariantKind::Unit - ) { - let ty_path = cx.tcx.item_path_str(edef.did); - let mut err = struct_span_warn!(cx.tcx.sess, p.span, E0170, - "pattern binding `{}` is named the same as one \ - of the variants of the type `{}`", - name.node, ty_path); - help!(err, - "if you meant to match on a variant, \ - consider making the path in the pattern qualified: `{}::{}`", - ty_path, name.node); - err.emit(); - } + if let PatKind::Binding(hir::BindByValue(hir::MutImmutable), name, None) = p.node { + let pat_ty = cx.tcx.pat_ty(p); + if let ty::TyEnum(edef, _) = pat_ty.sty { + let def = cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def()); + if let Some(Def::Local(..)) = def { + if edef.variants.iter().any(|variant| + variant.name == name.node.unhygienize() + && variant.kind() == VariantKind::Unit + ) { + let ty_path = cx.tcx.item_path_str(edef.did); + let mut err = struct_span_warn!(cx.tcx.sess, p.span, E0170, + "pattern binding `{}` is named the same as one \ + of the variants of the type `{}`", + name.node, ty_path); + help!(err, + "if you meant to match on a variant, \ + consider making the path in the pattern qualified: `{}::{}`", + ty_path, name.node); + err.emit(); } } } - _ => () } true }); @@ -371,8 +368,8 @@ fn check_arms(cx: &MatchCheckCtxt, /// Checks for common cases of "catchall" patterns that may not be intended as such. fn pat_is_catchall(dm: &DefMap, p: &Pat) -> bool { match p.node { - PatKind::Ident(_, _, None) => pat_is_binding(dm, p), - PatKind::Ident(_, _, Some(ref s)) => pat_is_catchall(dm, &s), + PatKind::Binding(_, _, None) => true, + PatKind::Binding(_, _, Some(ref s)) => pat_is_catchall(dm, &s), PatKind::Ref(ref s, _) => pat_is_catchall(dm, &s), PatKind::Tuple(ref v, _) => v.iter().all(|p| pat_is_catchall(dm, &p)), _ => false @@ -381,7 +378,7 @@ fn pat_is_catchall(dm: &DefMap, p: &Pat) -> bool { fn raw_pat(p: &Pat) -> &Pat { match p.node { - PatKind::Ident(_, _, Some(ref s)) => raw_pat(&s), + PatKind::Binding(_, _, Some(ref s)) => raw_pat(&s), _ => p } } @@ -487,11 +484,10 @@ impl<'map> IdVisitingOperation for RenamingRecorder<'map> { impl<'a, 'tcx> Folder for StaticInliner<'a, 'tcx> { fn fold_pat(&mut self, pat: P) -> P { return match pat.node { - PatKind::Ident(..) | PatKind::Path(..) | PatKind::QPath(..) => { + PatKind::Path(..) | PatKind::QPath(..) => { let def = self.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()); match def { - Some(Def::AssociatedConst(did)) | - Some(Def::Const(did)) => { + Some(Def::AssociatedConst(did)) | Some(Def::Const(did)) => { let substs = Some(self.tcx.node_id_item_substs(pat.id).substs); if let Some((const_expr, _)) = lookup_const_by_id(self.tcx, did, substs) { match const_expr_to_pat(self.tcx, const_expr, pat.id, pat.span) { @@ -717,7 +713,7 @@ fn is_useful(cx: &MatchCheckCtxt, let left_ty = cx.tcx.pat_ty(&real_pat); match real_pat.node { - PatKind::Ident(hir::BindByRef(..), _, _) => { + PatKind::Binding(hir::BindByRef(..), _, _) => { left_ty.builtin_deref(false, NoPreference).unwrap().ty } _ => left_ty, @@ -804,38 +800,37 @@ 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::Ident(..) => + PatKind::Struct(..) | PatKind::TupleStruct(..) | PatKind::Path(..) => match cx.tcx.def_map.borrow().get(&pat.id).unwrap().full_def() { 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::Local(..) => vec![], 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))), + vec![ConstantValue(eval_const_expr(cx.tcx, &expr))], PatKind::Range(ref lo, ref hi) => - vec!(ConstantRange(eval_const_expr(cx.tcx, &lo), eval_const_expr(cx.tcx, &hi))), + vec![ConstantRange(eval_const_expr(cx.tcx, &lo), eval_const_expr(cx.tcx, &hi))], PatKind::Vec(ref before, ref slice, ref after) => match left_ty.sty { - ty::TyArray(_, _) => vec!(Single), + ty::TyArray(_, _) => vec![Single], _ => if slice.is_some() { (before.len() + after.len()..max_slice_length+1) .map(|length| Slice(length)) .collect() } else { - vec!(Slice(before.len() + after.len())) + vec![Slice(before.len() + after.len())] } }, PatKind::Box(..) | PatKind::Tuple(..) | PatKind::Ref(..) => - vec!(Single), - PatKind::Wild => - vec!(), + vec![Single], + PatKind::Binding(..) | PatKind::Wild => + vec![], } } @@ -897,10 +892,10 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat], id: pat_id, ref node, span: pat_span } = raw_pat(r[col]); let head: Option> = match *node { - PatKind::Wild => + PatKind::Binding(..) | PatKind::Wild => Some(vec![DUMMY_WILD_PAT; arity]), - PatKind::Path(..) | PatKind::Ident(..) => { + PatKind::Path(..) => { let def = cx.tcx.def_map.borrow().get(&pat_id).unwrap().full_def(); match def { Def::Const(..) | Def::AssociatedConst(..) => @@ -908,7 +903,6 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat], been rewritten"), Def::Variant(_, id) if *constructor != Variant(id) => None, Def::Variant(..) | Def::Struct(..) => Some(Vec::new()), - Def::Local(..) => Some(vec![DUMMY_WILD_PAT; arity]), _ => span_bug!(pat_span, "specialize: unexpected \ definition {:?}", def), } @@ -1128,28 +1122,15 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt, for pat in pats { pat.walk(|p| { - if pat_is_binding(&def_map.borrow(), &p) { - match p.node { - PatKind::Ident(hir::BindByValue(_), _, ref sub) => { - let pat_ty = tcx.node_id_to_type(p.id); - //FIXME: (@jroesch) this code should be floated up as well - cx.tcx.infer_ctxt(None, Some(cx.param_env.clone()), - ProjectionMode::AnyFinal).enter(|infcx| { - if infcx.type_moves_by_default(pat_ty, pat.span) { - check_move(p, sub.as_ref().map(|p| &**p)); - } - }); + if let PatKind::Binding(hir::BindByValue(..), _, ref sub) = p.node { + let pat_ty = tcx.node_id_to_type(p.id); + //FIXME: (@jroesch) this code should be floated up as well + cx.tcx.infer_ctxt(None, Some(cx.param_env.clone()), + ProjectionMode::AnyFinal).enter(|infcx| { + if infcx.type_moves_by_default(pat_ty, pat.span) { + check_move(p, sub.as_ref().map(|p| &**p)); } - PatKind::Ident(hir::BindByRef(_), _, _) => { - } - _ => { - span_bug!( - p.span, - "binding pattern {} is not an identifier: {:?}", - p.id, - p.node); - } - } + }); } true }); @@ -1225,7 +1206,7 @@ impl<'a, 'b, 'tcx, 'v> Visitor<'v> for AtBindingPatternVisitor<'a, 'b, 'tcx> { } match pat.node { - PatKind::Ident(_, _, Some(_)) => { + PatKind::Binding(_, _, Some(_)) => { let bindings_were_allowed = self.bindings_allowed; self.bindings_allowed = false; intravisit::walk_pat(self, pat); diff --git a/src/librustc_lint/bad_style.rs b/src/librustc_lint/bad_style.rs index 27a6e433c7399..4c4dea406ba9e 100644 --- a/src/librustc_lint/bad_style.rs +++ b/src/librustc_lint/bad_style.rs @@ -274,9 +274,9 @@ impl LateLintPass for NonSnakeCase { } fn check_pat(&mut self, cx: &LateContext, p: &hir::Pat) { - if let &PatKind::Ident(_, ref path1, _) = &p.node { - let def = cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def()); - if let Some(Def::Local(..)) = def { + if let &PatKind::Binding(_, ref path1, _) = &p.node { + // Exclude parameter names from foreign functions (they have no `Def`) + if cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def()).is_some() { self.check_snake_case(cx, "variable", &path1.node.as_str(), Some(p.span)); } } @@ -360,12 +360,14 @@ impl LateLintPass for NonUpperCaseGlobals { fn check_pat(&mut self, cx: &LateContext, p: &hir::Pat) { // Lint for constants that look like binding identifiers (#7526) - match (&p.node, cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def())) { - (&PatKind::Ident(_, ref path1, _), Some(Def::Const(..))) => { - NonUpperCaseGlobals::check_upper_case(cx, "constant in pattern", - path1.node, p.span); + if let PatKind::Path(ref path) = p.node { + if !path.global && path.segments.len() == 1 && path.segments[0].parameters.is_empty() { + if let Some(Def::Const(..)) = cx.tcx.def_map.borrow().get(&p.id) + .map(|d| d.full_def()) { + NonUpperCaseGlobals::check_upper_case(cx, "constant in pattern", + path.segments[0].name, path.span); + } } - _ => {} } } } diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 49b59aea46ee7..3005f564ff41a 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -171,7 +171,7 @@ impl LateLintPass for NonShorthandFieldPatterns { } }); for fieldpat in field_pats { - if let PatKind::Ident(_, ident, None) = fieldpat.node.pat.node { + if let PatKind::Binding(_, ident, None) = fieldpat.node.pat.node { if ident.node.unhygienize() == fieldpat.node.name { cx.span_lint(NON_SHORTHAND_FIELD_PATTERNS, fieldpat.span, &format!("the `{}:` in this pattern is redundant and can \ diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 2bc953039adb2..e0c35a6fba84f 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -744,7 +744,7 @@ fn encode_method_argument_names(rbml_w: &mut Encoder, rbml_w.start_tag(tag_method_argument_names); for arg in &decl.inputs { let tag = tag_method_argument_name; - if let PatKind::Ident(_, ref path1, _) = arg.pat.node { + if let PatKind::Binding(_, ref path1, _) = arg.pat.node { let name = path1.node.as_str(); rbml_w.wr_tagged_bytes(tag, name.as_bytes()); } else { diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index d75cf3b7587ea..9d7818a9ba4d6 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -14,7 +14,6 @@ use rustc::ty::{self, Ty}; use rustc::mir::repr::*; use rustc_data_structures::fnv::FnvHashMap; use rustc::hir; -use rustc::hir::pat_util::pat_is_binding; use std::ops::{Index, IndexMut}; use syntax::abi::Abi; use syntax::ast; @@ -221,7 +220,7 @@ pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, by_ref: by_ref }; if let Some(hir::map::NodeLocal(pat)) = tcx.map.find(fv.def.var_id()) { - if let hir::PatKind::Ident(_, ref ident, _) = pat.node { + if let hir::PatKind::Binding(_, ref ident, _) = pat.node { decl.debug_name = ident.node; } } @@ -333,10 +332,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let mut name = keywords::Invalid.name(); if let Some(pat) = pattern { - if let hir::PatKind::Ident(_, ref ident, _) = pat.node { - if pat_is_binding(&self.hir.tcx().def_map.borrow(), pat) { - name = ident.node; - } + if let hir::PatKind::Binding(_, ref ident, _) = pat.node { + name = ident.node; } } diff --git a/src/librustc_mir/hair/cx/pattern.rs b/src/librustc_mir/hair/cx/pattern.rs index b9ba860e8d0aa..acde81979f927 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::fnv::FnvHashMap; use rustc_const_eval as const_eval; use rustc::hir::def::Def; -use rustc::hir::pat_util::{EnumerateAndAdjustIterator, pat_is_resolved_const, pat_is_binding}; +use rustc::hir::pat_util::{EnumerateAndAdjustIterator, pat_is_resolved_const}; use rustc::ty::{self, Ty}; use rustc::mir::repr::*; use rustc::hir::{self, PatKind}; @@ -81,7 +81,7 @@ impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> { PatternKind::Range { lo: lo, hi: hi } }, - PatKind::Path(..) | PatKind::Ident(..) | PatKind::QPath(..) + PatKind::Path(..) | PatKind::QPath(..) if pat_is_resolved_const(&self.cx.tcx.def_map.borrow(), pat) => { let def = self.cx.tcx.def_map.borrow().get(&pat.id).unwrap().full_def(); @@ -167,9 +167,7 @@ impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> { } } - PatKind::Ident(bm, ref ident, ref sub) - if pat_is_binding(&self.cx.tcx.def_map.borrow(), pat) => - { + PatKind::Binding(bm, ref ident, ref sub) => { let id = match self.binding_map { None => pat.id, Some(ref map) => map[&ident.node], @@ -210,7 +208,7 @@ impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> { } } - PatKind::Ident(..) | PatKind::Path(..) => { + PatKind::Path(..) => { self.variant_or_leaf(pat, vec![]) } diff --git a/src/librustc_trans/_match.rs b/src/librustc_trans/_match.rs index 4b22e410f4c22..bdde5ce16178b 100644 --- a/src/librustc_trans/_match.rs +++ b/src/librustc_trans/_match.rs @@ -424,12 +424,11 @@ impl<'a, 'p, 'blk, 'tcx> fmt::Debug for Match<'a, 'p, 'blk, 'tcx> { fn has_nested_bindings(m: &[Match], col: usize) -> bool { for br in m { - match br.pats[col].node { - PatKind::Ident(_, _, Some(_)) => return true, - _ => () + if let PatKind::Binding(_, _, Some(..)) = br.pats[col].node { + return true } } - return false; + false } // As noted in `fn match_datum`, we should eventually pass around a @@ -481,7 +480,7 @@ fn expand_nested_bindings<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let mut pat = br.pats[col]; loop { pat = match pat.node { - PatKind::Ident(_, ref path, Some(ref inner)) => { + PatKind::Binding(_, ref path, Some(ref inner)) => { bound_ptrs.push((path.node, val.val)); &inner }, @@ -501,7 +500,6 @@ fn expand_nested_bindings<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } fn enter_match<'a, 'b, 'p, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, - dm: &RefCell, m: &[Match<'a, 'p, 'blk, 'tcx>], col: usize, val: MatchInput, @@ -518,13 +516,11 @@ fn enter_match<'a, 'b, 'p, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, let this = br.pats[col]; let mut bound_ptrs = br.bound_ptrs.clone(); match this.node { - PatKind::Ident(_, ref path, None) => { - if pat_is_binding(&dm.borrow(), &this) { - bound_ptrs.push((path.node, val.val)); - } + PatKind::Binding(_, ref path, None) => { + bound_ptrs.push((path.node, val.val)); } PatKind::Vec(ref before, Some(ref slice), ref after) => { - if let PatKind::Ident(_, ref path, None) = slice.node { + if let PatKind::Binding(_, ref path, None) = slice.node { let subslice_val = bind_subslice_pat( bcx, this.id, val, before.len(), after.len()); @@ -554,7 +550,7 @@ fn enter_default<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let _indenter = indenter(); // Collect all of the matches that can match against anything. - enter_match(bcx, dm, m, col, val, |pats| { + enter_match(bcx, m, col, val, |pats| { if pat_is_binding_or_wild(&dm.borrow(), &pats[col]) { let mut r = pats[..col].to_vec(); r.extend_from_slice(&pats[col + 1..]); @@ -596,7 +592,6 @@ fn enter_default<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, fn enter_opt<'a, 'p, 'blk, 'tcx>( bcx: Block<'blk, 'tcx>, _: ast::NodeId, - dm: &RefCell, m: &[Match<'a, 'p, 'blk, 'tcx>], opt: &Opt, col: usize, @@ -628,7 +623,7 @@ fn enter_opt<'a, 'p, 'blk, 'tcx>( tcx: bcx.tcx(), param_env: param_env, }; - enter_match(bcx, dm, m, col, val, |pats| + enter_match(bcx, m, col, val, |pats| check_match::specialize(&mcx, &pats[..], &ctor, col, variant_size) ) } @@ -659,9 +654,7 @@ fn get_branches<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, PatKind::Lit(ref l) => { ConstantValue(ConstantExpr(&l), debug_loc) } - PatKind::Ident(..) | PatKind::Path(..) | - PatKind::TupleStruct(..) | PatKind::Struct(..) => { - // This is either an enum variant or a variable binding. + PatKind::Path(..) | PatKind::TupleStruct(..) | PatKind::Struct(..) => { let opt_def = tcx.def_map.borrow().get(&cur.id).map(|d| d.full_def()); match opt_def { Some(Def::Variant(enum_id, var_id)) => { @@ -793,8 +786,7 @@ fn any_irrefutable_adt_pat(tcx: TyCtxt, m: &[Match], col: usize) -> bool { let pat = br.pats[col]; match pat.node { PatKind::Tuple(..) => true, - PatKind::Struct(..) | PatKind::TupleStruct(..) | - PatKind::Path(..) | PatKind::Ident(_, _, None) => { + PatKind::Struct(..) | PatKind::TupleStruct(..) | PatKind::Path(..) => { match tcx.def_map.borrow().get(&pat.id).unwrap().full_def() { Def::Struct(..) | Def::TyAlias(..) => true, _ => false, @@ -839,7 +831,7 @@ impl FailureHandler { fn pick_column_to_specialize(def_map: &RefCell, m: &[Match]) -> Option { fn pat_score(def_map: &RefCell, pat: &hir::Pat) -> usize { match pat.node { - PatKind::Ident(_, _, Some(ref inner)) => pat_score(def_map, &inner), + PatKind::Binding(_, _, Some(ref inner)) => pat_score(def_map, &inner), _ if pat_is_refutable(&def_map.borrow(), pat) => 1, _ => 0 } @@ -1226,7 +1218,7 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, }; match adt_vals { Some(field_vals) => { - let pats = enter_match(bcx, dm, m, col, val, |pats| + let pats = enter_match(bcx, m, col, val, |pats| check_match::specialize(&mcx, pats, &Constructor::Single, col, field_vals.len()) @@ -1391,7 +1383,7 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, } ConstantValue(..) | ConstantRange(..) => () } - let opt_ms = enter_opt(opt_cx, pat_id, dm, m, opt, col, size, val); + let opt_ms = enter_opt(opt_cx, pat_id, m, opt, col, size, val); let mut opt_vals: Vec<_> = unpacked.into_iter() .map(|v|MatchInput::from_val(v)) .collect(); @@ -1796,38 +1788,35 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let tcx = bcx.tcx(); let ccx = bcx.ccx(); match pat.node { - PatKind::Ident(pat_binding_mode, ref path1, ref inner) => { - if pat_is_binding(&tcx.def_map.borrow(), &pat) { - // Allocate the stack slot where the value of this - // binding will live and place it into the appropriate - // map. - bcx = mk_binding_alloca( - bcx, pat.id, path1.node, cleanup_scope, (), - "_match::bind_irrefutable_pat", - |(), bcx, Datum { val: llval, ty, kind: _ }| { - match pat_binding_mode { - hir::BindByValue(_) => { - // By value binding: move the value that `val` - // points at into the binding's stack slot. - let d = val.to_datum(ty); - d.store_to(bcx, llval) - } + PatKind::Binding(pat_binding_mode, ref path1, ref inner) => { + // Allocate the stack slot where the value of this + // binding will live and place it into the appropriate + // map. + bcx = mk_binding_alloca(bcx, pat.id, path1.node, cleanup_scope, (), + "_match::bind_irrefutable_pat", + |(), bcx, Datum { val: llval, ty, kind: _ }| { + match pat_binding_mode { + hir::BindByValue(_) => { + // By value binding: move the value that `val` + // points at into the binding's stack slot. + let d = val.to_datum(ty); + d.store_to(bcx, llval) + } - hir::BindByRef(_) => { - // By ref binding: the value of the variable - // is the pointer `val` itself or fat pointer referenced by `val` - if type_is_fat_ptr(bcx.tcx(), ty) { - expr::copy_fat_ptr(bcx, val.val, llval); - } - else { - Store(bcx, val.val, llval); - } - - bcx - } + hir::BindByRef(_) => { + // By ref binding: the value of the variable + // is the pointer `val` itself or fat pointer referenced by `val` + if type_is_fat_ptr(bcx.tcx(), ty) { + expr::copy_fat_ptr(bcx, val.val, llval); } - }); - } + else { + Store(bcx, val.val, llval); + } + + bcx + } + } + }); if let Some(ref inner_pat) = *inner { bcx = bind_irrefutable_pat(bcx, &inner_pat, val, cleanup_scope); @@ -1941,7 +1930,7 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let val = if type_is_fat_ptr(tcx, pat_ty) { // We need to check for this, as the pattern could be binding // a fat pointer by-value. - if let PatKind::Ident(hir::BindByRef(_),_,_) = inner.node { + if let PatKind::Binding(hir::BindByRef(..),_,_) = inner.node { val.val } else { Load(bcx, val.val) @@ -1960,7 +1949,7 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let val = if type_is_fat_ptr(tcx, pat_ty) { // We need to check for this, as the pattern could be binding // a fat pointer by-value. - if let PatKind::Ident(hir::BindByRef(_),_,_) = inner.node { + if let PatKind::Binding(hir::BindByRef(..),_,_) = inner.node { val.val } else { Load(bcx, val.val) @@ -2001,8 +1990,8 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, cleanup_scope) }); } - PatKind::Path(..) | PatKind::QPath(..) | PatKind::Wild | PatKind::Lit(_) | - PatKind::Range(_, _) => () + PatKind::Path(..) | PatKind::QPath(..) | PatKind::Wild | + PatKind::Lit(..) | PatKind::Range(..) => () } return bcx; } diff --git a/src/librustc_trans/debuginfo/create_scope_map.rs b/src/librustc_trans/debuginfo/create_scope_map.rs index aec43e69e5182..66409a4c481c9 100644 --- a/src/librustc_trans/debuginfo/create_scope_map.rs +++ b/src/librustc_trans/debuginfo/create_scope_map.rs @@ -235,76 +235,66 @@ fn walk_pattern(cx: &CrateContext, pat: &hir::Pat, scope_stack: &mut Vec , scope_map: &mut NodeMap) { - - let def_map = &cx.tcx().def_map; - // Unfortunately, we cannot just use pat_util::pat_bindings() or // ast_util::walk_pat() here because we have to visit *all* nodes in // order to put them into the scope map. The above functions don't do that. match pat.node { - PatKind::Ident(_, ref path1, ref sub_pat_opt) => { - - // Check if this is a binding. If so we need to put it on the - // scope stack and maybe introduce an artificial scope - if pat_util::pat_is_binding(&def_map.borrow(), &pat) { - - let name = path1.node.unhygienize(); - - // LLVM does not properly generate 'DW_AT_start_scope' fields - // for variable DIEs. For this reason we have to introduce - // an artificial scope at bindings whenever a variable with - // the same name is declared in *any* parent scope. - // - // Otherwise the following error occurs: - // - // let x = 10; - // - // do_something(); // 'gdb print x' correctly prints 10 - // - // { - // do_something(); // 'gdb print x' prints 0, because it - // // already reads the uninitialized 'x' - // // from the next line... - // let x = 100; - // do_something(); // 'gdb print x' correctly prints 100 - // } - - // Is there already a binding with that name? - // N.B.: this comparison must be UNhygienic... because - // gdb knows nothing about the context, so any two - // variables with the same name will cause the problem. - let need_new_scope = scope_stack - .iter() - .any(|entry| entry.name == Some(name)); - - if need_new_scope { - // Create a new lexical scope and push it onto the stack - let loc = span_start(cx, pat.span); - let file_metadata = file_metadata(cx, &loc.file.name); - let parent_scope = scope_stack.last().unwrap().scope_metadata; - - let scope_metadata = unsafe { - llvm::LLVMDIBuilderCreateLexicalBlock( - DIB(cx), - parent_scope, - file_metadata, - loc.line as c_uint, - loc.col.to_usize() as c_uint) - }; - - scope_stack.push(ScopeStackEntry { - scope_metadata: scope_metadata, - name: Some(name) - }); - - } else { - // Push a new entry anyway so the name can be found - let prev_metadata = scope_stack.last().unwrap().scope_metadata; - scope_stack.push(ScopeStackEntry { - scope_metadata: prev_metadata, - name: Some(name) - }); - } + PatKind::Binding(_, ref path1, ref sub_pat_opt) => { + // LLVM does not properly generate 'DW_AT_start_scope' fields + // for variable DIEs. For this reason we have to introduce + // an artificial scope at bindings whenever a variable with + // the same name is declared in *any* parent scope. + // + // Otherwise the following error occurs: + // + // let x = 10; + // + // do_something(); // 'gdb print x' correctly prints 10 + // + // { + // do_something(); // 'gdb print x' prints 0, because it + // // already reads the uninitialized 'x' + // // from the next line... + // let x = 100; + // do_something(); // 'gdb print x' correctly prints 100 + // } + + // Is there already a binding with that name? + // N.B.: this comparison must be UNhygienic... because + // gdb knows nothing about the context, so any two + // variables with the same name will cause the problem. + let name = path1.node.unhygienize(); + let need_new_scope = scope_stack + .iter() + .any(|entry| entry.name == Some(name)); + + if need_new_scope { + // Create a new lexical scope and push it onto the stack + let loc = span_start(cx, pat.span); + let file_metadata = file_metadata(cx, &loc.file.name); + let parent_scope = scope_stack.last().unwrap().scope_metadata; + + let scope_metadata = unsafe { + llvm::LLVMDIBuilderCreateLexicalBlock( + DIB(cx), + parent_scope, + file_metadata, + loc.line as c_uint, + loc.col.to_usize() as c_uint) + }; + + scope_stack.push(ScopeStackEntry { + scope_metadata: scope_metadata, + name: Some(name) + }); + + } else { + // Push a new entry anyway so the name can be found + let prev_metadata = scope_stack.last().unwrap().scope_metadata; + scope_stack.push(ScopeStackEntry { + scope_metadata: prev_metadata, + name: Some(name) + }); } scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata); diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index ccb01789aa64c..b401166cfdb4c 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -1945,7 +1945,7 @@ pub fn create_captured_var_metadata<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } Some(hir_map::NodeLocal(pat)) => { match pat.node { - PatKind::Ident(_, ref path1, _) => { + PatKind::Binding(_, ref path1, _) => { path1.node } _ => { diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 9030a6f222b85..31805f14a8cde 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -149,8 +149,7 @@ impl<'a, 'gcx, 'tcx> PatCtxt<'a, 'gcx, 'tcx> { // subtyping doesn't matter here, as the value is some kind of scalar self.demand_eqtype(pat.span, expected, lhs_ty); } - PatKind::Path(..) | PatKind::Ident(..) - if pat_is_resolved_const(&tcx.def_map.borrow(), pat) => { + PatKind::Path(..) if pat_is_resolved_const(&tcx.def_map.borrow(), pat) => { if let Some(pat_def) = tcx.def_map.borrow().get(&pat.id) { let const_did = pat_def.def_id(); let const_scheme = tcx.lookup_item_type(const_did); @@ -170,8 +169,7 @@ impl<'a, 'gcx, 'tcx> PatCtxt<'a, 'gcx, 'tcx> { self.write_error(pat.id); } } - PatKind::Ident(bm, ref path, ref sub) - if pat_is_binding(&tcx.def_map.borrow(), pat) => { + PatKind::Binding(bm, ref path, ref sub) => { let typ = self.local_ty(pat.span, pat.id); match bm { hir::BindByRef(mutbl) => { @@ -211,10 +209,6 @@ impl<'a, 'gcx, 'tcx> PatCtxt<'a, 'gcx, 'tcx> { } } } - PatKind::Ident(_, ref path, _) => { - let path = hir::Path::from_name(path.span, path.node); - self.check_pat_enum(pat, &path, &[], None, expected, false); - } PatKind::TupleStruct(ref path, ref subpats, ddpos) => { self.check_pat_enum(pat, path, &subpats, ddpos, expected, true); } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 264003bb62b81..85a5d5b629338 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -572,19 +572,17 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for GatherLocalsVisitor<'a, 'gcx, 'tcx> { // Add pattern bindings. fn visit_pat(&mut self, p: &'gcx hir::Pat) { - if let PatKind::Ident(_, ref path1, _) = p.node { - if pat_util::pat_is_binding(&self.fcx.tcx.def_map.borrow(), p) { - let var_ty = self.assign(p.span, p.id, None); - - self.fcx.require_type_is_sized(var_ty, p.span, - traits::VariableType(p.id)); - - debug!("Pattern binding {} is assigned to {} with type {:?}", - path1.node, - self.fcx.ty_to_string( - self.fcx.locals.borrow().get(&p.id).unwrap().clone()), - var_ty); - } + if let PatKind::Binding(_, ref path1, _) = p.node { + let var_ty = self.assign(p.span, p.id, None); + + self.fcx.require_type_is_sized(var_ty, p.span, + traits::VariableType(p.id)); + + debug!("Pattern binding {} is assigned to {} with type {:?}", + path1.node, + self.fcx.ty_to_string( + self.fcx.locals.borrow().get(&p.id).unwrap().clone()), + var_ty); } intravisit::walk_pat(self, p); } diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 7b79f2ec9bfe6..bf34428832d2e 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -1160,7 +1160,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { let _ = mc.cat_pattern(discr_cmt, root_pat, |mc, sub_cmt, sub_pat| { match sub_pat.node { // `ref x` pattern - PatKind::Ident(hir::BindByRef(mutbl), _, _) => { + PatKind::Binding(hir::BindByRef(mutbl), _, _) => { self.link_region_from_node_type(sub_pat.span, sub_pat.id, mutbl, sub_cmt); } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 5896a34b0d160..92027a56ec1b0 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -2152,12 +2152,9 @@ fn compute_type_scheme_of_foreign_fn_decl<'a, 'tcx>( { for i in &decl.inputs { match i.pat.node { - PatKind::Ident(_, _, _) => (), - PatKind::Wild => (), - _ => { - span_err!(ccx.tcx.sess, i.pat.span, E0130, - "patterns aren't allowed in foreign function declarations"); - } + PatKind::Binding(..) | PatKind::Wild => {} + _ => span_err!(ccx.tcx.sess, i.pat.span, E0130, + "patterns aren't allowed in foreign function declarations") } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 4831ee9a2e041..bf503141ff642 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2578,7 +2578,7 @@ fn name_from_pat(p: &hir::Pat) -> String { match p.node { PatKind::Wild => "_".to_string(), - PatKind::Ident(_, ref p, _) => p.node.to_string(), + PatKind::Binding(_, ref p, _) => p.node.to_string(), PatKind::TupleStruct(ref p, _, _) | PatKind::Path(ref p) => path_to_string(p), PatKind::QPath(..) => panic!("tried to get argument name from PatKind::QPath, \ which is not allowed in function arguments"), From cf4682069468f231e6153b9fc910e0c720c71ecb Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 6 Mar 2016 15:54:44 +0300 Subject: [PATCH 2/3] Refactor away some functions from hir::pat_util --- src/librustc/cfg/construct.rs | 3 +- src/librustc/hir/mod.rs | 15 +- src/librustc/hir/pat_util.rs | 75 +++------ src/librustc/middle/expr_use_visitor.rs | 157 ++++++++---------- src/librustc/middle/liveness.rs | 14 +- src/librustc/ty/util.rs | 4 +- src/librustc_const_eval/check_match.rs | 46 +++-- src/librustc_lint/unused.rs | 2 +- src/librustc_mir/hair/cx/expr.rs | 2 +- src/librustc_trans/_match.rs | 22 ++- .../debuginfo/create_scope_map.rs | 5 +- src/librustc_trans/debuginfo/metadata.rs | 8 +- src/librustc_typeck/check/_match.rs | 22 +-- src/librustc_typeck/check/mod.rs | 20 +-- src/librustc_typeck/check/regionck.rs | 2 +- src/librustc_typeck/check/writeback.rs | 8 +- src/libsyntax/ast.rs | 18 +- 17 files changed, 168 insertions(+), 255 deletions(-) diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs index 61c0f1c1c6498..76b53094a722b 100644 --- a/src/librustc/cfg/construct.rs +++ b/src/librustc/cfg/construct.rs @@ -456,8 +456,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { // Visit the guard expression let guard_exit = self.expr(&guard, guard_start); - let this_has_bindings = pat_util::pat_contains_bindings_or_wild( - &self.tcx.def_map.borrow(), &pat); + let this_has_bindings = pat_util::pat_contains_bindings_or_wild(&pat); // If both this pattern and the previous pattern // were free of bindings, they must consist only diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 0e89dde70ee77..bf3d003f51cb5 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -524,14 +524,7 @@ pub enum PatKind { /// Represents a wildcard pattern (`_`) Wild, - /// A `PatKind::Ident` may either be a new bound variable, - /// or a unit struct/variant pattern, or a const pattern (in the last two cases - /// the third field must be `None`). - /// - /// In the unit or const pattern case, the parser can't determine - /// which it is. The resolver determines this, and - /// records this pattern's `NodeId` in an auxiliary - /// set (of "PatIdents that refer to unit patterns or constants"). + /// A fresh binding `ref mut binding @ OPT_SUBPATTERN`. Binding(BindingMode, Spanned, Option>), /// A struct or struct variant pattern, e.g. `Variant {x, y, ..}`. @@ -547,10 +540,8 @@ pub enum PatKind { /// Such pattern can be resolved to a unit struct/variant or a constant. Path(Path), - /// An associated const named using the qualified path `::CONST` or - /// `::CONST`. Associated consts from inherent impls can be - /// referred to as simply `T::CONST`, in which case they will end up as - /// PatKind::Path, and the resolver will have to sort that out. + /// A path pattern written in qualified form, i.e. `::CONST` or `::CONST`. + /// Such patterns can only refer to associated constants at the moment. QPath(QSelf, Path), /// A tuple pattern `(a, b)`. diff --git a/src/librustc/hir/pat_util.rs b/src/librustc/hir/pat_util.rs index 35a7f7174cbbc..27530d8c75d13 100644 --- a/src/librustc/hir/pat_util.rs +++ b/src/librustc/hir/pat_util.rs @@ -10,14 +10,12 @@ use hir::def::*; use hir::def_id::DefId; +use hir::{self, PatKind}; use ty::TyCtxt; use util::nodemap::FnvHashMap; - use syntax::ast; -use hir::{self, PatKind}; -use syntax::codemap::{respan, Span, Spanned, DUMMY_SP}; +use syntax::codemap::{Span, Spanned, DUMMY_SP}; -use std::cell::RefCell; use std::iter::{Enumerate, ExactSizeIterator}; pub type PatIdMap = FnvHashMap; @@ -57,9 +55,9 @@ impl EnumerateAndAdjustIterator for T { // This is used because same-named variables in alternative patterns need to // use the NodeId of their namesake in the first pattern. -pub fn pat_id_map(dm: &RefCell, pat: &hir::Pat) -> PatIdMap { +pub fn pat_id_map(pat: &hir::Pat) -> PatIdMap { let mut map = FnvHashMap(); - pat_bindings(dm, pat, |_bm, p_id, _s, path1| { + pat_bindings(pat, |_bm, p_id, _s, path1| { map.insert(path1.node, p_id); }); map @@ -123,31 +121,14 @@ pub fn pat_is_resolved_const(dm: &DefMap, pat: &hir::Pat) -> bool { } } -pub fn pat_is_binding(_: &DefMap, pat: &hir::Pat) -> bool { - match pat.node { - PatKind::Binding(..) => true, - _ => false - } -} - -pub fn pat_is_binding_or_wild(_: &DefMap, pat: &hir::Pat) -> bool { - match pat.node { - PatKind::Binding(..) | PatKind::Wild => true, - _ => false - } -} - -/// Call `it` on every "binding" in a pattern, e.g., on `a` in +/// Call `f` on every "binding" in a pattern, e.g., on `a` in /// `match foo() { Some(a) => (), None => () }` -pub fn pat_bindings(_: &RefCell, pat: &hir::Pat, mut it: I) where - I: FnMut(hir::BindingMode, ast::NodeId, Span, &Spanned), +pub fn pat_bindings(pat: &hir::Pat, mut f: F) + where F: FnMut(hir::BindingMode, ast::NodeId, Span, &Spanned), { pat.walk(|p| { - match p.node { - PatKind::Binding(binding_mode, ref pth, _) => { - it(binding_mode, p.id, p.span, &respan(pth.span, pth.node)); - } - _ => {} + if let PatKind::Binding(binding_mode, ref pth, _) = p.node { + f(binding_mode, p.id, p.span, pth); } true }); @@ -155,10 +136,10 @@ pub fn pat_bindings(_: &RefCell, pat: &hir::Pat, mut it: I) where /// Checks if the pattern contains any patterns that bind something to /// an ident, e.g. `foo`, or `Foo(foo)` or `foo @ Bar(..)`. -pub fn pat_contains_bindings(dm: &DefMap, pat: &hir::Pat) -> bool { +pub fn pat_contains_bindings(pat: &hir::Pat) -> bool { let mut contains_bindings = false; pat.walk(|p| { - if pat_is_binding(dm, p) { + if let PatKind::Binding(..) = p.node { contains_bindings = true; false // there's at least one binding, can short circuit now. } else { @@ -170,18 +151,15 @@ pub fn pat_contains_bindings(dm: &DefMap, pat: &hir::Pat) -> bool { /// Checks if the pattern contains any `ref` or `ref mut` bindings, /// and if yes whether its containing mutable ones or just immutables ones. -pub fn pat_contains_ref_binding(dm: &RefCell, pat: &hir::Pat) -> Option { +pub fn pat_contains_ref_binding(pat: &hir::Pat) -> Option { let mut result = None; - pat_bindings(dm, pat, |mode, _, _, _| { - match mode { - hir::BindingMode::BindByRef(m) => { - // Pick Mutable as maximum - match result { - None | Some(hir::MutImmutable) => result = Some(m), - _ => (), - } + pat_bindings(pat, |mode, _, _, _| { + if let hir::BindingMode::BindByRef(m) = mode { + // Pick Mutable as maximum + match result { + None | Some(hir::MutImmutable) => result = Some(m), + _ => (), } - hir::BindingMode::BindByValue(_) => { } } }); result @@ -189,9 +167,9 @@ pub fn pat_contains_ref_binding(dm: &RefCell, pat: &hir::Pat) -> Option< /// Checks if the patterns for this arm contain any `ref` or `ref mut` /// bindings, and if yes whether its containing mutable ones or just immutables ones. -pub fn arm_contains_ref_binding(dm: &RefCell, arm: &hir::Arm) -> Option { +pub fn arm_contains_ref_binding(arm: &hir::Arm) -> Option { arm.pats.iter() - .filter_map(|pat| pat_contains_ref_binding(dm, pat)) + .filter_map(|pat| pat_contains_ref_binding(pat)) .max_by_key(|m| match *m { hir::MutMutable => 1, hir::MutImmutable => 0, @@ -200,14 +178,15 @@ pub fn arm_contains_ref_binding(dm: &RefCell, arm: &hir::Arm) -> Option< /// Checks if the pattern contains any patterns that bind something to /// an ident or wildcard, e.g. `foo`, or `Foo(_)`, `foo @ Bar(..)`, -pub fn pat_contains_bindings_or_wild(dm: &DefMap, pat: &hir::Pat) -> bool { +pub fn pat_contains_bindings_or_wild(pat: &hir::Pat) -> bool { let mut contains_bindings = false; pat.walk(|p| { - if pat_is_binding_or_wild(dm, p) { - contains_bindings = true; - false // there's at least one binding/wildcard, can short circuit now. - } else { - true + match p.node { + PatKind::Binding(..) | PatKind::Wild => { + contains_bindings = true; + false // there's at least one binding/wildcard, can short circuit now. + } + _ => true } }); contains_bindings diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 12517d927de46..cf07493fa7b60 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -612,8 +612,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { match local.init { None => { let delegate = &mut self.delegate; - pat_util::pat_bindings(&self.mc.infcx.tcx.def_map, &local.pat, - |_, id, span, _| { + pat_util::pat_bindings(&local.pat, |_, id, span, _| { delegate.decl_without_init(id, span); }) } @@ -932,23 +931,16 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { debug!("determine_pat_move_mode cmt_discr={:?} pat={:?}", cmt_discr, pat); return_if_err!(self.mc.cat_pattern(cmt_discr, pat, |_mc, cmt_pat, pat| { - let def_map = &self.tcx().def_map; - if pat_util::pat_is_binding(&def_map.borrow(), pat) { - match pat.node { - PatKind::Binding(hir::BindByRef(_), _, _) => - mode.lub(BorrowingMatch), - PatKind::Binding(hir::BindByValue(_), _, _) => { - match copy_or_move(self.mc.infcx, &cmt_pat, PatBindingMove) { - Copy => mode.lub(CopyingMatch), - Move(_) => mode.lub(MovingMatch), - } - } - _ => { - span_bug!( - pat.span, - "binding pattern not an identifier"); + match pat.node { + PatKind::Binding(hir::BindByRef(..), _, _) => + mode.lub(BorrowingMatch), + PatKind::Binding(hir::BindByValue(..), _, _) => { + match copy_or_move(self.mc.infcx, &cmt_pat, PatBindingMove) { + Copy => mode.lub(CopyingMatch), + Move(..) => mode.lub(MovingMatch), } } + _ => {} } })); } @@ -968,83 +960,74 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { let def_map = &self.tcx().def_map; let delegate = &mut self.delegate; return_if_err!(mc.cat_pattern(cmt_discr.clone(), pat, |mc, cmt_pat, pat| { - if pat_util::pat_is_binding(&def_map.borrow(), pat) { - 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)); - - // Each match binding is effectively an assignment to the - // binding being produced. - let def = def_map.borrow().get(&pat.id).unwrap().full_def(); - match mc.cat_def(pat.id, pat.span, pat_ty, def) { - Ok(binding_cmt) => { + match pat.node { + PatKind::Binding(bmode, _, _) => { + 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)); + + // Each match binding is effectively an assignment to the + // binding being produced. + let def = def_map.borrow().get(&pat.id).unwrap().full_def(); + if let Ok(binding_cmt) = mc.cat_def(pat.id, pat.span, pat_ty, def) { delegate.mutate(pat.id, pat.span, binding_cmt, MutateMode::Init); } - Err(_) => { } - } - // It is also a borrow or copy/move of the value being matched. - match pat.node { - PatKind::Binding(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); } - } - PatKind::Binding(hir::BindByValue(_), _, _) => { - let mode = copy_or_move(infcx, &cmt_pat, PatBindingMove); - debug!("walk_pat binding consuming pat"); - delegate.consume_pat(pat, cmt_pat, mode); - } - _ => { - span_bug!( - pat.span, - "binding pattern not an identifier"); } } - } else { - match pat.node { - PatKind::Vec(_, Some(ref slice_pat), _) => { - // The `slice_pat` here creates a slice into - // the original vector. This is effectively a - // borrow of the elements of the vector being - // matched. - - let (slice_cmt, slice_mutbl, slice_r) = - return_if_err!(mc.cat_slice_pattern(cmt_pat, &slice_pat)); - - // Note: We declare here that the borrow - // occurs upon entering the `[...]` - // pattern. This implies that something like - // `[a; b]` where `a` is a move is illegal, - // because the borrow is already in effect. - // In fact such a move would be safe-ish, but - // it effectively *requires* that we use the - // nulling out semantics to indicate when a - // value has been moved, which we are trying - // to move away from. Otherwise, how can we - // indicate that the first element in the - // vector has been moved? Eventually, we - // could perhaps modify this rule to permit - // `[..a, b]` where `b` is a move, because in - // that case we can adjust the length of the - // original vec accordingly, but we'd have to - // make trans do the right thing, and it would - // only work for `Box<[T]>`s. It seems simpler - // to just require that people call - // `vec.pop()` or `vec.unshift()`. - let slice_bk = ty::BorrowKind::from_mutbl(slice_mutbl); - delegate.borrow(pat.id, pat.span, - slice_cmt, slice_r, - slice_bk, RefBinding); - } - _ => { } + PatKind::Vec(_, Some(ref slice_pat), _) => { + // The `slice_pat` here creates a slice into + // the original vector. This is effectively a + // borrow of the elements of the vector being + // matched. + + let (slice_cmt, slice_mutbl, slice_r) = + return_if_err!(mc.cat_slice_pattern(cmt_pat, &slice_pat)); + + // Note: We declare here that the borrow + // occurs upon entering the `[...]` + // pattern. This implies that something like + // `[a; b]` where `a` is a move is illegal, + // because the borrow is already in effect. + // In fact such a move would be safe-ish, but + // it effectively *requires* that we use the + // nulling out semantics to indicate when a + // value has been moved, which we are trying + // to move away from. Otherwise, how can we + // indicate that the first element in the + // vector has been moved? Eventually, we + // could perhaps modify this rule to permit + // `[..a, b]` where `b` is a move, because in + // that case we can adjust the length of the + // original vec accordingly, but we'd have to + // make trans do the right thing, and it would + // only work for `Box<[T]>`s. It seems simpler + // to just require that people call + // `vec.pop()` or `vec.unshift()`. + let slice_bk = ty::BorrowKind::from_mutbl(slice_mutbl); + delegate.borrow(pat.id, pat.span, + slice_cmt, slice_r, + slice_bk, RefBinding); } + _ => {} } })); diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index be8caeb436a34..f6ea10a70eb2a 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -380,9 +380,7 @@ fn visit_fn(ir: &mut IrMaps, debug!("creating fn_maps: {:?}", &fn_maps as *const IrMaps); for arg in &decl.inputs { - pat_util::pat_bindings(&ir.tcx.def_map, - &arg.pat, - |_bm, arg_id, _x, path1| { + pat_util::pat_bindings(&arg.pat, |_bm, arg_id, _x, path1| { debug!("adding argument {}", arg_id); let name = path1.node; fn_maps.add_variable(Arg(arg_id, name)); @@ -415,7 +413,7 @@ fn visit_fn(ir: &mut IrMaps, } fn visit_local(ir: &mut IrMaps, local: &hir::Local) { - pat_util::pat_bindings(&ir.tcx.def_map, &local.pat, |_, p_id, sp, path1| { + pat_util::pat_bindings(&local.pat, |_, p_id, sp, path1| { debug!("adding local variable {}", p_id); let name = path1.node; ir.add_live_node_for_node(p_id, VarDefNode(sp)); @@ -429,7 +427,7 @@ fn visit_local(ir: &mut IrMaps, local: &hir::Local) { fn visit_arm(ir: &mut IrMaps, arm: &hir::Arm) { for pat in &arm.pats { - pat_util::pat_bindings(&ir.tcx.def_map, &pat, |bm, p_id, sp, path1| { + pat_util::pat_bindings(&pat, |bm, p_id, sp, path1| { debug!("adding local variable {} from match with bm {:?}", p_id, bm); let name = path1.node; @@ -589,7 +587,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { fn pat_bindings(&mut self, pat: &hir::Pat, mut f: F) where F: FnMut(&mut Liveness<'a, 'tcx>, LiveNode, Variable, Span, NodeId), { - pat_util::pat_bindings(&self.ir.tcx.def_map, pat, |_bm, p_id, sp, _n| { + pat_util::pat_bindings(pat, |_bm, p_id, sp, _n| { let ln = self.live_node(p_id, sp); let var = self.variable(p_id, sp); f(self, ln, var, sp, p_id); @@ -1567,9 +1565,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { fn warn_about_unused_args(&self, decl: &hir::FnDecl, entry_ln: LiveNode) { for arg in &decl.inputs { - pat_util::pat_bindings(&self.ir.tcx.def_map, - &arg.pat, - |_bm, p_id, sp, path1| { + pat_util::pat_bindings(&arg.pat, |_bm, p_id, sp, path1| { let var = self.variable(p_id, sp); // Ignore unused self. let name = path1.node; diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 4f6188ea3c51f..a4df028721669 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -173,11 +173,11 @@ impl<'tcx> ParameterEnvironment<'tcx> { impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn pat_contains_ref_binding(self, pat: &hir::Pat) -> Option { - pat_util::pat_contains_ref_binding(&self.def_map, pat) + pat_util::pat_contains_ref_binding(pat) } pub fn arm_contains_ref_binding(self, arm: &hir::Arm) -> Option { - pat_util::arm_contains_ref_binding(&self.def_map, arm) + pat_util::arm_contains_ref_binding(arm) } /// Returns the type of element at index `i` in tuple or tuple-like type `t`. diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index 46e05d218fc64..49fa1896ff8dd 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -748,10 +748,9 @@ fn is_useful(cx: &MatchCheckCtxt, }).find(|result| result != &NotUseful).unwrap_or(NotUseful) } else { let matrix = rows.iter().filter_map(|r| { - if pat_is_binding_or_wild(&cx.tcx.def_map.borrow(), raw_pat(r[0])) { - Some(r[1..].to_vec()) - } else { - None + match raw_pat(r[0]).node { + PatKind::Binding(..) | PatKind::Wild => Some(r[1..].to_vec()), + _ => None, } }).collect(); match is_useful(cx, &matrix, &v[1..], witness) { @@ -1089,17 +1088,11 @@ fn is_refutable(cx: &MatchCheckCtxt, pat: &Pat, refutable: F) -> Option fn check_legality_of_move_bindings(cx: &MatchCheckCtxt, has_guard: bool, pats: &[P]) { - let tcx = cx.tcx; - let def_map = &tcx.def_map; let mut by_ref_span = None; for pat in pats { - pat_bindings(def_map, &pat, |bm, _, span, _path| { - match bm { - hir::BindByRef(_) => { - by_ref_span = Some(span); - } - hir::BindByValue(_) => { - } + pat_bindings(&pat, |bm, _, span, _path| { + if let hir::BindByRef(..) = bm { + by_ref_span = Some(span); } }) } @@ -1108,7 +1101,7 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt, // check legality of moving out of the enum // x @ Foo(..) is legal, but x @ Foo(y) isn't. - if sub.map_or(false, |p| pat_contains_bindings(&def_map.borrow(), &p)) { + if sub.map_or(false, |p| pat_contains_bindings(&p)) { span_err!(cx.tcx.sess, p.span, E0007, "cannot bind by-move with sub-bindings"); } else if has_guard { span_err!(cx.tcx.sess, p.span, E0008, "cannot bind by-move into a pattern guard"); @@ -1123,7 +1116,7 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt, for pat in pats { pat.walk(|p| { if let PatKind::Binding(hir::BindByValue(..), _, ref sub) = p.node { - let pat_ty = tcx.node_id_to_type(p.id); + let pat_ty = cx.tcx.node_id_to_type(p.id); //FIXME: (@jroesch) this code should be floated up as well cx.tcx.infer_ctxt(None, Some(cx.param_env.clone()), ProjectionMode::AnyFinal).enter(|infcx| { @@ -1199,18 +1192,19 @@ struct AtBindingPatternVisitor<'a, 'b:'a, 'tcx:'b> { impl<'a, 'b, 'tcx, 'v> Visitor<'v> for AtBindingPatternVisitor<'a, 'b, 'tcx> { fn visit_pat(&mut self, pat: &Pat) { - if !self.bindings_allowed && pat_is_binding(&self.cx.tcx.def_map.borrow(), pat) { - span_err!(self.cx.tcx.sess, pat.span, E0303, - "pattern bindings are not allowed \ - after an `@`"); - } - match pat.node { - PatKind::Binding(_, _, Some(_)) => { - let bindings_were_allowed = self.bindings_allowed; - self.bindings_allowed = false; - intravisit::walk_pat(self, pat); - self.bindings_allowed = bindings_were_allowed; + PatKind::Binding(_, _, ref subpat) => { + if !self.bindings_allowed { + span_err!(self.cx.tcx.sess, pat.span, E0303, + "pattern bindings are not allowed after an `@`"); + } + + if subpat.is_some() { + let bindings_were_allowed = self.bindings_allowed; + self.bindings_allowed = false; + intravisit::walk_pat(self, pat); + self.bindings_allowed = bindings_were_allowed; + } } _ => intravisit::walk_pat(self, pat), } diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index d1595f243c9bf..b765043da8853 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -43,7 +43,7 @@ impl UnusedMut { let mut mutables = FnvHashMap(); for p in pats { - pat_util::pat_bindings(&cx.tcx.def_map, p, |mode, id, _, path1| { + pat_util::pat_bindings(p, |mode, id, _, path1| { let name = path1.node; if let hir::BindByValue(hir::MutMutable) = mode { if !name.as_str().starts_with("_") { diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 1e7164a62c070..1f560672b62a8 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -656,7 +656,7 @@ fn convert_arm<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, None } else { map = FnvHashMap(); - pat_util::pat_bindings(&cx.tcx.def_map, &arm.pats[0], |_, p_id, _, path| { + pat_util::pat_bindings(&arm.pats[0], |_, p_id, _, path| { map.insert(path.node, p_id); }); Some(&map) diff --git a/src/librustc_trans/_match.rs b/src/librustc_trans/_match.rs index bdde5ce16178b..419e19532dd7c 100644 --- a/src/librustc_trans/_match.rs +++ b/src/librustc_trans/_match.rs @@ -540,7 +540,6 @@ fn enter_match<'a, 'b, 'p, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, } fn enter_default<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, - dm: &RefCell, m: &[Match<'a, 'p, 'blk, 'tcx>], col: usize, val: MatchInput) @@ -551,12 +550,13 @@ fn enter_default<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, // Collect all of the matches that can match against anything. enter_match(bcx, m, col, val, |pats| { - if pat_is_binding_or_wild(&dm.borrow(), &pats[col]) { - let mut r = pats[..col].to_vec(); - r.extend_from_slice(&pats[col + 1..]); - Some(r) - } else { - None + match pats[col].node { + PatKind::Binding(..) | PatKind::Wild => { + let mut r = pats[..col].to_vec(); + r.extend_from_slice(&pats[col + 1..]); + Some(r) + } + _ => None } }) } @@ -1145,7 +1145,6 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, has_genuine_default: bool) { let fcx = bcx.fcx; let tcx = bcx.tcx(); - let dm = &tcx.def_map; let mut vals_left = vals[0..col].to_vec(); vals_left.extend_from_slice(&vals[col + 1..]); @@ -1279,7 +1278,7 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, C_int(ccx, 0) // Placeholder for when not using a switch }; - let defaults = enter_default(else_cx, dm, m, col, val); + let defaults = enter_default(else_cx, m, col, val); let exhaustive = chk.is_infallible() && defaults.is_empty(); let len = opts.len(); @@ -1509,10 +1508,9 @@ fn create_bindings_map<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, pat: &hir::Pat, // Note that we use the names because each binding will have many ids // from the various alternatives. let ccx = bcx.ccx(); - let tcx = bcx.tcx(); let reassigned = is_discr_reassigned(bcx, discr, body); let mut bindings_map = FnvHashMap(); - pat_bindings(&tcx.def_map, &pat, |bm, p_id, span, path1| { + pat_bindings(&pat, |bm, p_id, span, path1| { let name = path1.node; let variable_ty = node_id_type(bcx, p_id); let llvariable_ty = type_of::type_of(ccx, variable_ty); @@ -1655,7 +1653,7 @@ pub fn store_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, // create dummy memory for the variables if we have no // value to store into them immediately let tcx = bcx.tcx(); - pat_bindings(&tcx.def_map, pat, |_, p_id, _, path1| { + pat_bindings(pat, |_, p_id, _, path1| { let scope = cleanup::var_scope(tcx, p_id); bcx = mk_binding_alloca( bcx, p_id, path1.node, scope, (), diff --git a/src/librustc_trans/debuginfo/create_scope_map.rs b/src/librustc_trans/debuginfo/create_scope_map.rs index 66409a4c481c9..bba0edd5f0496 100644 --- a/src/librustc_trans/debuginfo/create_scope_map.rs +++ b/src/librustc_trans/debuginfo/create_scope_map.rs @@ -42,16 +42,13 @@ pub fn create_scope_map(cx: &CrateContext, fn_ast_id: ast::NodeId) -> NodeMap { let mut scope_map = NodeMap(); - - let def_map = &cx.tcx().def_map; - let mut scope_stack = vec!(ScopeStackEntry { scope_metadata: fn_metadata, name: None }); scope_map.insert(fn_ast_id, fn_metadata); // Push argument identifiers onto the stack so arguments integrate nicely // with variable shadowing. for arg in args { - pat_util::pat_bindings(def_map, &arg.pat, |_, node_id, _, path1| { + pat_util::pat_bindings(&arg.pat, |_, node_id, _, path1| { scope_stack.push(ScopeStackEntry { scope_metadata: fn_metadata, name: Some(path1.node.unhygienize()) }); scope_map.insert(node_id, fn_metadata); diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index b401166cfdb4c..ab4860dff1510 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -1889,11 +1889,8 @@ pub fn create_local_var_metadata(bcx: Block, local: &hir::Local) { return; } - let cx = bcx.ccx(); - let def_map = &cx.tcx().def_map; let locals = bcx.fcx.lllocals.borrow(); - - pat_util::pat_bindings(def_map, &local.pat, |_, node_id, span, var_name| { + pat_util::pat_bindings(&local.pat, |_, node_id, span, var_name| { let datum = match locals.get(&node_id) { Some(datum) => datum, None => { @@ -2062,7 +2059,6 @@ pub fn create_argument_metadata(bcx: Block, arg: &hir::Arg) { return; } - let def_map = &bcx.tcx().def_map; let scope_metadata = bcx .fcx .debug_context @@ -2070,7 +2066,7 @@ pub fn create_argument_metadata(bcx: Block, arg: &hir::Arg) { .fn_metadata; let locals = bcx.fcx.lllocals.borrow(); - pat_util::pat_bindings(def_map, &arg.pat, |_, node_id, span, var_name| { + pat_util::pat_bindings(&arg.pat, |_, node_id, span, var_name| { let datum = match locals.get(&node_id) { Some(v) => v, None => { diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 31805f14a8cde..99b443e292491 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -10,7 +10,7 @@ use hir::def::{self, Def}; use rustc::infer::{self, InferOk, TypeOrigin}; -use hir::pat_util::{PatIdMap, pat_id_map, pat_is_binding}; +use hir::pat_util::{PatIdMap, pat_id_map}; use hir::pat_util::{EnumerateAndAdjustIterator, pat_is_resolved_const}; use rustc::ty::subst::Substs; use rustc::ty::{self, Ty, TypeFoldable, LvaluePreference}; @@ -436,23 +436,19 @@ impl<'a, 'gcx, 'tcx> PatCtxt<'a, 'gcx, 'tcx> { } pub fn check_dereferencable(&self, span: Span, expected: Ty<'tcx>, inner: &hir::Pat) -> bool { - let tcx = self.tcx; - if pat_is_binding(&tcx.def_map.borrow(), inner) { - let expected = self.shallow_resolve(expected); - expected.builtin_deref(true, ty::NoPreference).map_or(true, |mt| match mt.ty.sty { - ty::TyTrait(_) => { + if let PatKind::Binding(..) = inner.node { + if let Some(mt) = self.shallow_resolve(expected).builtin_deref(true, ty::NoPreference) { + if let ty::TyTrait(..) = mt.ty.sty { // This is "x = SomeTrait" being reduced from // "let &x = &SomeTrait" or "let box x = Box", an error. - span_err!(tcx.sess, span, E0033, + span_err!(self.tcx.sess, span, E0033, "type `{}` cannot be dereferenced", self.ty_to_string(expected)); - false + return false } - _ => true - }) - } else { - true + } } + true } } @@ -491,7 +487,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { for arm in arms { let pcx = PatCtxt { fcx: self, - map: pat_id_map(&tcx.def_map, &arm.pats[0]), + map: pat_id_map(&arm.pats[0]), }; for p in &arm.pats { pcx.check_pat(&p, discrim_ty); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 85a5d5b629338..819448e6a8068 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -630,8 +630,6 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, body: &'gcx hir::Block) -> FnCtxt<'a, 'gcx, 'tcx> { - let tcx = inherited.tcx; - let arg_tys = &fn_sig.inputs; let ret_ty = fn_sig.output; @@ -667,19 +665,15 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, fcx.register_old_wf_obligation(arg_ty, input.ty.span, traits::MiscObligation); // Create type variables for each argument. - pat_util::pat_bindings( - &tcx.def_map, - &input.pat, - |_bm, pat_id, sp, _path| { - let var_ty = visit.assign(sp, pat_id, None); - fcx.require_type_is_sized(var_ty, sp, - traits::VariableType(pat_id)); - }); + pat_util::pat_bindings(&input.pat, |_bm, pat_id, sp, _path| { + let var_ty = visit.assign(sp, pat_id, None); + fcx.require_type_is_sized(var_ty, sp, traits::VariableType(pat_id)); + }); // Check the pattern. let pcx = PatCtxt { fcx: &fcx, - map: pat_id_map(&tcx.def_map, &input.pat), + map: pat_id_map(&input.pat), }; pcx.check_pat(&input.pat, *arg_ty); } @@ -3932,8 +3926,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } pub fn check_decl_local(&self, local: &'gcx hir::Local) { - let tcx = self.tcx; - let t = self.local_ty(local.span, local.id); self.write_ty(local.id, t); @@ -3947,7 +3939,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let pcx = PatCtxt { fcx: self, - map: pat_id_map(&tcx.def_map, &local.pat), + map: pat_id_map(&local.pat), }; pcx.check_pat(&local.pat, t); let pat_ty = self.node_ty(local.pat.id); diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index bf34428832d2e..fd1b60551734c 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -452,7 +452,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { fn constrain_bindings_in_pat(&mut self, pat: &hir::Pat) { let tcx = self.tcx; debug!("regionck::visit_pat(pat={:?})", pat); - pat_util::pat_bindings(&tcx.def_map, pat, |_, id, span, _| { + pat_util::pat_bindings(pat, |_, id, span, _| { // If we have a variable that contains region'd data, that // data will be accessible from anywhere that the variable is // accessed. We must be wary of loops like this: diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index e6500747c05b3..205eaf1a38e14 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -15,7 +15,6 @@ use self::ResolveReason::*; use check::FnCtxt; use hir::def_id::DefId; -use hir::pat_util; use rustc::ty::{self, Ty, TyCtxt, MethodCall, MethodCallee}; use rustc::ty::adjustment; use rustc::ty::fold::{TypeFolder,TypeFoldable}; @@ -29,7 +28,7 @@ use syntax::ast; use syntax::codemap::{DUMMY_SP, Span}; use rustc::hir::print::pat_to_string; use rustc::hir::intravisit::{self, Visitor}; -use rustc::hir; +use rustc::hir::{self, PatKind}; /////////////////////////////////////////////////////////////////////////// // Entry point functions @@ -54,9 +53,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { wbcx.visit_pat(&arg.pat); // Privacy needs the type for the whole pattern, not just each binding - if !pat_util::pat_is_binding(&self.tcx.def_map.borrow(), &arg.pat) { - wbcx.visit_node_id(ResolvingPattern(arg.pat.span), - arg.pat.id); + if let PatKind::Binding(..) = arg.pat.node {} else { + wbcx.visit_node_id(ResolvingPattern(arg.pat.span), arg.pat.id); } } wbcx.visit_upvar_borrow_map(); diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 9ecaa5b346af4..be8d296dab09b 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -616,14 +616,10 @@ pub enum PatKind { /// Represents a wildcard pattern (`_`) Wild, - /// A `PatKind::Ident` may either be a new bound variable, - /// or a unit struct/variant pattern, or a const pattern (in the last two cases - /// the third field must be `None`). - /// - /// In the unit or const pattern case, the parser can't determine - /// which it is. The resolver determines this, and - /// records this pattern's `NodeId` in an auxiliary - /// set (of "PatIdents that refer to unit patterns or constants"). + /// A `PatKind::Ident` may either be a new bound variable (`ref mut binding @ OPT_SUBPATTERN`), + /// or a unit struct/variant pattern, or a const pattern (in the last two cases the third + /// field must be `None`). Disambiguation cannot be done with parser alone, so it happens + /// during name resolution. Ident(BindingMode, SpannedIdent, Option>), /// A struct or struct variant pattern, e.g. `Variant {x, y, ..}`. @@ -639,10 +635,8 @@ pub enum PatKind { /// Such pattern can be resolved to a unit struct/variant or a constant. Path(Path), - /// An associated const named using the qualified path `::CONST` or - /// `::CONST`. Associated consts from inherent impls can be - /// referred to as simply `T::CONST`, in which case they will end up as - /// PatKind::Path, and the resolver will have to sort that out. + /// A path pattern written in qualified form, i.e. `::CONST` or `::CONST`. + /// Such patterns can only refer to associated constants at the moment. QPath(QSelf, Path), /// A tuple pattern `(a, b)`. From ae999e9c8f063eb62c867eafdd86729acd798044 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 6 Mar 2016 15:54:44 +0300 Subject: [PATCH 3/3] Address review comments --- src/librustc/hir/mod.rs | 6 ++++-- src/librustc/middle/expr_use_visitor.rs | 7 +------ src/libsyntax/ast.rs | 6 ++++-- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index bf3d003f51cb5..c36c88c7990d3 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -540,8 +540,10 @@ pub enum PatKind { /// Such pattern can be resolved to a unit struct/variant or a constant. Path(Path), - /// A path pattern written in qualified form, i.e. `::CONST` or `::CONST`. - /// Such patterns can only refer to associated constants at the moment. + /// An associated const named using the qualified path `::CONST` or + /// `::CONST`. Associated consts from inherent impls can be + /// referred to as simply `T::CONST`, in which case they will end up as + /// PatKind::Path, and the resolver will have to sort that out. QPath(QSelf, Path), /// A tuple pattern `(a, b)`. diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index cf07493fa7b60..48b5420dd6be7 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -1043,11 +1043,6 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { PatKind::Struct(..) | PatKind::TupleStruct(..) | PatKind::Path(..) | PatKind::QPath(..) => { match def_map.get(&pat.id).map(|d| d.full_def()) { - None => { - // no definition found: pat is not a - // struct or enum pattern. - } - Some(Def::Variant(enum_did, variant_did)) => { let downcast_cmt = if tcx.lookup_adt_def(enum_did).is_univariant() { @@ -1083,7 +1078,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { // `matched_pat` call. } - Some(def) => { + def => { // An enum type should never be in a pattern. // Remaining cases are e.g. Def::Fn, to // which identifiers within patterns diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index be8d296dab09b..488d8ed2e5e35 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -635,8 +635,10 @@ pub enum PatKind { /// Such pattern can be resolved to a unit struct/variant or a constant. Path(Path), - /// A path pattern written in qualified form, i.e. `::CONST` or `::CONST`. - /// Such patterns can only refer to associated constants at the moment. + /// An associated const named using the qualified path `::CONST` or + /// `::CONST`. Associated consts from inherent impls can be + /// referred to as simply `T::CONST`, in which case they will end up as + /// PatKind::Path, and the resolver will have to sort that out. QPath(QSelf, Path), /// A tuple pattern `(a, b)`.