diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index 4c922654e02d5..1ea184fa82cdd 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -74,6 +74,7 @@ fn alloc_hir_dep_nodes( dep_graph: &DepGraph, hcx: &mut StableHashingContext<'_>, def_path_hash: DefPathHash, + parent: HirId, item_like: impl for<'a> HashStable>, hir_body_nodes: &mut Vec<(DefPathHash, Fingerprint)>, ) -> (DepNodeIndex, DepNodeIndex) { @@ -81,7 +82,7 @@ fn alloc_hir_dep_nodes( .input_task( def_path_hash.to_dep_node(DepKind::Hir), &mut *hcx, - HirItemLike { item_like: &item_like, hash_bodies: false }, + HirItemLike { item_like: &(parent, &item_like), hash_bodies: false }, ) .1; let (full, hash) = input_dep_node_and_hash( @@ -146,6 +147,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { dep_graph, &mut hcx, root_mod_def_path_hash, + CRATE_HIR_ID, (module, attrs, span), &mut hir_body_nodes, ) @@ -316,6 +318,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { self.dep_graph, &mut self.hcx, def_path_hash, + self.parent_node, item_like, &mut self.hir_body_nodes, ); diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 1645420892a75..75f438760d866 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -181,7 +181,7 @@ impl<'hir> Iterator for ParentHirIterator<'_, 'hir> { } self.current_id = parent_id; - if let Some(entry) = self.map.find_entry(parent_id) { + if let Some(entry) = self.map.find_and_read_entry(parent_id) { return Some((parent_id, entry.node)); } // If this `HirId` doesn't have an `Entry`, skip it and look for its `parent_id`. @@ -381,6 +381,12 @@ impl<'hir> Map<'hir> { self.lookup(id).cloned() } + fn find_and_read_entry(&self, id: HirId) -> Option> { + let entry = self.find_entry(id); + entry.map(|e| self.dep_graph.read_index(e.dep_node)); + entry + } + pub fn item(&self, id: HirId) -> &'hir Item<'hir> { self.read(id); @@ -414,7 +420,7 @@ impl<'hir> Map<'hir> { } pub fn fn_decl_by_hir_id(&self, hir_id: HirId) -> Option<&'hir FnDecl<'hir>> { - if let Some(entry) = self.find_entry(hir_id) { + if let Some(entry) = self.find_and_read_entry(hir_id) { entry.fn_decl() } else { bug!("no entry for hir_id `{}`", hir_id) @@ -422,7 +428,7 @@ impl<'hir> Map<'hir> { } pub fn fn_sig_by_hir_id(&self, hir_id: HirId) -> Option<&'hir FnSig<'hir>> { - if let Some(entry) = self.find_entry(hir_id) { + if let Some(entry) = self.find_and_read_entry(hir_id) { entry.fn_sig() } else { bug!("no entry for hir_id `{}`", hir_id) @@ -612,7 +618,12 @@ impl<'hir> Map<'hir> { if self.dep_graph.is_fully_enabled() { let hir_id_owner = hir_id.owner; let def_path_hash = self.definitions.def_path_hash(hir_id_owner); - self.dep_graph.read(def_path_hash.to_dep_node(DepKind::HirBody)); + let kind = if hir_id.local_id == ItemLocalId::from_u32_const(0) { + DepKind::Hir + } else { + DepKind::HirBody + }; + self.dep_graph.read(def_path_hash.to_dep_node(kind)); } self.find_entry(hir_id).and_then(|x| x.parent_node()).unwrap_or(hir_id) @@ -654,7 +665,7 @@ impl<'hir> Map<'hir> { /// Wether `hir_id` corresponds to a `mod` or a crate. pub fn is_hir_id_module(&self, hir_id: HirId) -> bool { - match self.lookup(hir_id) { + match self.find_and_read_entry(hir_id) { Some(Entry { node: Node::Item(Item { kind: ItemKind::Mod(_), .. }), .. }) | Some(Entry { node: Node::Crate, .. }) => true, _ => false, @@ -1150,7 +1161,7 @@ impl<'a> NodesMatchingSuffix<'a> { } fn matches_suffix(&self, hir: HirId) -> bool { - let name = match self.map.find_entry(hir).map(|entry| entry.node) { + let name = match self.map.find_and_read_entry(hir).map(|entry| entry.node) { Some(Node::Item(n)) => n.name(), Some(Node::ForeignItem(n)) => n.name(), Some(Node::TraitItem(n)) => n.name(), diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 2e7e8fdd72491..9cd044da0389d 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -8,9 +8,10 @@ pub mod map; use crate::ty::query::Providers; use crate::ty::TyCtxt; -use rustc_hir::def_id::LOCAL_CRATE; +use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::print; use rustc_hir::Crate; +use rustc_hir::HirId; use std::ops::Deref; /// A wrapper type which allows you to access HIR. @@ -46,9 +47,17 @@ impl<'tcx> TyCtxt<'tcx> { pub fn hir(self) -> Hir<'tcx> { Hir { tcx: self, map: &self.hir_map } } + + pub fn hir_id_parent_module(self, id: HirId) -> DefId { + self.parent_module(DefId::local(id.owner)) + } } pub fn provide(providers: &mut Providers<'_>) { + providers.parent_module = |tcx, id| { + let hir = tcx.hir(); + hir.get_module_parent(hir.as_local_hir_id(id).unwrap()) + }; providers.hir_crate = |tcx, _| tcx.hir_map.untracked_krate(); map::provide(providers); } diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index 7cb1f3aa0e851..5785f19760a03 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -98,6 +98,10 @@ rustc_queries! { eval_always desc { "computing the lint levels for items in this crate" } } + + query parent_module(_: DefId) -> DefId { + eval_always + } } Codegen { diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 0118fc4c8ac84..5d45501c13dcd 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -301,9 +301,7 @@ impl Visibility { Res::Err => Visibility::Public, def => Visibility::Restricted(def.def_id()), }, - hir::VisibilityKind::Inherited => { - Visibility::Restricted(tcx.hir().get_module_parent(id)) - } + hir::VisibilityKind::Inherited => Visibility::Restricted(tcx.hir_id_parent_module(id)), } } @@ -2968,7 +2966,7 @@ impl<'tcx> TyCtxt<'tcx> { Some(actual_expansion) => { self.hir().definitions().parent_module_of_macro_def(actual_expansion) } - None => self.hir().get_module_parent(block), + None => self.hir_id_parent_module(block), }; (ident, scope) } diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 5490e5e2b4d55..c7a2bcf172999 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -127,7 +127,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { plural_len: usize, ) -> bool { if ty.is_unit() - || cx.tcx.is_ty_uninhabited_from(cx.tcx.hir().get_module_parent(expr.hir_id), ty) + || cx.tcx.is_ty_uninhabited_from(cx.tcx.hir_id_parent_module(expr.hir_id), ty) { return true; } diff --git a/src/librustc_mir_build/hair/pattern/check_match.rs b/src/librustc_mir_build/hair/pattern/check_match.rs index b77bd4ecb8e1f..deda221086a3d 100644 --- a/src/librustc_mir_build/hair/pattern/check_match.rs +++ b/src/librustc_mir_build/hair/pattern/check_match.rs @@ -142,7 +142,7 @@ impl<'tcx> MatchVisitor<'_, 'tcx> { } fn check_in_cx(&self, hir_id: HirId, f: impl FnOnce(MatchCheckCtxt<'_, 'tcx>)) { - let module = self.tcx.hir().get_module_parent(hir_id); + let module = self.tcx.hir_id_parent_module(hir_id); MatchCheckCtxt::create_and_enter(self.tcx, self.param_env, module, |cx| f(cx)); } diff --git a/src/librustc_passes/liveness.rs b/src/librustc_passes/liveness.rs index b355a47c39470..0fd5943b6a328 100644 --- a/src/librustc_passes/liveness.rs +++ b/src/librustc_passes/liveness.rs @@ -1125,7 +1125,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } hir::ExprKind::Call(ref f, ref args) => { - let m = self.ir.tcx.hir().get_module_parent(expr.hir_id); + let m = self.ir.tcx.hir_id_parent_module(expr.hir_id); let succ = if self.ir.tcx.is_ty_uninhabited_from(m, self.tables.expr_ty(expr)) { self.s.exit_ln } else { @@ -1136,7 +1136,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } hir::ExprKind::MethodCall(.., ref args) => { - let m = self.ir.tcx.hir().get_module_parent(expr.hir_id); + let m = self.ir.tcx.hir_id_parent_module(expr.hir_id); let succ = if self.ir.tcx.is_ty_uninhabited_from(m, self.tables.expr_ty(expr)) { self.s.exit_ln } else { diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 74bb72d6fad7f..c553d24e6ccda 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -327,7 +327,7 @@ fn def_id_visibility<'tcx>( } Node::Expr(expr) => { return ( - ty::Visibility::Restricted(tcx.hir().get_module_parent(expr.hir_id)), + ty::Visibility::Restricted(tcx.hir_id_parent_module(expr.hir_id)), expr.span, "private", ); diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 789bac2705b07..ff5e9f3482c1c 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -427,7 +427,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }); if let Some((field, field_ty)) = field_receiver { - let scope = self.tcx.hir().get_module_parent(self.body_id); + let scope = self.tcx.hir_id_parent_module(self.body_id); let is_accessible = field.vis.is_accessible_from(scope, self.tcx); if is_accessible { @@ -686,7 +686,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { mut msg: String, candidates: Vec, ) { - let module_did = self.tcx.hir().get_module_parent(self.body_id); + let module_did = self.tcx.hir_id_parent_module(self.body_id); let module_id = self.tcx.hir().as_local_hir_id(module_did).unwrap(); let krate = self.tcx.hir().krate(); let (span, found_use) = UsePlacementFinder::check(self.tcx, krate, module_id); diff --git a/src/test/incremental/ich_nested_items.rs b/src/test/incremental/ich_nested_items.rs index b2b7e663151e2..2ef50153aad11 100644 --- a/src/test/incremental/ich_nested_items.rs +++ b/src/test/incremental/ich_nested_items.rs @@ -7,18 +7,21 @@ #![crate_type = "rlib"] #![feature(rustc_attrs)] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] +#[rustc_clean(label = "Hir", cfg = "cfail2")] +#[rustc_dirty(label = "HirBody", cfg = "cfail2")] pub fn foo() { #[cfg(cfail1)] - pub fn baz() { } // order is different... + pub fn baz() {} // order is different... - #[rustc_clean(label="Hir", cfg="cfail2")] - #[rustc_clean(label="HirBody", cfg="cfail2")] - pub fn bar() { } // but that doesn't matter. + // FIXME: Make "Hir" use `rustc_clean` here. Currently "Hir" includes a reference to + // the parent node, which is the statement holding this item. Changing the position of + // `bar` in `foo` will update that reference and make `Hir(bar)` dirty. + #[rustc_dirty(label = "Hir", cfg = "cfail2")] + #[rustc_clean(label = "HirBody", cfg = "cfail2")] + pub fn bar() {} // but that doesn't matter. #[cfg(cfail2)] - pub fn baz() { } // order is different... + pub fn baz() {} // order is different... - pub fn bap() { } // neither does adding a new item + pub fn bap() {} // neither does adding a new item }