]> git.lizzy.rs Git - rust.git/commitdiff
operate on `HirId` in `hir::Pat::each_binding`, and consequences of that
authorZack M. Davis <code@zackmdavis.net>
Mon, 21 May 2018 03:19:34 +0000 (20:19 -0700)
committerZack M. Davis <code@zackmdavis.net>
Mon, 28 May 2018 16:20:14 +0000 (09:20 -0700)
Changing the `each_binding` utility method to take the `HirId` of a
binding pattern rather than its `NodeId` seems like a modest first step
in support of the `HirId`ification initiative #50928. (The inspiration
for choosing this in particular came from the present author's previous
work on diagnostics issued during liveness analysis, which is the most
greatly affected module in this change.)

src/librustc/hir/pat_util.rs
src/librustc/middle/expr_use_visitor.rs
src/librustc/middle/liveness.rs
src/librustc/ty/context.rs
src/librustc/util/nodemap.rs
src/librustc_borrowck/borrowck/unused.rs
src/librustc_mir/hair/pattern/check_match.rs
src/librustc_typeck/check/regionck.rs

index 13fff3aa34274d404dbee5d565e681caa97d4896..5a059b6a219a21e7e5468ab99ecaf3459b1cac37 100644 (file)
@@ -10,7 +10,7 @@
 
 use hir::def::Def;
 use hir::def_id::DefId;
-use hir::{self, PatKind};
+use hir::{self, HirId, PatKind};
 use syntax::ast;
 use syntax::codemap::Spanned;
 use syntax_pos::Span;
