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.)
use hir::def::Def;
use hir::def_id::DefId;
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;
use syntax::ast;
use syntax::codemap::Spanned;
use syntax_pos::Span;
/// 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)
/// 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 {
{
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);
fn walk_local(&mut self, local: &hir::Local) {
match local.init {
None => {
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);
use ty::{self, TyCtxt};
use lint;
use errors::Applicability;
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 std::collections::VecDeque;
use std::{fmt, u32};
use syntax::symbol::keywords;
use syntax_pos::Span;
use syntax::symbol::keywords;
use syntax_pos::Span;
use hir;
use hir::intravisit::{self, Visitor, FnKind, NestedVisitorMap};
use hir;
use hir::intravisit::{self, Visitor, FnKind, NestedVisitorMap};
struct CaptureInfo {
ln: LiveNode,
struct CaptureInfo {
ln: LiveNode,
}
#[derive(Copy, Clone, Debug)]
struct LocalInfo {
}
#[derive(Copy, Clone, Debug)]
struct LocalInfo {
name: ast::Name,
is_shorthand: bool,
}
#[derive(Copy, Clone, Debug)]
enum VarKind {
name: ast::Name,
is_shorthand: bool,
}
#[derive(Copy, Clone, Debug)]
enum VarKind {
- Arg(NodeId, ast::Name),
Local(LocalInfo),
CleanExit
}
Local(LocalInfo),
CleanExit
}
num_live_nodes: usize,
num_vars: usize,
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>,
capture_info_map: NodeMap<Rc<Vec<CaptureInfo>>>,
var_kinds: Vec<VarKind>,
lnks: Vec<LiveNodeKind>,
tcx,
num_live_nodes: 0,
num_vars: 0,
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(),
capture_info_map: NodeMap(),
var_kinds: Vec::new(),
lnks: Vec::new(),
- 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);
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 {
}
fn add_variable(&mut self, vk: VarKind) -> Variable {
- 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 => {
Some(&var) => var,
None => {
- span_bug!(span, "no variable registered for id {}", node_id);
+ span_bug!(span, "no variable registered for id {:?}", hir_id);
let body = ir.tcx.hir.body(body_id);
for arg in &body.arguments {
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);
- fn_maps.add_variable(Arg(arg_id, name));
+ fn_maps.add_variable(Arg(hir_id, name));
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`).
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() {
let mut pats = VecDeque::new();
pats.push_back(pat);
while let Some(pat) = pats.pop_front() {
Struct(_, ref fields, _) => {
for field in fields {
if field.node.is_shorthand {
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);
- pat.each_binding(|_bm, p_id, _sp, path1| {
+ pat.each_binding(|_bm, hir_id, _sp, path1| {
- 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 {
ir.add_variable(Local(LocalInfo {
- is_shorthand: shorthand_field_ids.contains(&p_id)
+ is_shorthand: shorthand_field_ids.contains(&hir_id)
hir::ExprPath(hir::QPath::Resolved(_, ref path)) => {
debug!("expr {}: path that leads to {:?}", expr.id, path.def);
if let Def::Local(..) = path.def {
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)
}
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
// Make a live_node for each captured variable, with the span
// being the location that the variable is used. This results
for fv in freevars {
if let Def::Local(rv) = fv.def {
let fv_ln = ir.add_live_node(FreeVarNode(fv.span));
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 });
// live nodes required for interesting control flow:
hir::ExprIf(..) | hir::ExprMatch(..) | hir::ExprWhile(..) | hir::ExprLoop(..) => {
// 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() => {
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);
}
intravisit::walk_expr(ir, expr);
}
- 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
Some(&ln) => ln,
None => {
// This must be a mismatch between the ir_map construction
// creating liveness nodes for.
span_bug!(
span,
// 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
}
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
})
}
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);
{
if let Some(pat) = pat {
self.pat_bindings(pat, f);
match expr.node {
// Interesting cases with control flow or which gen/kill
hir::ExprPath(hir::QPath::Resolved(_, ref path)) => {
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, _) => {
}
hir::ExprField(ref e, _) => {
hir::ExprClosure(.., blk_id, _, _) => {
debug!("{} is an ExprClosure", self.ir.tcx.hir.node_to_pretty_string(expr.id));
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;
let break_ln = succ;
let cont_ln = node;
};
caps.iter().rev().fold(succ, |succ, cap| {
self.init_from_succ(cap.ln, succ);
};
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
})
self.acc(cap.ln, var, ACC_READ | ACC_USE);
cap.ln
})
//
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 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)
self.init_from_succ(ln, else_ln);
self.merge_from_succ(ln, then_ln, false);
self.propagate_through_expr(&cond, ln)
- 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 {
self.init_empty(ln, succ);
let mut first_merge = true;
for arm in arms {
hir::ExprBinary(op, ref l, ref r) if op.node.is_lazy() => {
let r_succ = self.propagate_through_expr(&r, succ);
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);
self.init_from_succ(ln, succ);
self.merge_from_succ(ln, r_succ, false);
-> LiveNode {
match expr.node {
hir::ExprPath(hir::QPath::Resolved(_, ref path)) => {
-> 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
}
// We do not track other places, so just propagate through
- 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)
- let ln = self.live_node(id, span);
+ let ln = self.live_node(hir_id, span);
if acc != 0 {
self.init_from_succ(ln, succ);
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
}
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) => {
-> 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)
// first iteration:
let mut first_merge = true;
// 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 => {}
self.init_empty(ln, succ);
match kind {
LoopLoop => {}
// if there is no later assignment. If this local is actually
// mutable, then check for a reassignment to flag the mutability
// as being used.
// 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);
fn warn_about_unused_args(&self, body: &hir::Body, entry_ln: LiveNode) {
for arg in &body.arguments {
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 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() {
// 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() {
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);
fn warn_about_unused(&self,
sp: Span,
fn warn_about_unused(&self,
sp: Span,
ln: LiveNode,
var: Variable)
-> bool {
ln: LiveNode,
var: Variable)
-> bool {
if is_assigned {
self.ir.tcx
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
} 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),
if self.ir.variable_is_shorthand(var) {
err.span_suggestion_with_applicability(sp, "try ignoring the field",
format!("{}: _", name),
fn warn_about_dead_assign(&self,
sp: Span,
fn warn_about_dead_assign(&self,
sp: Span,
ln: LiveNode,
var: Variable) {
if self.live_on_exit(ln, var).is_none() {
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 {
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 {
&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));
}
}
&format!("value assigned to `{}` is never read", name));
}
}
&self.intern_goals(&[goal])[0]
}
&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,
pub fn lint_node<S: Into<MultiSpan>>(self,
lint: &'static Lint,
id: NodeId,
self.struct_span_lint_node(lint, id, span.into(), msg).emit()
}
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,
pub fn lint_node_note<S: Into<MultiSpan>>(self,
lint: &'static Lint,
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,
pub fn struct_span_lint_node<S: Into<MultiSpan>>(self,
lint: &'static Lint,
id: NodeId,
pub fn NodeMap<T>() -> NodeMap<T> { FxHashMap() }
pub fn DefIdMap<T>() -> DefIdMap<T> { FxHashMap() }
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 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() }
pub fn ItemLocalSet() -> ItemLocalSet { FxHashSet() }
let tcx = self.bccx.tcx;
let mut mutables = FxHashMap();
for p in pats {
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("_") {
let name = path1.node;
// Skip anything that looks like `_foo`
if name.as_str().starts_with("_") {
}
// Skip anything that looks like `&foo` or `&mut foo`, only look
// for by-value bindings
}
// 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"),
let bm = match self.bccx.tables.pat_binding_modes().get(hir_id) {
Some(&bm) => bm,
None => span_bug!(span, "missing binding mode"),
- 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
});
}
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.
// 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();
}
.span_suggestion_short(mut_span, "remove this `mut`", "".to_owned())
.emit();
}
pats: &[P<Pat>]) {
let mut by_ref_span = None;
for pat in pats {
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)
let bm = *cx.tables
.pat_binding_modes()
.get(hir_id)
fn constrain_bindings_in_pat(&mut self, pat: &hir::Pat) {
debug!("regionck::visit_pat(pat={:?})", pat);
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:
// 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:
// 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.
// 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));
let var_scope = self.region_scope_tree.var_scope(hir_id.local_id);
let var_region = self.tcx.mk_region(ty::ReScope(var_scope));