1
Fork 0

Auto merge of #50929 - zackmdavis:hiridification_initiative, r=michaelwoerister

operate on `HirId` instead of `NodeId` in `hir::Pat::each_binding`, and consequences of that

See #50928 for motivation.

Questions—

 * Is #50928 actually a good idea as a plan of record, or is there some reason to keep `NodeId`s?
 * Are the uses of `find_node_for_hir_id` in this initial submission OK (see the FIXME comments)?
 * Can we bikeshed a better method names `struct_span_lint_hir` _&c._? (Coined in analogy to the `struct_span_lint_node` and `NodeId`, but it feels kind of semantically clunky.)

r? @michaelwoerister
This commit is contained in:
bors 2018-05-28 19:16:27 +00:00
commit 5bf68db6ec
13 changed files with 145 additions and 135 deletions

View file

@ -487,14 +487,6 @@ impl Definitions {
self.node_to_hir_id[node_id]
}
pub fn find_node_for_hir_id(&self, hir_id: hir::HirId) -> ast::NodeId {
self.node_to_hir_id
.iter()
.position(|x| *x == hir_id)
.map(|idx| ast::NodeId::new(idx))
.unwrap()
}
#[inline]
pub fn def_index_to_hir_id(&self, def_index: DefIndex) -> hir::HirId {
let space_index = def_index.address_space().index();

View 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 @@ impl hir::Pat {
/// 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
});

View file

@ -608,9 +608,9 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
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, _| {
let node_id = self.mc.tcx.hir.hir_to_node_id(hir_id);
self.delegate.decl_without_init(node_id, span);
})
}

View file

@ -110,7 +110,7 @@ use hir::def::*;
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};
@ -122,7 +122,7 @@ use syntax::ptr::P;
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 @@ impl<'a, '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 @@ impl<'a, 'tcx> IrMaps<'a, 'tcx> {
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 @@ impl<'a, 'tcx> IrMaps<'a, 'tcx> {
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 @@ impl<'a, 'tcx> 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 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
// 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 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
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 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
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 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
};
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 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
//
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 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
// ( 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 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
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 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
-> 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 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
}
}
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 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
// 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 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
// 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 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
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 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
fn warn_about_unused(&self,
sp: Span,
id: NodeId,
hir_id: HirId,
ln: LiveNode,
var: Variable)
-> bool {
@ -1527,14 +1523,14 @@ impl<'a, 'tcx> Liveness<'a, '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
.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 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
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));
}
}

View file

@ -488,7 +488,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
// FIXME
None if self.is_tainted_by_errors() => Err(()),
None => {
let id = self.tcx.hir.definitions().find_node_for_hir_id(id);
let id = self.tcx.hir.hir_to_node_id(id);
bug!("no type for node {}: {} in mem_categorization",
id, self.tcx.hir.node_to_string(id));
}

View file

@ -266,9 +266,7 @@ fn validate_hir_id_for_typeck_tables(local_id_root: Option<DefId>,
if let Some(local_id_root) = local_id_root {
if hir_id.owner != local_id_root.index {
ty::tls::with(|tcx| {
let node_id = tcx.hir
.definitions()
.find_node_for_hir_id(hir_id);
let node_id = tcx.hir.hir_to_node_id(hir_id);
bug!("node {} with HirId::owner {:?} cannot be placed in \
TypeckTables with local_id_root {:?}",
@ -527,7 +525,7 @@ impl<'tcx> TypeckTables<'tcx> {
None => {
bug!("node_id_to_type: no type for node `{}`",
tls::with(|tcx| {
let id = tcx.hir.definitions().find_node_for_hir_id(id);
let id = tcx.hir.hir_to_node_id(id);
tcx.hir.node_to_string(id)
}))
}
@ -2544,6 +2542,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
&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 +2558,17 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
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 +2607,18 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
})
}
pub fn struct_span_lint_hir<S: Into<MultiSpan>>(self,
lint: &'static Lint,
hir_id: HirId,
span: S,
msg: &str)
-> DiagnosticBuilder<'tcx>
{
let node_id = self.hir.hir_to_node_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,

View file

@ -19,20 +19,16 @@ use syntax::ast;
pub use rustc_data_structures::fx::FxHashMap;
pub use rustc_data_structures::fx::FxHashSet;
pub type NodeMap<T> = FxHashMap<ast::NodeId, T>;
pub type DefIdMap<T> = FxHashMap<DefId, T>;
pub type HirIdMap<T> = FxHashMap<HirId, T>;
pub type ItemLocalMap<T> = FxHashMap<ItemLocalId, T>;
pub type NodeSet = FxHashSet<ast::NodeId>;
pub type DefIdSet = FxHashSet<DefId>;
pub type HirIdSet = FxHashSet<HirId>;
pub type ItemLocalSet = FxHashSet<ItemLocalId>;
pub fn NodeMap<T>() -> NodeMap<T> { FxHashMap() }
pub fn DefIdMap<T>() -> DefIdMap<T> { FxHashMap() }
pub fn ItemLocalMap<T>() -> ItemLocalMap<T> { FxHashMap() }
pub fn NodeSet() -> NodeSet { FxHashSet() }
pub fn DefIdSet() -> DefIdSet { FxHashSet() }
pub fn ItemLocalSet() -> ItemLocalSet { FxHashSet() }
macro_rules! define_id_collections {
($map_name:ident, $set_name:ident, $key:ty) => {
pub type $map_name<T> = FxHashMap<$key, T>;
pub fn $map_name<T>() -> $map_name<T> { FxHashMap() }
pub type $set_name = FxHashSet<$key>;
pub fn $set_name() -> $set_name { FxHashSet() }
}
}
define_id_collections!(NodeMap, NodeSet, ast::NodeId);
define_id_collections!(DefIdMap, DefIdSet, DefId);
define_id_collections!(HirIdMap, HirIdSet, HirId);
define_id_collections!(ItemLocalMap, ItemLocalSet, ItemLocalId);

View file

@ -46,17 +46,16 @@ impl<'a, 'tcx> UnusedMutCx<'a, 'tcx> {
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 @@ impl<'a, 'tcx> UnusedMutCx<'a, 'tcx> {
_ => 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();
}

View 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)

View file

@ -2110,7 +2110,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
Some(&t) => t,
None if self.is_tainted_by_errors() => self.tcx.types.err,
None => {
let node_id = self.tcx.hir.definitions().find_node_for_hir_id(id);
let node_id = self.tcx.hir.hir_to_node_id(id);
bug!("no type for node {}: {} in fcx {}",
node_id, self.tcx.hir.node_to_string(node_id),
self.tag());

View file

@ -380,7 +380,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
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 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
// 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));

View file

@ -560,7 +560,7 @@ impl Locatable for DefIndex {
impl Locatable for hir::HirId {
fn to_span(&self, tcx: &TyCtxt) -> Span {
let node_id = tcx.hir.definitions().find_node_for_hir_id(*self);
let node_id = tcx.hir.hir_to_node_id(*self);
tcx.hir.span(node_id)
}
}

View file

@ -106,7 +106,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
}
assert_eq!(def_id.krate, LOCAL_CRATE);
let hir_id = tcx.hir.definitions().def_index_to_hir_id(def_id.index);
let id = tcx.hir.definitions().find_node_for_hir_id(hir_id);
let id = tcx.hir.hir_to_node_id(hir_id);
let lint = lint::builtin::UNUSED_EXTERN_CRATES;
let msg = "unused extern crate";
tcx.lint_node(lint, id, span, msg);