diff --git a/src/librustc/hir/def_id.rs b/src/librustc/hir/def_id.rs index 7f76e1bf770bf..bb3b248674ab7 100644 --- a/src/librustc/hir/def_id.rs +++ b/src/librustc/hir/def_id.rs @@ -201,4 +201,11 @@ impl DefId { pub fn is_local(&self) -> bool { self.krate == LOCAL_CRATE } + + pub fn invalid() -> DefId { + DefId { + krate: INVALID_CRATE, + index: CRATE_DEF_INDEX, + } + } } diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 421a81c0d2342..27048a71454bc 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -155,6 +155,11 @@ enum ParamMode { Optional } +struct LoweredNodeId { + node_id: NodeId, + hir_id: hir::HirId, +} + impl<'a> LoweringContext<'a> { fn lower_crate(mut self, c: &Crate) -> hir::Crate { /// Full-crate AST visitor that inserts into a fresh @@ -278,11 +283,14 @@ impl<'a> LoweringContext<'a> { fn lower_node_id_generic(&mut self, ast_node_id: NodeId, alloc_hir_id: F) - -> NodeId + -> LoweredNodeId where F: FnOnce(&mut Self) -> hir::HirId { if ast_node_id == DUMMY_NODE_ID { - return ast_node_id; + return LoweredNodeId { + node_id: DUMMY_NODE_ID, + hir_id: hir::DUMMY_HIR_ID, + } } let min_size = ast_node_id.as_usize() + 1; @@ -291,12 +299,22 @@ impl<'a> LoweringContext<'a> { self.node_id_to_hir_id.resize(min_size, hir::DUMMY_HIR_ID); } - if self.node_id_to_hir_id[ast_node_id] == hir::DUMMY_HIR_ID { + let existing_hir_id = self.node_id_to_hir_id[ast_node_id]; + + if existing_hir_id == hir::DUMMY_HIR_ID { // Generate a new HirId - self.node_id_to_hir_id[ast_node_id] = alloc_hir_id(self); + let hir_id = alloc_hir_id(self); + self.node_id_to_hir_id[ast_node_id] = hir_id; + LoweredNodeId { + node_id: ast_node_id, + hir_id, + } + } else { + LoweredNodeId { + node_id: ast_node_id, + hir_id: existing_hir_id, + } } - - ast_node_id } fn with_hir_id_owner(&mut self, owner: NodeId, f: F) @@ -323,7 +341,7 @@ impl<'a> LoweringContext<'a> { /// actually used in the HIR, as that would trigger an assertion in the /// HirIdValidator later on, which makes sure that all NodeIds got mapped /// properly. Calling the method twice with the same NodeId is fine though. - fn lower_node_id(&mut self, ast_node_id: NodeId) -> NodeId { + fn lower_node_id(&mut self, ast_node_id: NodeId) -> LoweredNodeId { self.lower_node_id_generic(ast_node_id, |this| { let &mut (def_index, ref mut local_id_counter) = this.current_hir_id_owner .last_mut() @@ -340,7 +358,7 @@ impl<'a> LoweringContext<'a> { fn lower_node_id_with_owner(&mut self, ast_node_id: NodeId, owner: NodeId) - -> NodeId { + -> LoweredNodeId { self.lower_node_id_generic(ast_node_id, |this| { let local_id_counter = this.item_local_id_counters .get_mut(&owner) @@ -375,7 +393,7 @@ impl<'a> LoweringContext<'a> { id } - fn next_id(&mut self) -> NodeId { + fn next_id(&mut self) -> LoweredNodeId { self.lower_node_id(self.sess.next_node_id()) } @@ -517,7 +535,7 @@ impl<'a> LoweringContext<'a> { match destination { Some((id, label_ident)) => { let target = if let Def::Label(loop_id) = self.expect_full_def(id) { - hir::LoopIdResult::Ok(self.lower_node_id(loop_id)) + hir::LoopIdResult::Ok(self.lower_node_id(loop_id).node_id) } else { hir::LoopIdResult::Err(hir::LoopIdError::UnresolvedLabel) }; @@ -534,7 +552,7 @@ impl<'a> LoweringContext<'a> { hir::Destination { ident: None, target_id: hir::ScopeTarget::Loop( - loop_id.map(|id| Ok(self.lower_node_id(id))) + loop_id.map(|id| Ok(self.lower_node_id(id).node_id)) .unwrap_or(Err(hir::LoopIdError::OutsideLoopScope)) .into()) } @@ -557,7 +575,7 @@ impl<'a> LoweringContext<'a> { fn lower_ty_binding(&mut self, b: &TypeBinding) -> hir::TypeBinding { hir::TypeBinding { - id: self.lower_node_id(b.id), + id: self.lower_node_id(b.id).node_id, name: self.lower_ident(b.ident), ty: self.lower_ty(&b.ty), span: b.span, @@ -594,7 +612,7 @@ impl<'a> LoweringContext<'a> { return self.lower_ty(ty); } TyKind::Path(ref qself, ref path) => { - let id = self.lower_node_id(t.id); + let id = self.lower_node_id(t.id).node_id; let qpath = self.lower_qpath(t.id, qself, path, ParamMode::Explicit); return self.ty_path(id, t.span, qpath); } @@ -645,7 +663,7 @@ impl<'a> LoweringContext<'a> { }; P(hir::Ty { - id: self.lower_node_id(t.id), + id: self.lower_node_id(t.id).node_id, node: kind, span: t.span, }) @@ -758,7 +776,7 @@ impl<'a> LoweringContext<'a> { // Otherwise, the base path is an implicit `Self` type path, // e.g. `Vec` in `Vec::new` or `::Item` in // `::Item::default`. - let new_id = self.next_id(); + let new_id = self.next_id().node_id; self.ty_path(new_id, p.span, hir::QPath::Resolved(qself, path)) }; @@ -782,7 +800,7 @@ impl<'a> LoweringContext<'a> { } // Wrap the associated extension in another type node. - let new_id = self.next_id(); + let new_id = self.next_id().node_id; ty = self.ty_path(new_id, p.span, qpath); } @@ -887,7 +905,7 @@ impl<'a> LoweringContext<'a> { fn lower_local(&mut self, l: &Local) -> P { P(hir::Local { - id: self.lower_node_id(l.id), + id: self.lower_node_id(l.id).node_id, ty: l.ty.as_ref().map(|t| self.lower_ty(t)), pat: self.lower_pat(&l.pat), init: l.init.as_ref().map(|e| P(self.lower_expr(e))), @@ -905,8 +923,10 @@ impl<'a> LoweringContext<'a> { } fn lower_arg(&mut self, arg: &Arg) -> hir::Arg { + let LoweredNodeId { node_id, hir_id } = self.lower_node_id(arg.id); hir::Arg { - id: self.lower_node_id(arg.id), + id: node_id, + hir_id, pat: self.lower_pat(&arg.pat), } } @@ -969,7 +989,7 @@ impl<'a> LoweringContext<'a> { } hir::TyParam { - id: self.lower_node_id(tp.id), + id: self.lower_node_id(tp.id).node_id, name, bounds, default: tp.default.as_ref().map(|x| self.lower_ty(x)), @@ -987,7 +1007,7 @@ impl<'a> LoweringContext<'a> { fn lower_lifetime(&mut self, l: &Lifetime) -> hir::Lifetime { hir::Lifetime { - id: self.lower_node_id(l.id), + id: self.lower_node_id(l.id).node_id, name: self.lower_ident(l.ident), span: l.span, } @@ -1059,7 +1079,7 @@ impl<'a> LoweringContext<'a> { fn lower_where_clause(&mut self, wc: &WhereClause) -> hir::WhereClause { hir::WhereClause { - id: self.lower_node_id(wc.id), + id: self.lower_node_id(wc.id).node_id, predicates: wc.predicates .iter() .map(|predicate| self.lower_where_predicate(predicate)) @@ -1098,7 +1118,7 @@ impl<'a> LoweringContext<'a> { ref rhs_ty, span}) => { hir::WherePredicate::EqPredicate(hir::WhereEqPredicate { - id: self.lower_node_id(id), + id: self.lower_node_id(id).node_id, lhs_ty: self.lower_ty(lhs_ty), rhs_ty: self.lower_ty(rhs_ty), span, @@ -1114,16 +1134,16 @@ impl<'a> LoweringContext<'a> { .enumerate() .map(|f| self.lower_struct_field(f)) .collect(), - self.lower_node_id(id)) + self.lower_node_id(id).node_id) } VariantData::Tuple(ref fields, id) => { hir::VariantData::Tuple(fields.iter() .enumerate() .map(|f| self.lower_struct_field(f)) .collect(), - self.lower_node_id(id)) + self.lower_node_id(id).node_id) } - VariantData::Unit(id) => hir::VariantData::Unit(self.lower_node_id(id)), + VariantData::Unit(id) => hir::VariantData::Unit(self.lower_node_id(id).node_id), } } @@ -1134,7 +1154,7 @@ impl<'a> LoweringContext<'a> { }; hir::TraitRef { path, - ref_id: self.lower_node_id(p.ref_id), + ref_id: self.lower_node_id(p.ref_id).node_id, } } @@ -1149,7 +1169,7 @@ impl<'a> LoweringContext<'a> { fn lower_struct_field(&mut self, (index, f): (usize, &StructField)) -> hir::StructField { hir::StructField { span: f.span, - id: self.lower_node_id(f.id), + id: self.lower_node_id(f.id).node_id, name: self.lower_ident(match f.ident { Some(ident) => ident, // FIXME(jseyfried) positional field hygiene @@ -1198,8 +1218,11 @@ impl<'a> LoweringContext<'a> { } } + let LoweredNodeId { node_id, hir_id } = self.lower_node_id(b.id); + P(hir::Block { - id: self.lower_node_id(b.id), + id: node_id, + hir_id, stmts: stmts.into(), expr, rules: self.lower_block_check_mode(&b.rules), @@ -1249,7 +1272,7 @@ impl<'a> LoweringContext<'a> { hir::Visibility::Restricted { path: path.clone(), // We are allocating a new NodeId here - id: this.next_id(), + id: this.next_id().node_id, } } }; @@ -1387,7 +1410,7 @@ impl<'a> LoweringContext<'a> { fn lower_trait_item(&mut self, i: &TraitItem) -> hir::TraitItem { self.with_parent_def(i.id, |this| { hir::TraitItem { - id: this.lower_node_id(i.id), + id: this.lower_node_id(i.id).node_id, name: this.lower_ident(i.ident), attrs: this.lower_attrs(&i.attrs), node: match i.node { @@ -1448,7 +1471,7 @@ impl<'a> LoweringContext<'a> { fn lower_impl_item(&mut self, i: &ImplItem) -> hir::ImplItem { self.with_parent_def(i.id, |this| { hir::ImplItem { - id: this.lower_node_id(i.id), + id: this.lower_node_id(i.id).node_id, name: this.lower_ident(i.ident), attrs: this.lower_attrs(&i.attrs), vis: this.lower_visibility(&i.vis, None), @@ -1540,7 +1563,7 @@ impl<'a> LoweringContext<'a> { }); Some(hir::Item { - id: self.lower_node_id(i.id), + id: self.lower_node_id(i.id).node_id, name, attrs, node, @@ -1552,7 +1575,7 @@ impl<'a> LoweringContext<'a> { fn lower_foreign_item(&mut self, i: &ForeignItem) -> hir::ForeignItem { self.with_parent_def(i.id, |this| { hir::ForeignItem { - id: this.lower_node_id(i.id), + id: this.lower_node_id(i.id).node_id, name: i.ident.name, attrs: this.lower_attrs(&i.attrs), node: match i.node { @@ -1630,8 +1653,11 @@ impl<'a> LoweringContext<'a> { } fn lower_pat(&mut self, p: &Pat) -> P { + let LoweredNodeId { node_id, hir_id } = self.lower_node_id(p.id); + P(hir::Pat { - id: self.lower_node_id(p.id), + id: node_id, + hir_id, node: match p.node { PatKind::Wild => hir::PatKind::Wild, PatKind::Ident(ref binding_mode, pth1, ref sub) => { @@ -1813,7 +1839,7 @@ impl<'a> LoweringContext<'a> { let call_move_val_init = hir::StmtSemi( make_call(self, &move_val_init, hir_vec![ptr, pop_unsafe_expr]), - self.next_id()); + self.next_id().node_id); let call_move_val_init = respan(e.span, call_move_val_init); let place = self.expr_ident(e.span, place_ident, place_binding); @@ -1883,11 +1909,15 @@ impl<'a> LoweringContext<'a> { // wrap the if-let expr in a block let span = els.span; let els = P(self.lower_expr(els)); - let id = self.next_id(); + let LoweredNodeId { + node_id, + hir_id, + } = self.next_id(); let blk = P(hir::Block { stmts: hir_vec![], expr: Some(els), - id, + id: node_id, + hir_id, rules: hir::DefaultBlock, span, targeted_by_break: false, @@ -1986,8 +2016,11 @@ impl<'a> LoweringContext<'a> { let struct_path = self.std_path(unstable_span, &struct_path, is_unit); let struct_path = hir::QPath::Resolved(None, P(struct_path)); + let LoweredNodeId { node_id, hir_id } = self.lower_node_id(e.id); + return hir::Expr { - id: self.lower_node_id(e.id), + id: node_id, + hir_id, node: if is_unit { hir::ExprPath(struct_path) } else { @@ -2234,7 +2267,7 @@ impl<'a> LoweringContext<'a> { hir::MatchSource::ForLoopDesugar), ThinVec::new())) }; - let match_stmt = respan(e.span, hir::StmtExpr(match_expr, self.next_id())); + let match_stmt = respan(e.span, hir::StmtExpr(match_expr, self.next_id().node_id)); let next_expr = P(self.expr_ident(e.span, next_ident, next_pat.id)); @@ -2254,7 +2287,7 @@ impl<'a> LoweringContext<'a> { let body_block = self.with_loop_scope(e.id, |this| this.lower_block(body, false)); let body_expr = P(self.expr_block(body_block, ThinVec::new())); - let body_stmt = respan(e.span, hir::StmtExpr(body_expr, self.next_id())); + let body_stmt = respan(e.span, hir::StmtExpr(body_expr, self.next_id().node_id)); let loop_block = P(self.block_all(e.span, hir_vec![next_let, @@ -2266,8 +2299,10 @@ impl<'a> LoweringContext<'a> { // `[opt_ident]: loop { ... }` let loop_expr = hir::ExprLoop(loop_block, self.lower_opt_sp_ident(opt_ident), hir::LoopSource::ForLoop); + let LoweredNodeId { node_id, hir_id } = self.lower_node_id(e.id); let loop_expr = P(hir::Expr { - id: self.lower_node_id(e.id), + id: node_id, + hir_id, node: loop_expr, span: e.span, attrs: ThinVec::new(), @@ -2406,8 +2441,11 @@ impl<'a> LoweringContext<'a> { ExprKind::Mac(_) => panic!("Shouldn't exist here"), }; + let LoweredNodeId { node_id, hir_id } = self.lower_node_id(e.id); + hir::Expr { - id: self.lower_node_id(e.id), + id: node_id, + hir_id, node: kind, span: e.span, attrs: e.attrs.clone(), @@ -2420,7 +2458,7 @@ impl<'a> LoweringContext<'a> { node: hir::StmtDecl(P(Spanned { node: hir::DeclLocal(self.lower_local(l)), span: s.span, - }), self.lower_node_id(s.id)), + }), self.lower_node_id(s.id).node_id), span: s.span, }, StmtKind::Item(ref it) => { @@ -2431,22 +2469,22 @@ impl<'a> LoweringContext<'a> { node: hir::DeclItem(item_id), span: s.span, }), id.take() - .map(|id| self.lower_node_id(id)) - .unwrap_or_else(|| self.next_id())), + .map(|id| self.lower_node_id(id).node_id) + .unwrap_or_else(|| self.next_id().node_id)), span: s.span, }).collect(); } StmtKind::Expr(ref e) => { Spanned { node: hir::StmtExpr(P(self.lower_expr(e)), - self.lower_node_id(s.id)), + self.lower_node_id(s.id).node_id), span: s.span, } } StmtKind::Semi(ref e) => { Spanned { node: hir::StmtSemi(P(self.lower_expr(e)), - self.lower_node_id(s.id)), + self.lower_node_id(s.id).node_id), span: s.span, } } @@ -2477,9 +2515,9 @@ impl<'a> LoweringContext<'a> { hir::Visibility::Restricted { path: P(self.lower_path(id, path, ParamMode::Explicit, true)), id: if let Some(owner) = explicit_owner { - self.lower_node_id_with_owner(id, owner) + self.lower_node_id_with_owner(id, owner).node_id } else { - self.lower_node_id(id) + self.lower_node_id(id).node_id } } } @@ -2621,8 +2659,10 @@ impl<'a> LoweringContext<'a> { } fn expr(&mut self, span: Span, node: hir::Expr_, attrs: ThinVec) -> hir::Expr { + let LoweredNodeId { node_id, hir_id } = self.next_id(); hir::Expr { - id: self.next_id(), + id: node_id, + hir_id, node, span, attrs, @@ -2639,13 +2679,13 @@ impl<'a> LoweringContext<'a> { pat, ty: None, init: ex, - id: self.next_id(), + id: self.next_id().node_id, span: sp, attrs: ThinVec::new(), source, }); let decl = respan(sp, hir::DeclLocal(local)); - respan(sp, hir::StmtDecl(P(decl), self.next_id())) + respan(sp, hir::StmtDecl(P(decl), self.next_id().node_id)) } fn stmt_let(&mut self, sp: Span, mutbl: bool, ident: Name, ex: P) @@ -2665,10 +2705,13 @@ impl<'a> LoweringContext<'a> { fn block_all(&mut self, span: Span, stmts: hir::HirVec, expr: Option>) -> hir::Block { + let LoweredNodeId { node_id, hir_id } = self.next_id(); + hir::Block { stmts, expr, - id: self.next_id(), + id: node_id, + hir_id, rules: hir::DefaultBlock, span, targeted_by_break: false, @@ -2712,18 +2755,22 @@ impl<'a> LoweringContext<'a> { fn pat_ident_binding_mode(&mut self, span: Span, name: Name, bm: hir::BindingAnnotation) -> P { - let id = self.next_id(); + let LoweredNodeId { node_id, hir_id } = self.next_id(); let parent_def = self.parent_def.unwrap(); let def_id = { let defs = self.resolver.definitions(); let def_path_data = DefPathData::Binding(name); - let def_index = defs - .create_def_with_parent(parent_def, id, def_path_data, REGULAR_SPACE, Mark::root()); + let def_index = defs.create_def_with_parent(parent_def, + node_id, + def_path_data, + REGULAR_SPACE, + Mark::root()); DefId::local(def_index) }; P(hir::Pat { - id, + id: node_id, + hir_id, node: hir::PatKind::Binding(bm, def_id, Spanned { @@ -2740,8 +2787,10 @@ impl<'a> LoweringContext<'a> { } fn pat(&mut self, span: Span, pat: hir::PatKind) -> P { + let LoweredNodeId { node_id, hir_id } = self.next_id(); P(hir::Pat { - id: self.next_id(), + id: node_id, + hir_id, node: pat, span, }) @@ -2770,11 +2819,13 @@ impl<'a> LoweringContext<'a> { rule: hir::BlockCheckMode, attrs: ThinVec) -> hir::Expr { - let id = self.next_id(); + let LoweredNodeId { node_id, hir_id } = self.next_id(); + let block = P(hir::Block { rules: rule, span, - id, + id: node_id, + hir_id, stmts, expr: Some(expr), targeted_by_break: false, @@ -2799,7 +2850,7 @@ impl<'a> LoweringContext<'a> { // The original ID is taken by the `PolyTraitRef`, // so the `Ty` itself needs a different one. - id = self.next_id(); + id = self.next_id().node_id; hir::TyTraitObject(hir_vec![principal], self.elided_lifetime(span)) } else { @@ -2813,7 +2864,7 @@ impl<'a> LoweringContext<'a> { fn elided_lifetime(&mut self, span: Span) -> hir::Lifetime { hir::Lifetime { - id: self.next_id(), + id: self.next_id().node_id, span, name: keywords::Invalid.name() } diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index cdd5a6e3da7f1..d3e3998360b60 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -465,6 +465,10 @@ 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.binary_search(&hir_id).unwrap() + } + /// Add a definition with a parent definition. pub fn create_root_def(&mut self, crate_name: &str, diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 45b1d6c184101..3b73647f0eb0e 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -357,6 +357,7 @@ impl<'hir> Map<'hir> { } } + #[inline] pub fn definitions(&self) -> &Definitions { &self.definitions } @@ -377,6 +378,7 @@ impl<'hir> Map<'hir> { self.definitions.def_path(def_id.index) } + #[inline] pub fn local_def_id(&self, node: NodeId) -> DefId { self.opt_local_def_id(node).unwrap_or_else(|| { bug!("local_def_id: no entry for `{}`, which has a map of `{:?}`", @@ -384,14 +386,21 @@ impl<'hir> Map<'hir> { }) } + #[inline] pub fn opt_local_def_id(&self, node: NodeId) -> Option { self.definitions.opt_local_def_id(node) } + #[inline] pub fn as_local_node_id(&self, def_id: DefId) -> Option { self.definitions.as_local_node_id(def_id) } + #[inline] + pub fn node_to_hir_id(&self, node_id: NodeId) -> HirId { + self.definitions.node_to_hir_id(node_id) + } + fn entry_count(&self) -> usize { self.map.len() } diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index efe0504aa18c4..a2be74b552234 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -129,9 +129,11 @@ pub const CRATE_HIR_ID: HirId = HirId { pub const DUMMY_HIR_ID: HirId = HirId { owner: CRATE_DEF_INDEX, - local_id: ItemLocalId(!0) + local_id: DUMMY_ITEM_LOCAL_ID, }; +pub const DUMMY_ITEM_LOCAL_ID: ItemLocalId = ItemLocalId(!0); + #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)] pub struct Lifetime { pub id: NodeId, @@ -547,6 +549,7 @@ pub struct Block { /// without a semicolon, if any pub expr: Option>, pub id: NodeId, + pub hir_id: HirId, /// Distinguishes between `unsafe { ... }` and `{ ... }` pub rules: BlockCheckMode, pub span: Span, @@ -560,6 +563,7 @@ pub struct Block { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)] pub struct Pat { pub id: NodeId, + pub hir_id: HirId, pub node: PatKind, pub span: Span, } @@ -986,6 +990,7 @@ pub struct Expr { pub span: Span, pub node: Expr_, pub attrs: ThinVec, + pub hir_id: HirId, } impl fmt::Debug for Expr { @@ -1423,6 +1428,7 @@ pub struct InlineAsm { pub struct Arg { pub pat: P, pub id: NodeId, + pub hir_id: HirId, } /// Represents the header (not the body) of a function declaration diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index b344084f580bf..fca70de704f39 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -359,6 +359,7 @@ impl<'a, 'gcx, 'tcx> HashStable> for hir::B ref stmts, ref expr, id, + hir_id: _, rules, span, targeted_by_break, @@ -423,6 +424,7 @@ impl<'a, 'gcx, 'tcx> HashStable> for hir::P let hir::Pat { id, + hir_id: _, ref node, ref span } = *self; @@ -551,6 +553,7 @@ impl<'a, 'gcx, 'tcx> HashStable> for hir::E hcx.while_hashing_hir_bodies(true, |hcx| { let hir::Expr { id, + hir_id: _, ref span, ref node, ref attrs @@ -1021,7 +1024,8 @@ impl_stable_hash_for!(enum hir::Stmt_ { impl_stable_hash_for!(struct hir::Arg { pat, - id + id, + hir_id }); impl_stable_hash_for!(struct hir::Body { diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 8a37d7bab4445..37ef7e8cbfa3b 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -618,6 +618,7 @@ for ty::TypeckTables<'gcx> { hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let ty::TypeckTables { + local_id_root: _, ref type_dependent_defs, ref node_types, ref node_substs, @@ -637,7 +638,9 @@ for ty::TypeckTables<'gcx> { } = *self; hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { - ich::hash_stable_nodemap(hcx, hasher, type_dependent_defs); + ich::hash_stable_hashmap(hcx, hasher, type_dependent_defs, |_, item_local_id| { + *item_local_id + }); ich::hash_stable_nodemap(hcx, hasher, node_types); ich::hash_stable_nodemap(hcx, hasher, node_substs); ich::hash_stable_nodemap(hcx, hasher, adjustments); diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index bf79becfe4a10..6aa84a9750330 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -358,8 +358,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> { impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> { /// Used only by `rustc_typeck` during body type-checking/inference, /// will initialize `in_progress_tables` with fresh `TypeckTables`. - pub fn with_fresh_in_progress_tables(mut self) -> Self { - self.fresh_tables = Some(RefCell::new(ty::TypeckTables::empty())); + pub fn with_fresh_in_progress_tables(mut self, table_owner: DefId) -> Self { + self.fresh_tables = Some(RefCell::new(ty::TypeckTables::empty(table_owner))); self } diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 6ee06dc0a8163..cd06806ca6017 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -43,7 +43,7 @@ use syntax::ast; use syntax_pos::{MultiSpan, Span}; use errors::DiagnosticBuilder; use hir; -use hir::def_id::LOCAL_CRATE; +use hir::def_id::{DefId, LOCAL_CRATE}; use hir::intravisit as hir_visit; use syntax::visit as ast_visit; @@ -986,7 +986,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { let mut cx = LateContext { tcx, - tables: &ty::TypeckTables::empty(), + tables: &ty::TypeckTables::empty(DefId::invalid()), param_env: ty::ParamEnv::empty(Reveal::UserFacing), access_levels, lint_sess: LintSession::new(&tcx.sess.lint_store), diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 4e08bc90c7c3a..4cf27981e1b68 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -94,7 +94,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { } } - fn lookup_and_handle_method(&mut self, id: ast::NodeId) { + fn lookup_and_handle_method(&mut self, id: hir::ItemLocalId) { self.check_def_id(self.tables.type_dependent_defs[&id].def_id()); } @@ -119,6 +119,8 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { fn handle_field_pattern_match(&mut self, lhs: &hir::Pat, def: Def, pats: &[codemap::Spanned]) { + + let variant = match self.tables.node_id_to_type(lhs.id).sty { ty::TyAdt(adt, _) => adt.variant_of_def(def), _ => span_bug!(lhs.span, "non-ADT in struct pattern") @@ -235,11 +237,11 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> { fn visit_expr(&mut self, expr: &'tcx hir::Expr) { match expr.node { hir::ExprPath(ref qpath @ hir::QPath::TypeRelative(..)) => { - let def = self.tables.qpath_def(qpath, expr.id); + let def = self.tables.qpath_def(qpath, expr.hir_id); self.handle_definition(def); } hir::ExprMethodCall(..) => { - self.lookup_and_handle_method(expr.id); + self.lookup_and_handle_method(expr.hir_id.local_id); } hir::ExprField(ref lhs, ref name) => { self.handle_field_access(&lhs, name.node); @@ -282,7 +284,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> { self.handle_field_pattern_match(pat, path.def, fields); } PatKind::Path(ref qpath @ hir::QPath::TypeRelative(..)) => { - let def = self.tables.qpath_def(qpath, pat.id); + let def = self.tables.qpath_def(qpath, pat.hir_id); self.handle_definition(def); } _ => () @@ -425,7 +427,7 @@ fn find_live<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let mut symbol_visitor = MarkSymbolVisitor { worklist, tcx, - tables: &ty::TypeckTables::empty(), + tables: &ty::TypeckTables::empty(DefId::invalid()), live_symbols: box FxHashSet(), struct_has_extern_repr: false, ignore_non_const_paths: false, diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs index fcf366788b223..e8ecf9c21cd35 100644 --- a/src/librustc/middle/effect.rs +++ b/src/librustc/middle/effect.rs @@ -19,6 +19,7 @@ use syntax::ast; use syntax_pos::Span; use hir::{self, PatKind}; use hir::def::Def; +use hir::def_id::DefId; use hir::intravisit::{self, FnKind, Visitor, NestedVisitorMap}; #[derive(Copy, Clone)] @@ -165,7 +166,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EffectCheckVisitor<'a, 'tcx> { fn visit_expr(&mut self, expr: &'tcx hir::Expr) { match expr.node { hir::ExprMethodCall(..) => { - let def_id = self.tables.type_dependent_defs[&expr.id].def_id(); + let def_id = self.tables.type_dependent_defs[&expr.hir_id.local_id].def_id(); let sig = self.tcx.fn_sig(def_id); debug!("effect: method call case, signature is {:?}", sig); @@ -262,7 +263,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EffectCheckVisitor<'a, 'tcx> { pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { let mut visitor = EffectCheckVisitor { tcx, - tables: &ty::TypeckTables::empty(), + tables: &ty::TypeckTables::empty(DefId::invalid()), body_id: hir::BodyId { node_id: ast::CRATE_NODE_ID }, unsafe_context: UnsafeContext::new(SafeContext), }; diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 87e933e85e228..80abe87470c2f 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -537,7 +537,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { } ty::TyError => { } _ => { - let def_id = self.mc.tables.type_dependent_defs[&call.id].def_id(); + let def_id = self.mc.tables.type_dependent_defs[&call.hir_id.local_id].def_id(); match OverloadedCallType::from_method_id(self.tcx(), def_id) { FnMutOverloadedCall => { let call_scope_r = self.tcx().node_scope_region(call.id); @@ -863,7 +863,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { PatKind::Struct(ref qpath, ..) => qpath, _ => return }; - let def = mc.tables.qpath_def(qpath, pat.id); + let def = mc.tables.qpath_def(qpath, pat.hir_id); match def { Def::Variant(variant_did) | Def::VariantCtor(variant_did, ..) => { diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs index d29622b4a8159..83278bd88e92d 100644 --- a/src/librustc/middle/intrinsicck.rs +++ b/src/librustc/middle/intrinsicck.rs @@ -146,7 +146,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ExprVisitor<'a, 'tcx> { fn visit_expr(&mut self, expr: &'tcx hir::Expr) { let def = if let hir::ExprPath(ref qpath) = expr.node { - self.tables.qpath_def(qpath, expr.id) + self.tables.qpath_def(qpath, expr.hir_id) } else { Def::Err }; diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index b4993aafc4c9e..c6773250bde98 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -604,7 +604,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { } hir::ExprPath(ref qpath) => { - let def = self.tables.qpath_def(qpath, expr.id); + let def = self.tables.qpath_def(qpath, expr.hir_id); self.cat_def(expr.id, expr.span, expr_ty, def) } @@ -1124,7 +1124,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { match pat.node { PatKind::TupleStruct(ref qpath, ref subpats, ddpos) => { - let def = self.tables.qpath_def(qpath, pat.id); + let def = self.tables.qpath_def(qpath, pat.hir_id); let (cmt, expected_len) = match def { Def::Err => { debug!("access to unresolvable pattern {:?}", pat); @@ -1161,7 +1161,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { PatKind::Struct(ref qpath, ref field_pats, _) => { // {f1: p1, ..., fN: pN} - let def = self.tables.qpath_def(qpath, pat.id); + let def = self.tables.qpath_def(qpath, pat.hir_id); let cmt = match def { Def::Err => { debug!("access to unresolvable pattern {:?}", pat); diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index df828c8d8e71a..98f82a51267fe 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -107,10 +107,10 @@ impl<'a, 'tcx> Visitor<'tcx> for ReachableContext<'a, 'tcx> { fn visit_expr(&mut self, expr: &'tcx hir::Expr) { let def = match expr.node { hir::ExprPath(ref qpath) => { - Some(self.tables.qpath_def(qpath, expr.id)) + Some(self.tables.qpath_def(qpath, expr.hir_id)) } hir::ExprMethodCall(..) => { - Some(self.tables.type_dependent_defs[&expr.id]) + Some(self.tables.type_dependent_defs[&expr.hir_id.local_id]) } _ => None }; @@ -375,7 +375,7 @@ fn reachable_set<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum) -> }); let mut reachable_context = ReachableContext { tcx, - tables: &ty::TypeckTables::empty(), + tables: &ty::TypeckTables::empty(DefId::invalid()), reachable_symbols: NodeSet(), worklist: Vec::new(), any_library, diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 6b9cbabf20e97..46bb13c89ba78 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -14,7 +14,7 @@ use dep_graph::DepGraph; use errors::DiagnosticBuilder; use session::Session; use middle; -use hir::TraitMap; +use hir::{TraitMap}; use hir::def::{Def, ExportMap}; use hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use hir::map as hir_map; @@ -42,7 +42,7 @@ use ty::inhabitedness::DefIdForest; use ty::maps; use ty::steal::Steal; use ty::BindingMode; -use util::nodemap::{NodeMap, NodeSet, DefIdSet}; +use util::nodemap::{NodeMap, NodeSet, DefIdSet, ItemLocalMap}; use util::nodemap::{FxHashMap, FxHashSet}; use rustc_data_structures::accumulate_vec::AccumulateVec; @@ -209,9 +209,12 @@ pub struct CommonTypes<'tcx> { #[derive(RustcEncodable, RustcDecodable)] pub struct TypeckTables<'tcx> { + /// The HirId::owner all ItemLocalIds in this table are relative to. + pub local_id_root: DefId, + /// Resolved definitions for `::X` associated paths and /// method calls, including those of overloaded operators. - pub type_dependent_defs: NodeMap, + pub type_dependent_defs: ItemLocalMap, /// Stores the types for various nodes in the AST. Note that this table /// is not guaranteed to be populated until after typeck. See @@ -271,9 +274,10 @@ pub struct TypeckTables<'tcx> { } impl<'tcx> TypeckTables<'tcx> { - pub fn empty() -> TypeckTables<'tcx> { + pub fn empty(local_id_root: DefId) -> TypeckTables<'tcx> { TypeckTables { - type_dependent_defs: NodeMap(), + local_id_root, + type_dependent_defs: ItemLocalMap(), node_types: FxHashMap(), node_substs: NodeMap(), adjustments: NodeMap(), @@ -291,11 +295,12 @@ impl<'tcx> TypeckTables<'tcx> { } /// Returns the final resolution of a `QPath` in an `Expr` or `Pat` node. - pub fn qpath_def(&self, qpath: &hir::QPath, id: NodeId) -> Def { + pub fn qpath_def(&self, qpath: &hir::QPath, id: hir::HirId) -> Def { match *qpath { hir::QPath::Resolved(_, ref path) => path.def, hir::QPath::TypeRelative(..) => { - self.type_dependent_defs.get(&id).cloned().unwrap_or(Def::Err) + self.validate_hir_id(id); + self.type_dependent_defs.get(&id.local_id).cloned().unwrap_or(Def::Err) } } } @@ -373,7 +378,8 @@ impl<'tcx> TypeckTables<'tcx> { return false; } - match self.type_dependent_defs.get(&expr.id) { + self.validate_hir_id(expr.hir_id); + match self.type_dependent_defs.get(&expr.hir_id.local_id) { Some(&Def::Method(_)) => true, _ => false } @@ -382,6 +388,30 @@ impl<'tcx> TypeckTables<'tcx> { pub fn upvar_capture(&self, upvar_id: ty::UpvarId) -> ty::UpvarCapture<'tcx> { self.upvar_capture_map[&upvar_id] } + + /// Validate that a NodeId can safely be converted to an ItemLocalId for + /// this table. + #[inline] + pub fn validate_hir_id(&self, hir_id: hir::HirId) { + #[cfg(debug_assertions)] + { + if self.local_id_root.is_local() { + if hir_id.owner != self.local_id_root.index { + ty::tls::with(|tcx| { + let node_id = tcx.hir + .definitions() + .find_node_for_hir_id(hir_id); + + bug!("node {} with HirId::owner {:?} cannot be placed in \ + TypeckTables with local_id_root {:?}", + tcx.hir.node_to_string(node_id), + DefId::local(hir_id.owner), + self.local_id_root) + }); + } + } + } + } } impl<'tcx> CommonTypes<'tcx> { diff --git a/src/librustc/util/nodemap.rs b/src/librustc/util/nodemap.rs index b03011fcb216d..c397371c5c767 100644 --- a/src/librustc/util/nodemap.rs +++ b/src/librustc/util/nodemap.rs @@ -13,6 +13,7 @@ #![allow(non_snake_case)] use hir::def_id::DefId; +use hir::ItemLocalId; use syntax::ast; pub use rustc_data_structures::fx::FxHashMap; @@ -20,12 +21,14 @@ pub use rustc_data_structures::fx::FxHashSet; pub type NodeMap = FxHashMap; pub type DefIdMap = FxHashMap; +pub type ItemLocalMap = FxHashMap; pub type NodeSet = FxHashSet; pub type DefIdSet = FxHashSet; pub fn NodeMap() -> NodeMap { FxHashMap() } pub fn DefIdMap() -> DefIdMap { FxHashMap() } +pub fn ItemLocalMap() -> ItemLocalMap { FxHashMap() } pub fn NodeSet() -> NodeSet { FxHashSet() } pub fn DefIdSet() -> DefIdSet { FxHashSet() } diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index eb45fd9c0e0a4..cce511daf8ae7 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -276,7 +276,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>, } hir::ExprPath(ref qpath) => { let substs = cx.tables.node_substs(e.id).subst(tcx, cx.substs); - match cx.tables.qpath_def(qpath, e.id) { + match cx.tables.qpath_def(qpath, e.hir_id) { Def::Const(def_id) | Def::AssociatedConst(def_id) => { match tcx.at(e.span).const_eval(cx.param_env.and((def_id, substs))) { diff --git a/src/librustc_const_eval/pattern.rs b/src/librustc_const_eval/pattern.rs index f37a112a596ac..30183ca2daf71 100644 --- a/src/librustc_const_eval/pattern.rs +++ b/src/librustc_const_eval/pattern.rs @@ -321,7 +321,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { } PatKind::Path(ref qpath) => { - return self.lower_path(qpath, pat.id, pat.id, pat.span); + return self.lower_path(qpath, (pat.id, pat.hir_id), pat.id, pat.span); } PatKind::Ref(ref subpattern, _) | @@ -417,7 +417,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { } PatKind::TupleStruct(ref qpath, ref subpatterns, ddpos) => { - let def = self.tables.qpath_def(qpath, pat.id); + let def = self.tables.qpath_def(qpath, pat.hir_id); let adt_def = match ty.sty { ty::TyAdt(adt_def, _) => adt_def, _ => span_bug!(pat.span, "tuple struct pattern not applied to an ADT"), @@ -436,7 +436,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { } PatKind::Struct(ref qpath, ref fields, _) => { - let def = self.tables.qpath_def(qpath, pat.id); + let def = self.tables.qpath_def(qpath, pat.hir_id); let adt_def = match ty.sty { ty::TyAdt(adt_def, _) => adt_def, _ => { @@ -590,12 +590,12 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { fn lower_path(&mut self, qpath: &hir::QPath, - id: ast::NodeId, + (id, hir_id): (ast::NodeId, hir::HirId), pat_id: ast::NodeId, span: Span) -> Pattern<'tcx> { let ty = self.tables.node_id_to_type(id); - let def = self.tables.qpath_def(qpath, id); + let def = self.tables.qpath_def(qpath, hir_id); let kind = match def { Def::Const(def_id) | Def::AssociatedConst(def_id) => { let substs = self.tables.node_substs(id); @@ -696,7 +696,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { _ => bug!() }; let ty = self.tables.node_id_to_type(callee.id); - let def = self.tables.qpath_def(qpath, callee.id); + let def = self.tables.qpath_def(qpath, callee.hir_id); match def { Def::Fn(..) | Def::Method(..) => self.lower_lit(expr), _ => { @@ -712,7 +712,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { } hir::ExprStruct(ref qpath, ref fields, None) => { - let def = self.tables.qpath_def(qpath, expr.id); + let def = self.tables.qpath_def(qpath, expr.hir_id); let adt_def = match pat_ty.sty { ty::TyAdt(adt_def, _) => adt_def, _ => { @@ -755,7 +755,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { } hir::ExprPath(ref qpath) => { - return self.lower_path(qpath, expr.id, pat_id, span); + return self.lower_path(qpath, (expr.id, expr.hir_id), pat_id, span); } _ => self.lower_lit(expr) diff --git a/src/librustc_data_structures/indexed_vec.rs b/src/librustc_data_structures/indexed_vec.rs index 1f44378c9e646..bc9bfa4049723 100644 --- a/src/librustc_data_structures/indexed_vec.rs +++ b/src/librustc_data_structures/indexed_vec.rs @@ -196,6 +196,16 @@ impl IndexVec { } } +impl IndexVec { + #[inline] + pub fn binary_search(&self, value: &T) -> Result { + match self.raw.binary_search(value) { + Ok(i) => Ok(Idx::new(i)), + Err(i) => Err(Idx::new(i)), + } + } +} + impl Index for IndexVec { type Output = T; diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index 269363fdd2f98..51f5cc4f249f2 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -45,6 +45,7 @@ use std::option; use std::path::Path; use std::str::FromStr; +use rustc::hir::def_id::DefId; use rustc::hir::map as hir_map; use rustc::hir::map::blocks; use rustc::hir; @@ -232,7 +233,7 @@ impl PpSourceMode { arenas, id, |tcx, _, _, _| { - let empty_tables = ty::TypeckTables::empty(); + let empty_tables = ty::TypeckTables::empty(DefId::invalid()); let annotation = TypedAnnotation { tcx: tcx, tables: Cell::new(&empty_tables) diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 88432e6429031..85ec606e87efd 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -896,7 +896,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion { match cx.tcx.hir.get(id) { hir_map::NodeExpr(&hir::Expr { node: hir::ExprCall(ref callee, _), .. }) => { let def = if let hir::ExprPath(ref qpath) = callee.node { - cx.tables.qpath_def(qpath, callee.id) + cx.tables.qpath_def(qpath, callee.hir_id) } else { return false; }; @@ -934,7 +934,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion { // Check for method calls and overloaded operators. if cx.tables.is_method_call(expr) { - let def_id = cx.tables.type_dependent_defs[&id].def_id(); + let local_id = cx.tcx.hir.definitions().node_to_hir_id(id).local_id; + let def_id = cx.tables.type_dependent_defs[&local_id].def_id(); let substs = cx.tables.node_substs(id); if method_call_refers_to_method(cx, method, def_id, substs, id) { return true; @@ -945,7 +946,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion { match expr.node { hir::ExprCall(ref callee, _) => { let def = if let hir::ExprPath(ref qpath) = callee.node { - cx.tables.qpath_def(qpath, callee.id) + cx.tables.qpath_def(qpath, callee.hir_id) } else { return false; }; @@ -1179,7 +1180,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableTransmutes { expr: &hir::Expr) -> Option<(&'tcx ty::TypeVariants<'tcx>, &'tcx ty::TypeVariants<'tcx>)> { let def = if let hir::ExprPath(ref qpath) = expr.node { - cx.tables.qpath_def(qpath, expr.id) + cx.tables.qpath_def(qpath, expr.hir_id) } else { return None; }; diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 06a0c4ff213da..3effc29d67e2d 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -450,7 +450,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } hir::ExprPath(ref qpath) => { - let def = cx.tables().qpath_def(qpath, expr.id); + let def = cx.tables().qpath_def(qpath, expr.hir_id); convert_path_expr(cx, expr, def) } @@ -580,7 +580,8 @@ fn method_callee<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, -> Expr<'tcx> { let temp_lifetime = cx.region_maps.temporary_scope(expr.id); let (def_id, substs) = custom_callee.unwrap_or_else(|| { - (cx.tables().type_dependent_defs[&expr.id].def_id(), + cx.tables().validate_hir_id(expr.hir_id); + (cx.tables().type_dependent_defs[&expr.hir_id.local_id].def_id(), cx.tables().node_substs(expr.id)) }); Expr { diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs index 8443cc8267d1c..b3a1509972a04 100644 --- a/src/librustc_passes/consts.rs +++ b/src/librustc_passes/consts.rs @@ -329,7 +329,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node } } hir::ExprPath(ref qpath) => { - let def = v.tables.qpath_def(qpath, e.id); + let def = v.tables.qpath_def(qpath, e.hir_id); match def { Def::VariantCtor(..) | Def::StructCtor(..) | Def::Fn(..) | Def::Method(..) => {} @@ -365,7 +365,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node } // The callee is an arbitrary expression, it doesn't necessarily have a definition. let def = if let hir::ExprPath(ref qpath) = callee.node { - v.tables.qpath_def(qpath, callee.id) + v.tables.qpath_def(qpath, callee.hir_id) } else { Def::Err }; @@ -387,7 +387,8 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node } } hir::ExprMethodCall(..) => { - let def_id = v.tables.type_dependent_defs[&e.id].def_id(); + v.tables.validate_hir_id(e.hir_id); + let def_id = v.tables.type_dependent_defs[&e.hir_id.local_id].def_id(); match v.tcx.associated_item(def_id).container { ty::ImplContainer(_) => v.handle_const_fn_call(def_id, node_ty), ty::TraitContainer(_) => v.promotable = false @@ -471,7 +472,7 @@ fn check_adjustments<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Exp pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { tcx.hir.krate().visit_all_item_likes(&mut CheckCrateVisitor { tcx: tcx, - tables: &ty::TypeckTables::empty(), + tables: &ty::TypeckTables::empty(DefId::invalid()), in_fn: false, promotable: false, mut_rvalue_borrows: NodeSet(), diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 9fa5fea20d915..c1cab0cc8f744 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -473,6 +473,7 @@ struct NamePrivacyVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, tables: &'a ty::TypeckTables<'tcx>, current_item: ast::NodeId, + empty_tables: &'a ty::TypeckTables<'tcx>, } impl<'a, 'tcx> NamePrivacyVisitor<'a, 'tcx> { @@ -489,6 +490,22 @@ impl<'a, 'tcx> NamePrivacyVisitor<'a, 'tcx> { } } +// Set the correct TypeckTables for the given `item_id` (or an empty table if +// there is no TypeckTables for the item). +fn update_tables<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + item_id: ast::NodeId, + tables: &mut &'a ty::TypeckTables<'tcx>, + empty_tables: &'a ty::TypeckTables<'tcx>) + -> &'a ty::TypeckTables<'tcx> { + let def_id = tcx.hir.local_def_id(item_id); + + if tcx.has_typeck_tables(def_id) { + replace(tables, tcx.typeck_tables_of(def_id)) + } else { + replace(tables, empty_tables) + } +} + impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> { /// We want to visit items in the context of their containing /// module and so forth, so supply a crate for doing a deep walk. @@ -505,14 +522,28 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> { fn visit_item(&mut self, item: &'tcx hir::Item) { let orig_current_item = replace(&mut self.current_item, item.id); + let orig_tables = update_tables(self.tcx, item.id, &mut self.tables, self.empty_tables); intravisit::walk_item(self, item); self.current_item = orig_current_item; + self.tables = orig_tables; + } + + fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem) { + let orig_tables = update_tables(self.tcx, ti.id, &mut self.tables, self.empty_tables); + intravisit::walk_trait_item(self, ti); + self.tables = orig_tables; + } + + fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) { + let orig_tables = update_tables(self.tcx, ii.id, &mut self.tables, self.empty_tables); + intravisit::walk_impl_item(self, ii); + self.tables = orig_tables; } fn visit_expr(&mut self, expr: &'tcx hir::Expr) { match expr.node { hir::ExprStruct(ref qpath, ref fields, ref base) => { - let def = self.tables.qpath_def(qpath, expr.id); + let def = self.tables.qpath_def(qpath, expr.hir_id); let adt = self.tables.expr_ty(expr).ty_adt_def().unwrap(); let variant = adt.variant_of_def(def); if let Some(ref base) = *base { @@ -539,7 +570,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> { fn visit_pat(&mut self, pat: &'tcx hir::Pat) { match pat.node { PatKind::Struct(ref qpath, ref fields, _) => { - let def = self.tables.qpath_def(qpath, pat.id); + let def = self.tables.qpath_def(qpath, pat.hir_id); let adt = self.tables.pat_ty(pat).ty_adt_def().unwrap(); let variant = adt.variant_of_def(def); for field in fields { @@ -564,6 +595,7 @@ struct TypePrivacyVisitor<'a, 'tcx: 'a> { tables: &'a ty::TypeckTables<'tcx>, current_item: DefId, span: Span, + empty_tables: &'a ty::TypeckTables<'tcx>, } impl<'a, 'tcx> TypePrivacyVisitor<'a, 'tcx> { @@ -716,7 +748,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { } hir::ExprMethodCall(_, span, _) => { // Method calls have to be checked specially. - let def_id = self.tables.type_dependent_defs[&expr.id].def_id(); + self.tables.validate_hir_id(expr.hir_id); + let def_id = self.tables.type_dependent_defs[&expr.hir_id.local_id].def_id(); self.span = span; if self.tcx.type_of(def_id).visit_with(self) { return; @@ -732,7 +765,9 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { // Inherent associated constants don't have self type in substs, // we have to check it additionally. if let hir::QPath::TypeRelative(..) = *qpath { - if let Some(def) = self.tables.type_dependent_defs.get(&id).cloned() { + let hir_id = self.tcx.hir.node_to_hir_id(id); + self.tables.validate_hir_id(hir_id); + if let Some(def) = self.tables.type_dependent_defs.get(&hir_id.local_id).cloned() { if let Some(assoc_item) = self.tcx.opt_associated_item(def.def_id()) { if let ty::ImplContainer(impl_def_id) = assoc_item.container { if self.tcx.type_of(impl_def_id).visit_with(self) { @@ -770,6 +805,10 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { // Check types in item interfaces fn visit_item(&mut self, item: &'tcx hir::Item) { let orig_current_item = self.current_item; + let orig_tables = update_tables(self.tcx, + item.id, + &mut self.tables, + self.empty_tables); match item.node { hir::ItemExternCrate(..) | hir::ItemMod(..) | @@ -829,8 +868,21 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { self.current_item = self.tcx.hir.local_def_id(item.id); intravisit::walk_item(self, item); + self.tables = orig_tables; self.current_item = orig_current_item; } + + fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem) { + let orig_tables = update_tables(self.tcx, ti.id, &mut self.tables, self.empty_tables); + intravisit::walk_trait_item(self, ti); + self.tables = orig_tables; + } + + fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) { + let orig_tables = update_tables(self.tcx, ii.id, &mut self.tables, self.empty_tables); + intravisit::walk_impl_item(self, ii); + self.tables = orig_tables; + } } impl<'a, 'tcx> TypeVisitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { @@ -1606,11 +1658,15 @@ fn privacy_access_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let krate = tcx.hir.krate(); + let empty_tables = ty::TypeckTables::empty(DefId::invalid()); + + // Check privacy of names not checked in previous compilation stages. let mut visitor = NamePrivacyVisitor { tcx: tcx, - tables: &ty::TypeckTables::empty(), + tables: &empty_tables, current_item: CRATE_NODE_ID, + empty_tables: &empty_tables, }; intravisit::walk_crate(&mut visitor, krate); @@ -1618,9 +1674,10 @@ fn privacy_access_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // inferred types of expressions and patterns. let mut visitor = TypePrivacyVisitor { tcx: tcx, - tables: &ty::TypeckTables::empty(), + tables: &empty_tables, current_item: DefId::local(CRATE_DEF_INDEX), span: krate.span, + empty_tables: &empty_tables, }; intravisit::walk_crate(&mut visitor, krate); diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 1dd0df4108fc6..d46d8624a12ca 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -550,7 +550,8 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } } ast::ExprKind::MethodCall(..) => { - let method_id = self.tables.type_dependent_defs[&expr.id].def_id(); + let local_id = self.tcx.hir.definitions().node_to_hir_id(expr.id).local_id; + let method_id = self.tables.type_dependent_defs[&local_id].def_id(); let (def_id, decl_id) = match self.tcx.associated_item(method_id).container { ty::ImplContainer(_) => (Some(method_id), None), ty::TraitContainer(_) => (None, Some(method_id)), @@ -586,7 +587,8 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { Node::NodePat(&hir::Pat { node: hir::PatKind::Path(ref qpath), .. }) | Node::NodePat(&hir::Pat { node: hir::PatKind::Struct(ref qpath, ..), .. }) | Node::NodePat(&hir::Pat { node: hir::PatKind::TupleStruct(ref qpath, ..), .. }) => { - self.tables.qpath_def(qpath, id) + let hir_id = self.tcx.hir.node_to_hir_id(id); + self.tables.qpath_def(qpath, hir_id) } Node::NodeLocal(&hir::Pat { node: hir::PatKind::Binding(_, def_id, ..), .. }) => { @@ -975,7 +977,7 @@ pub fn process_crate<'l, 'tcx, H: SaveHandler>(tcx: TyCtxt<'l, 'tcx, 'tcx>, let save_ctxt = SaveContext { tcx: tcx, - tables: &ty::TypeckTables::empty(), + tables: &ty::TypeckTables::empty(DefId::invalid()), analysis: analysis, span_utils: SpanUtils::new(&tcx.sess), config: find_config(config), diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index a0801a7486654..cdf1c3b235b67 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -222,7 +222,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let hir::ExprCall(ref expr, _) = call_expr.node { let def = if let hir::ExprPath(ref qpath) = expr.node { - self.tables.borrow().qpath_def(qpath, expr.id) + self.tables.borrow().qpath_def(qpath, expr.hir_id) } else { Def::Err }; @@ -314,7 +314,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { TupleArgumentsFlag::TupleArguments, expected); - self.write_method_call(call_expr.id, method_callee); + self.write_method_call((call_expr.id, call_expr.hir_id), method_callee); output_type } } @@ -364,7 +364,8 @@ impl<'a, 'gcx, 'tcx> DeferredCallResolution<'gcx, 'tcx> { adjustments.extend(autoref); fcx.apply_adjustments(self.callee_expr, adjustments); - fcx.write_method_call(self.call_expr.id, method_callee); + fcx.write_method_call((self.call_expr.id, self.call_expr.hir_id), + method_callee); } None => { span_bug!(self.call_expr.span, diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index b6a5ce0a6ce5a..a6f904b0c96c4 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -513,7 +513,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { None => return self.tcx.sess.delay_span_bug(expr.span, "re-trying op failed") }; debug!("convert_lvalue_op_to_mutable: method={:?}", method); - self.write_method_call(expr.id, method); + self.write_method_call((expr.id, expr.hir_id), method); let (region, mutbl) = if let ty::TyRef(r, mt) = method.sig.inputs()[0].sty { (r, mt.mutbl) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 697d9de931a86..885472a76a92f 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -572,8 +572,16 @@ pub struct InheritedBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> { pub fn build(tcx: TyCtxt<'a, 'gcx, 'gcx>, def_id: DefId) -> InheritedBuilder<'a, 'gcx, 'tcx> { + let hir_id_root = if def_id.is_local() { + let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); + let hir_id = tcx.hir.definitions().node_to_hir_id(node_id); + DefId::local(hir_id.owner) + } else { + def_id + }; + InheritedBuilder { - infcx: tcx.infer_ctxt().with_fresh_in_progress_tables(), + infcx: tcx.infer_ctxt().with_fresh_in_progress_tables(hir_id_root), def_id, } } @@ -840,7 +848,7 @@ fn typeck_tables_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }); let body = tcx.hir.body(body_id); - Inherited::build(tcx, def_id).enter(|inh| { + let tables = Inherited::build(tcx, def_id).enter(|inh| { let param_env = tcx.param_env(def_id); let fcx = if let Some(decl) = fn_decl { let fn_sig = tcx.fn_sig(def_id); @@ -887,7 +895,13 @@ fn typeck_tables_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } fcx.resolve_type_vars_in_body(body) - }) + }); + + // Consistency check our TypeckTables instance can hold all ItemLocalIds + // it will need to hold. + assert_eq!(tables.local_id_root, + DefId::local(tcx.hir.definitions().node_to_hir_id(id).owner)); + tables } fn check_abi<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, span: Span, abi: Abi) { @@ -1804,8 +1818,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } - pub fn write_method_call(&self, node_id: ast::NodeId, method: MethodCallee<'tcx>) { - self.tables.borrow_mut().type_dependent_defs.insert(node_id, Def::Method(method.def_id)); + // The NodeId and the ItemLocalId must identify the same item. We just pass + // both of them for consistency checking. + pub fn write_method_call(&self, + (node_id, hir_id): (ast::NodeId, hir::HirId), + method: MethodCallee<'tcx>) { + { + let mut tables = self.tables.borrow_mut(); + tables.validate_hir_id(hir_id); + tables.type_dependent_defs.insert(hir_id.local_id, Def::Method(method.def_id)); + } self.write_substs(node_id, method.substs); } @@ -2254,7 +2276,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } self.apply_adjustments(base_expr, adjustments); - self.write_method_call(expr.id, method); + self.write_method_call((expr.id, expr.hir_id), method); (input_ty, self.make_overloaded_lvalue_return_type(method).ty) }); if result.is_some() { @@ -2794,7 +2816,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { expr, rcvr) { Ok(method) => { - self.write_method_call(expr.id, method); + self.write_method_call((expr.id, expr.hir_id), method); Ok(method) } Err(error) => { @@ -3499,7 +3521,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }]); } oprnd_t = self.make_overloaded_lvalue_return_type(method).ty; - self.write_method_call(expr.id, method); + self.write_method_call((expr.id, expr.hir_id), method); } else { type_error_struct!(tcx.sess, expr.span, oprnd_t, E0614, "type `{}` cannot be dereferenced", @@ -4000,7 +4022,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ty, def, segment); // Write back the new resolution. - self.tables.borrow_mut().type_dependent_defs.insert(node_id, def); + let hir_id = self.tcx.hir.node_to_hir_id(node_id); + let mut tables = self.tables.borrow_mut(); + tables.validate_hir_id(hir_id); + tables.type_dependent_defs.insert(hir_id.local_id, def); (def, ty) } @@ -4041,7 +4066,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }; // Write back the new resolution. - self.tables.borrow_mut().type_dependent_defs.insert(node_id, def); + let hir_id = self.tcx.hir.node_to_hir_id(node_id); + let mut tables = self.tables.borrow_mut(); + tables.validate_hir_id(hir_id); + tables.type_dependent_defs.insert(hir_id.local_id, def); (def, Some(ty), slice::ref_slice(&**item_segment)) } diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index c1711491ee48c..71457377b1088 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -214,7 +214,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { .or_insert(vec![]).push(autoref); } } - self.write_method_call(expr.id, method); + self.write_method_call((expr.id, expr.hir_id), method); method.sig.output() } @@ -340,7 +340,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { assert!(op.is_by_value()); match self.lookup_op_method(operand_ty, &[], Op::Unary(op, ex.span)) { Ok(method) => { - self.write_method_call(ex.id, method); + self.write_method_call((ex.id, ex.hir_id), method); method.sig.output() } Err(()) => { diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 9e5cf5137c21f..93d0e6e976a70 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -14,6 +14,7 @@ use check::FnCtxt; use rustc::hir; +use rustc::hir::def_id::DefId; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::infer::{InferCtxt}; use rustc::ty::{self, Ty, TyCtxt}; @@ -34,7 +35,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let mut wbcx = WritebackCx::new(self, body); for arg in &body.arguments { - wbcx.visit_node_id(arg.pat.span, arg.id); + wbcx.visit_node_id(arg.pat.span, (arg.id, arg.hir_id)); } wbcx.visit_body(body); wbcx.visit_upvar_borrow_map(); @@ -74,10 +75,13 @@ struct WritebackCx<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> { impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { fn new(fcx: &'cx FnCtxt<'cx, 'gcx, 'tcx>, body: &'gcx hir::Body) - -> WritebackCx<'cx, 'gcx, 'tcx> { + -> WritebackCx<'cx, 'gcx, 'tcx> + { + let owner = fcx.tcx.hir.definitions().node_to_hir_id(body.id().node_id); + WritebackCx { fcx: fcx, - tables: ty::TypeckTables::empty(), + tables: ty::TypeckTables::empty(DefId::local(owner.owner)), body: body } } @@ -105,7 +109,8 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { if inner_ty.is_scalar() { let mut tables = self.fcx.tables.borrow_mut(); - tables.type_dependent_defs.remove(&e.id); + tables.validate_hir_id(e.hir_id); + tables.type_dependent_defs.remove(&e.hir_id.local_id); tables.node_substs.remove(&e.id); } } @@ -119,7 +124,8 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { if lhs_ty.is_scalar() && rhs_ty.is_scalar() { let mut tables = self.fcx.tables.borrow_mut(); - tables.type_dependent_defs.remove(&e.id); + tables.validate_hir_id(e.hir_id); + tables.type_dependent_defs.remove(&e.hir_id.local_id); tables.node_substs.remove(&e.id); match e.node { @@ -157,12 +163,12 @@ impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> { fn visit_expr(&mut self, e: &'gcx hir::Expr) { self.fix_scalar_builtin_expr(e); - self.visit_node_id(e.span, e.id); + self.visit_node_id(e.span, (e.id, e.hir_id)); if let hir::ExprClosure(_, _, body, _) = e.node { let body = self.fcx.tcx.hir.body(body); for arg in &body.arguments { - self.visit_node_id(e.span, arg.id); + self.visit_node_id(e.span, (arg.id, arg.hir_id)); } self.visit_body(body); @@ -172,7 +178,7 @@ impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> { } fn visit_block(&mut self, b: &'gcx hir::Block) { - self.visit_node_id(b.span, b.id); + self.visit_node_id(b.span, (b.id, b.hir_id)); intravisit::walk_block(self, b); } @@ -186,7 +192,7 @@ impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> { _ => {} }; - self.visit_node_id(p.span, p.id); + self.visit_node_id(p.span, (p.id, p.hir_id)); intravisit::walk_pat(self, p); } @@ -277,10 +283,17 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { } } - fn visit_node_id(&mut self, span: Span, node_id: ast::NodeId) { - // Export associated path extensions and method resultions. - if let Some(def) = self.fcx.tables.borrow_mut().type_dependent_defs.remove(&node_id) { - self.tables.type_dependent_defs.insert(node_id, def); + fn visit_node_id(&mut self, + span: Span, + (node_id, hir_id): (ast::NodeId, hir::HirId)) { + { + let mut fcx_tables = self.fcx.tables.borrow_mut(); + fcx_tables.validate_hir_id(hir_id); + // Export associated path extensions and method resultions. + if let Some(def) = fcx_tables.type_dependent_defs.remove(&hir_id.local_id) { + self.tables.validate_hir_id(hir_id); + self.tables.type_dependent_defs.insert(hir_id.local_id, def); + } } // Resolve any borrowings for the node with id `node_id`