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)`.