@@ -91,11 +91,11 @@ pub fn is_const(&self) -> bool {
     /// Call `f` on every "binding" in a pattern, e.g., on `a` in
     /// `match foo() { Some(a) => (), None => () }`
     pub fn each_binding<F>(&self, mut f: F)
-        where F: FnMut(hir::BindingAnnotation, ast::NodeId, Span, &Spanned<ast::Name>),
+        where F: FnMut(hir::BindingAnnotation, HirId, Span, &Spanned<ast::Name>),
     {
         self.walk(|p| {
             if let PatKind::Binding(binding_mode, _, ref pth, _) = p.node {
-                f(binding_mode, p.id, p.span, pth);
+                f(binding_mode, p.hir_id, p.span, pth);
             }
             true
         });
index fd6c2f652f04bfab41fa292202f6bfebdaf5c04a..66c6cf73513ec921d4cfe36e604b1740b8ca454c 100644 (file)
@@ -608,9 +608,10 @@ fn walk_stmt(&mut self, stmt: &hir::Stmt) {
     fn walk_local(&mut self, local: &hir::Local) {
         match local.init {
             None => {
-                let delegate = &mut self.delegate;
-                local.pat.each_binding(|_, id, span, _| {
-                    delegate.decl_without_init(id, span);
+                local.pat.each_binding(|_, hir_id, span, _| {
+                    // FIXME: converting HirId → NodeId is said to be relatively expensive
+                    let node_id = self.mc.tcx.hir.definitions().find_node_for_hir_id(hir_id);
+                    self.delegate.decl_without_init(node_id, span);
                 })
             }
 
index 3633d6f9934ec8558d779b427db2477c2aa58f87..82686bc737bc818eb7a7dc2e9f9374164701acf0 100644 (file)
 use ty::{self, TyCtxt};
 use lint;
 use errors::Applicability;
-use util::nodemap::{NodeMap, NodeSet};
+use util::nodemap::{NodeMap, HirIdMap, HirIdSet};
 
 use std::collections::VecDeque;
 use std::{fmt, u32};
 use syntax::symbol::keywords;
 use syntax_pos::Span;
 
-use hir::Expr;
+use hir::{Expr, HirId};
 use hir;
 use hir::intravisit::{self, Visitor, FnKind, NestedVisitorMap};
 
@@ -236,19 +236,19 @@ fn invalid_node() -> LiveNode { LiveNode(u32::MAX) }
 
 struct CaptureInfo {
     ln: LiveNode,
-    var_nid: NodeId
+    var_hid: HirId
 }
 
 #[derive(Copy, Clone, Debug)]
 struct LocalInfo {
-    id: NodeId,
+    id: HirId,
     name: ast::Name,
     is_shorthand: bool,
 }
 
 #[derive(Copy, Clone, Debug)]
 enum VarKind {
-    Arg(NodeId, ast::Name),
+    Arg(HirId, ast::Name),
     Local(LocalInfo),
     CleanExit
 }
@@ -258,8 +258,8 @@ struct IrMaps<'a, 'tcx: 'a> {
 
     num_live_nodes: usize,
     num_vars: usize,
-    live_node_map: NodeMap<LiveNode>,
-    variable_map: NodeMap<Variable>,
+    live_node_map: HirIdMap<LiveNode>,
+    variable_map: HirIdMap<Variable>,
     capture_info_map: NodeMap<Rc<Vec<CaptureInfo>>>,
     var_kinds: Vec<VarKind>,
     lnks: Vec<LiveNodeKind>,
@@ -271,8 +271,8 @@ fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> IrMaps<'a, 'tcx> {
             tcx,
             num_live_nodes: 0,
             num_vars: 0,
-            live_node_map: NodeMap(),
-            variable_map: NodeMap(),
+            live_node_map: HirIdMap(),
+            variable_map: HirIdMap(),
             capture_info_map: NodeMap(),
             var_kinds: Vec::new(),
             lnks: Vec::new(),
@@ -290,11 +290,11 @@ fn add_live_node(&mut self, lnk: LiveNodeKind) -> LiveNode {
         ln
     }
 
-    fn add_live_node_for_node(&mut self, node_id: NodeId, lnk: LiveNodeKind) {
+    fn add_live_node_for_node(&mut self, hir_id: HirId, lnk: LiveNodeKind) {
         let ln = self.add_live_node(lnk);
-        self.live_node_map.insert(node_id, ln);
+        self.live_node_map.insert(hir_id, ln);
 
-        debug!("{:?} is node {}", ln, node_id);
+        debug!("{:?} is node {:?}", ln, hir_id);
     }
 
     fn add_variable(&mut self, vk: VarKind) -> Variable {
@@ -314,11 +314,11 @@ fn add_variable(&mut self, vk: VarKind) -> Variable {
         v
     }
 
-    fn variable(&self, node_id: NodeId, span: Span) -> Variable {
-        match self.variable_map.get(&node_id) {
+    fn variable(&self, hir_id: HirId, span: Span) -> Variable {
+        match self.variable_map.get(&hir_id) {
             Some(&var) => var,
             None => {
-                span_bug!(span, "no variable registered for id {}", node_id);
+                span_bug!(span, "no variable registered for id {:?}", hir_id);
             }
         }
     }
@@ -374,10 +374,10 @@ fn visit_fn<'a, 'tcx: 'a>(ir: &mut IrMaps<'a, 'tcx>,
     let body = ir.tcx.hir.body(body_id);
 
     for arg in &body.arguments {
-        arg.pat.each_binding(|_bm, arg_id, _x, path1| {
-            debug!("adding argument {}", arg_id);
+        arg.pat.each_binding(|_bm, hir_id, _x, path1| {
+            debug!("adding argument {:?}", hir_id);
             let name = path1.node;
-            fn_maps.add_variable(Arg(arg_id, name));
+            fn_maps.add_variable(Arg(hir_id, name));
         })
     };
 
@@ -397,11 +397,7 @@ fn visit_fn<'a, 'tcx: 'a>(ir: &mut IrMaps<'a, 'tcx>,
 fn add_from_pat<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, pat: &P<hir::Pat>) {
     // For struct patterns, take note of which fields used shorthand
     // (`x` rather than `x: x`).
-    //
-    // FIXME: according to the rust-lang-nursery/rustc-guide book, `NodeId`s are to be
-    // phased out in favor of `HirId`s; however, we need to match the signature of
-    // `each_binding`, which uses `NodeIds`.
-    let mut shorthand_field_ids = NodeSet();
+    let mut shorthand_field_ids = HirIdSet();
     let mut pats = VecDeque::new();
     pats.push_back(pat);
     while let Some(pat) = pats.pop_front() {
@@ -413,7 +409,7 @@ fn add_from_pat<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, pat: &P<hir::Pat>) {
             Struct(_, ref fields, _) => {
                 for field in fields {
                     if field.node.is_shorthand {
-                        shorthand_field_ids.insert(field.node.pat.id);
+                        shorthand_field_ids.insert(field.node.pat.hir_id);
                     }
                 }
             }
@@ -434,13 +430,13 @@ fn add_from_pat<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, pat: &P<hir::Pat>) {
         }
     }
 
-    pat.each_binding(|_bm, p_id, _sp, path1| {
+    pat.each_binding(|_bm, hir_id, _sp, path1| {
         let name = path1.node;
-        ir.add_live_node_for_node(p_id, VarDefNode(path1.span));
+        ir.add_live_node_for_node(hir_id, VarDefNode(path1.span));
         ir.add_variable(Local(LocalInfo {
-            id: p_id,
+            id: hir_id,
             name,
-            is_shorthand: shorthand_field_ids.contains(&p_id)
+            is_shorthand: shorthand_field_ids.contains(&hir_id)
         }));
     });
 }
@@ -463,14 +459,14 @@ fn visit_expr<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, expr: &'tcx Expr) {
       hir::ExprPath(hir::QPath::Resolved(_, ref path)) => {
         debug!("expr {}: path that leads to {:?}", expr.id, path.def);
         if let Def::Local(..) = path.def {
-            ir.add_live_node_for_node(expr.id, ExprNode(expr.span));
+            ir.add_live_node_for_node(expr.hir_id, ExprNode(expr.span));
         }
         intravisit::walk_expr(ir, expr);
       }
       hir::ExprClosure(..) => {
         // Interesting control flow (for loops can contain labeled
         // breaks or continues)
-        ir.add_live_node_for_node(expr.id, ExprNode(expr.span));
+        ir.add_live_node_for_node(expr.hir_id, ExprNode(expr.span));
 
         // Make a live_node for each captured variable, with the span
         // being the location that the variable is used.  This results
@@ -481,8 +477,8 @@ fn visit_expr<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, expr: &'tcx Expr) {
             for fv in freevars {
                 if let Def::Local(rv) = fv.def {
                     let fv_ln = ir.add_live_node(FreeVarNode(fv.span));
-                    call_caps.push(CaptureInfo {ln: fv_ln,
-                                                var_nid: rv});
+                    let var_hid = ir.tcx.hir.node_to_hir_id(rv);
+                    call_caps.push(CaptureInfo { ln: fv_ln, var_hid });
                 }
             }
         });
@@ -493,11 +489,11 @@ fn visit_expr<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, expr: &'tcx Expr) {
 
       // live nodes required for interesting control flow:
       hir::ExprIf(..) | hir::ExprMatch(..) | hir::ExprWhile(..) | hir::ExprLoop(..) => {
-        ir.add_live_node_for_node(expr.id, ExprNode(expr.span));
+        ir.add_live_node_for_node(expr.hir_id, ExprNode(expr.span));
         intravisit::walk_expr(ir, expr);
       }
       hir::ExprBinary(op, ..) if op.node.is_lazy() => {
-        ir.add_live_node_for_node(expr.id, ExprNode(expr.span));
+        ir.add_live_node_for_node(expr.hir_id, ExprNode(expr.span));
         intravisit::walk_expr(ir, expr);
       }
 
@@ -590,8 +586,8 @@ fn new(ir: &'a mut IrMaps<'a, 'tcx>, body: hir::BodyId) -> Liveness<'a, 'tcx> {
         }
     }
 
-    fn live_node(&self, node_id: NodeId, span: Span) -> LiveNode {
-        match self.ir.live_node_map.get(&node_id) {
+    fn live_node(&self, hir_id: HirId, span: Span) -> LiveNode {
+        match self.ir.live_node_map.get(&hir_id) {
           Some(&ln) => ln,
           None => {
             // This must be a mismatch between the ir_map construction
@@ -600,28 +596,28 @@ fn live_node(&self, node_id: NodeId, span: Span) -> LiveNode {
             // creating liveness nodes for.
             span_bug!(
                 span,
-                "no live node registered for node {}",
-                node_id);
+                "no live node registered for node {:?}",
+                hir_id);
           }
         }
     }
 
-    fn variable(&self, node_id: NodeId, span: Span) -> Variable {
-        self.ir.variable(node_id, span)
+    fn variable(&self, hir_id: HirId, span: Span) -> Variable {
+        self.ir.variable(hir_id, span)
     }
 
     fn pat_bindings<F>(&mut self, pat: &hir::Pat, mut f: F) where
-        F: FnMut(&mut Liveness<'a, 'tcx>, LiveNode, Variable, Span, NodeId),
+        F: FnMut(&mut Liveness<'a, 'tcx>, LiveNode, Variable, Span, HirId),
     {
-        pat.each_binding(|_bm, p_id, sp, n| {
-            let ln = self.live_node(p_id, sp);
-            let var = self.variable(p_id, n.span);
-            f(self, ln, var, n.span, p_id);
+        pat.each_binding(|_bm, hir_id, sp, n| {
+            let ln = self.live_node(hir_id, sp);
+            let var = self.variable(hir_id, n.span);
+            f(self, ln, var, n.span, hir_id);
         })
     }
 
     fn arm_pats_bindings<F>(&mut self, pat: Option<&hir::Pat>, f: F) where
-        F: FnMut(&mut Liveness<'a, 'tcx>, LiveNode, Variable, Span, NodeId),
+        F: FnMut(&mut Liveness<'a, 'tcx>, LiveNode, Variable, Span, HirId),
     {
         if let Some(pat) = pat {
             self.pat_bindings(pat, f);
@@ -927,7 +923,7 @@ fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode)
         match expr.node {
           // Interesting cases with control flow or which gen/kill
           hir::ExprPath(hir::QPath::Resolved(_, ref path)) => {
-              self.access_path(expr.id, path, succ, ACC_READ | ACC_USE)
+              self.access_path(expr.hir_id, path, succ, ACC_READ | ACC_USE)
           }
 
           hir::ExprField(ref e, _) => {
@@ -937,11 +933,9 @@ fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode)
           hir::ExprClosure(.., blk_id, _, _) => {
               debug!("{} is an ExprClosure", self.ir.tcx.hir.node_to_pretty_string(expr.id));
 
-              /*
-              The next-node for a break is the successor of the entire
-              loop. The next-node for a continue is the top of this loop.
-              */
-              let node = self.live_node(expr.id, expr.span);
+              // The next-node for a break is the successor of the entire
+              // loop. The next-node for a continue is the top of this loop.
+              let node = self.live_node(expr.hir_id, expr.span);
 
               let break_ln = succ;
               let cont_ln = node;
@@ -958,7 +952,7 @@ fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode)
               };
               caps.iter().rev().fold(succ, |succ, cap| {
                   self.init_from_succ(cap.ln, succ);
-                  let var = self.variable(cap.var_nid, expr.span);
+                  let var = self.variable(cap.var_hid, expr.span);
                   self.acc(cap.ln, var, ACC_READ | ACC_USE);
                   cap.ln
               })
@@ -980,7 +974,7 @@ fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode)
             //
             let else_ln = self.propagate_through_opt_expr(els.as_ref().map(|e| &**e), succ);
             let then_ln = self.propagate_through_expr(&then, succ);
-            let ln = self.live_node(expr.id, expr.span);
+            let ln = self.live_node(expr.hir_id, expr.span);
             self.init_from_succ(ln, else_ln);
             self.merge_from_succ(ln, then_ln, false);
             self.propagate_through_expr(&cond, ln)
@@ -1011,7 +1005,7 @@ fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode)
             //   (  succ  )
             //
             //
-            let ln = self.live_node(expr.id, expr.span);
+            let ln = self.live_node(expr.hir_id, expr.span);
             self.init_empty(ln, succ);
             let mut first_merge = true;
             for arm in arms {
@@ -1132,7 +1126,7 @@ fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode)
           hir::ExprBinary(op, ref l, ref r) if op.node.is_lazy() => {
             let r_succ = self.propagate_through_expr(&r, succ);
 
-            let ln = self.live_node(expr.id, expr.span);
+            let ln = self.live_node(expr.hir_id, expr.span);
             self.init_from_succ(ln, succ);
             self.merge_from_succ(ln, r_succ, false);
 
@@ -1249,7 +1243,7 @@ fn write_place(&mut self, expr: &Expr, succ: LiveNode, acc: u32)
                     -> LiveNode {
         match expr.node {
           hir::ExprPath(hir::QPath::Resolved(_, ref path)) => {
-              self.access_path(expr.id, path, succ, acc)
+              self.access_path(expr.hir_id, path, succ, acc)
           }
 
           // We do not track other places, so just propagate through
@@ -1260,22 +1254,23 @@ fn write_place(&mut self, expr: &Expr, succ: LiveNode, acc: u32)
         }
     }
 
-    fn access_var(&mut self, id: NodeId, nid: NodeId, succ: LiveNode, acc: u32, span: Span)
+    fn access_var(&mut self, hir_id: HirId, nid: NodeId, succ: LiveNode, acc: u32, span: Span)
                   -> LiveNode {
-        let ln = self.live_node(id, span);
+        let ln = self.live_node(hir_id, span);
         if acc != 0 {
             self.init_from_succ(ln, succ);
-            let var = self.variable(nid, span);
+            let var_hid = self.ir.tcx.hir.node_to_hir_id(nid);
+            let var = self.variable(var_hid, span);
             self.acc(ln, var, acc);
         }
         ln
     }
 
-    fn access_path(&mut self, id: NodeId, path: &hir::Path, succ: LiveNode, acc: u32)
+    fn access_path(&mut self, hir_id: HirId, path: &hir::Path, succ: LiveNode, acc: u32)
                    -> LiveNode {
         match path.def {
           Def::Local(nid) => {
-            self.access_var(id, nid, succ, acc, path.span)
+            self.access_var(hir_id, nid, succ, acc, path.span)
           }
           _ => succ
         }
@@ -1309,7 +1304,7 @@ fn propagate_through_loop(&mut self,
 
         // first iteration:
         let mut first_merge = true;
-        let ln = self.live_node(expr.id, expr.span);
+        let ln = self.live_node(expr.hir_id, expr.span);
         self.init_empty(ln, succ);
         match kind {
             LoopLoop => {}
@@ -1455,9 +1450,10 @@ fn check_place(&mut self, expr: &'tcx Expr) {
                     // if there is no later assignment. If this local is actually
                     // mutable, then check for a reassignment to flag the mutability
                     // as being used.
-                    let ln = self.live_node(expr.id, expr.span);
-                    let var = self.variable(nid, expr.span);
-                    self.warn_about_dead_assign(expr.span, expr.id, ln, var);
+                    let ln = self.live_node(expr.hir_id, expr.span);
+                    let var_hid = self.ir.tcx.hir.node_to_hir_id(nid);
+                    let var = self.variable(var_hid, expr.span);
+                    self.warn_about_dead_assign(expr.span, expr.hir_id, ln, var);
                 }
             }
             _ => {
@@ -1479,15 +1475,15 @@ fn should_warn(&self, var: Variable) -> Option<String> {
 
     fn warn_about_unused_args(&self, body: &hir::Body, entry_ln: LiveNode) {
         for arg in &body.arguments {
-            arg.pat.each_binding(|_bm, p_id, _, path1| {
+            arg.pat.each_binding(|_bm, hir_id, _, path1| {
                 let sp = path1.span;
-                let var = self.variable(p_id, sp);
+                let var = self.variable(hir_id, sp);
                 // Ignore unused self.
                 let name = path1.node;
                 if name != keywords::SelfValue.name() {
-                    if !self.warn_about_unused(sp, p_id, entry_ln, var) {
+                    if !self.warn_about_unused(sp, hir_id, entry_ln, var) {
                         if self.live_on_entry(entry_ln, var).is_none() {
-                            self.report_dead_assign(p_id, sp, var, true);
+                            self.report_dead_assign(hir_id, sp, var, true);
                         }
                     }
                 }
@@ -1505,7 +1501,7 @@ fn warn_about_unused_or_dead_vars_in_pat(&mut self, pat: &hir::Pat) {
 
     fn warn_about_unused(&self,
                          sp: Span,
-                         id: NodeId,
+                         hir_id: HirId,
                          ln: LiveNode,
                          var: Variable)
                          -> bool {
@@ -1527,14 +1523,14 @@ fn warn_about_unused(&self,
 
                 if is_assigned {
                     self.ir.tcx
-                        .lint_node_note(lint::builtin::UNUSED_VARIABLES, id, sp,
-                                        &format!("variable `{}` is assigned to, but never used",
-                                                 name),
-                                        &suggest_underscore_msg);
+                        .lint_hir_note(lint::builtin::UNUSED_VARIABLES, hir_id, sp,
+                                       &format!("variable `{}` is assigned to, but never used",
+                                                name),
+                                       &suggest_underscore_msg);
                 } else if name != "self" {
                     let msg = format!("unused variable: `{}`", name);
                     let mut err = self.ir.tcx
-                        .struct_span_lint_node(lint::builtin::UNUSED_VARIABLES, id, sp, &msg);
+                        .struct_span_lint_hir(lint::builtin::UNUSED_VARIABLES, hir_id, sp, &msg);
                     if self.ir.variable_is_shorthand(var) {
                         err.span_suggestion_with_applicability(sp, "try ignoring the field",
                                                                format!("{}: _", name),
@@ -1557,21 +1553,21 @@ fn warn_about_unused(&self,
 
     fn warn_about_dead_assign(&self,
                               sp: Span,
-                              id: NodeId,
+                              hir_id: HirId,
                               ln: LiveNode,
                               var: Variable) {
         if self.live_on_exit(ln, var).is_none() {
-            self.report_dead_assign(id, sp, var, false);
+            self.report_dead_assign(hir_id, sp, var, false);
         }
     }
 
-    fn report_dead_assign(&self, id: NodeId, sp: Span, var: Variable, is_argument: bool) {
+    fn report_dead_assign(&self, hir_id: HirId, sp: Span, var: Variable, is_argument: bool) {
         if let Some(name) = self.should_warn(var) {
             if is_argument {
-                self.ir.tcx.lint_node(lint::builtin::UNUSED_ASSIGNMENTS, id, sp,
+                self.ir.tcx.lint_hir(lint::builtin::UNUSED_ASSIGNMENTS, hir_id, sp,
                     &format!("value passed to `{}` is never read", name));
             } else {
-                self.ir.tcx.lint_node(lint::builtin::UNUSED_ASSIGNMENTS, id, sp,
+                self.ir.tcx.lint_hir(lint::builtin::UNUSED_ASSIGNMENTS, hir_id, sp,
                     &format!("value assigned to `{}` is never read", name));
             }
         }
index 2b2da6f842bb6245973e53162996c66c31f1c12c..df2996d7ee1f55f6a9529764107697102c912886 100644 (file)
@@ -2544,6 +2544,14 @@ pub fn mk_goal(self, goal: Goal<'tcx>) -> &'tcx Goal {
         &self.intern_goals(&[goal])[0]
     }
 
+    pub fn lint_hir<S: Into<MultiSpan>>(self,
+                                        lint: &'static Lint,
+                                        hir_id: HirId,
+                                        span: S,
+                                        msg: &str) {
+        self.struct_span_lint_hir(lint, hir_id, span.into(), msg).emit()
+    }
+
     pub fn lint_node<S: Into<MultiSpan>>(self,
                                          lint: &'static Lint,
                                          id: NodeId,
@@ -2552,6 +2560,17 @@ pub fn lint_node<S: Into<MultiSpan>>(self,
         self.struct_span_lint_node(lint, id, span.into(), msg).emit()
     }
 
+    pub fn lint_hir_note<S: Into<MultiSpan>>(self,
+                                              lint: &'static Lint,
+                                              hir_id: HirId,
+                                              span: S,
+                                              msg: &str,
+                                              note: &str) {
+        let mut err = self.struct_span_lint_hir(lint, hir_id, span.into(), msg);
+        err.note(note);
+        err.emit()
+    }
+
     pub fn lint_node_note<S: Into<MultiSpan>>(self,
                                               lint: &'static Lint,
                                               id: NodeId,
@@ -2590,6 +2609,19 @@ pub fn lint_level_at_node(self, lint: &'static Lint, mut id: NodeId)
         })
     }
 
+    pub fn struct_span_lint_hir<S: Into<MultiSpan>>(self,
+                                                    lint: &'static Lint,
+                                                    hir_id: HirId,
+                                                    span: S,
+                                                    msg: &str)
+        -> DiagnosticBuilder<'tcx>
+    {
+        // FIXME: converting HirId → NodeId is said to be relatively expensive
+        let node_id = self.hir.definitions().find_node_for_hir_id(hir_id);
+        let (level, src) = self.lint_level_at_node(lint, node_id);
+        lint::struct_lint_level(self.sess, lint, level, src, Some(span.into()), msg)
+    }
+
     pub fn struct_span_lint_node<S: Into<MultiSpan>>(self,
                                                      lint: &'static Lint,
                                                      id: NodeId,
index f98a8f834df8a912f1bdb914f1d904eed1c6270e..c92aa24b8cf5a93681a70a605826124840a39eae 100644 (file)
@@ -31,8 +31,9 @@
 
 pub fn NodeMap<T>() -> NodeMap<T> { FxHashMap() }
 pub fn DefIdMap<T>() -> DefIdMap<T> { FxHashMap() }
+pub fn HirIdMap<T>() -> HirIdMap<T> { FxHashMap() }
 pub fn ItemLocalMap<T>() -> ItemLocalMap<T> { FxHashMap() }
 pub fn NodeSet() -> NodeSet { FxHashSet() }
 pub fn DefIdSet() -> DefIdSet { FxHashSet() }
+pub fn HirIdSet() -> HirIdSet { FxHashSet() }
 pub fn ItemLocalSet() -> ItemLocalSet { FxHashSet() }
-
index 7bcd8a185453b11004648411493a1bf70febb5dd..b2b4c7d777eabdc20136e9d1a7ca20326d43c165 100644 (file)
@@ -46,17 +46,16 @@ fn check_unused_mut_pat(&self, pats: &[P<hir::Pat>]) {
         let tcx = self.bccx.tcx;
         let mut mutables = FxHashMap();
         for p in pats {
-            p.each_binding(|_, id, span, path1| {
+            p.each_binding(|_, hir_id, span, path1| {
                 let name = path1.node;
 
                 // Skip anything that looks like `_foo`
                 if name.as_str().starts_with("_") {
-                    return
+                    return;
                 }
 
                 // Skip anything that looks like `&foo` or `&mut foo`, only look
                 // for by-value bindings
-                let hir_id = tcx.hir.node_to_hir_id(id);
                 let bm = match self.bccx.tables.pat_binding_modes().get(hir_id) {
                     Some(&bm) => bm,
                     None => span_bug!(span, "missing binding mode"),
@@ -66,25 +65,26 @@ fn check_unused_mut_pat(&self, pats: &[P<hir::Pat>]) {
                     _ => return,
                 }
 
-                mutables.entry(name).or_insert(Vec::new()).push((id, hir_id, span));
+                mutables.entry(name).or_insert(Vec::new()).push((hir_id, span));
             });
         }
 
         for (_name, ids) in mutables {
             // If any id for this name was used mutably then consider them all
             // ok, so move on to the next
-            if ids.iter().any(|&(_, ref id, _)| self.used_mut.contains(id)) {
-                continue
+            if ids.iter().any(|&(ref hir_id, _)| self.used_mut.contains(hir_id)) {
+                continue;
             }
 
-            let mut_span = tcx.sess.codemap().span_until_non_whitespace(ids[0].2);
+            let (hir_id, span) = ids[0];
+            let mut_span = tcx.sess.codemap().span_until_non_whitespace(span);
 
             // Ok, every name wasn't used mutably, so issue a warning that this
             // didn't need to be mutable.
-            tcx.struct_span_lint_node(UNUSED_MUT,
-                                      ids[0].0,
-                                      ids[0].2,
-                                      "variable does not need to be mutable")
+            tcx.struct_span_lint_hir(UNUSED_MUT,
+                                     hir_id,
+                                     span,
+                                     "variable does not need to be mutable")
                 .span_suggestion_short(mut_span, "remove this `mut`", "".to_owned())
                 .emit();
         }
index 77bcd88cecb6ed0e6f362e6c8501f0126d0a8465..7c44a8d4d5f3b7b2251c391b93627d73fd1165c7 100644 (file)
@@ -499,8 +499,7 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor,
                                    pats: &[P<Pat>]) {
     let mut by_ref_span = None;
     for pat in pats {
-        pat.each_binding(|_, id, span, _path| {
-            let hir_id = cx.tcx.hir.node_to_hir_id(id);
+        pat.each_binding(|_, hir_id, span, _path| {
             let bm = *cx.tables
                         .pat_binding_modes()
                         .get(hir_id)
index badf5bcb6a9a0d45e7ececfb78b3381171c5593a..fa8045d70321f4c9a7deedc8c00daf60babcdb3f 100644 (file)
@@ -380,7 +380,7 @@ fn resolve_regions_and_report_errors_unless_nll(&self) {
 
     fn constrain_bindings_in_pat(&mut self, pat: &hir::Pat) {
         debug!("regionck::visit_pat(pat={:?})", pat);
-        pat.each_binding(|_, id, span, _| {
+        pat.each_binding(|_, hir_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:
@@ -403,8 +403,6 @@ fn constrain_bindings_in_pat(&mut self, pat: &hir::Pat) {
             // iteration. The easiest way to guarantee this is to require
             // that the lifetime of any regions that appear in a
             // variable's type enclose at least the variable's scope.
-
-            let hir_id = self.tcx.hir.node_to_hir_id(id);
             let var_scope = self.region_scope_tree.var_scope(hir_id.local_id);
             let var_region = self.tcx.mk_region(ty::ReScope(var_scope));