diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index a7f1ba8b791..9ba3d0446dd 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -476,6 +476,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let (nodes, parenting) = index::index_hir(self.sess, self.resolver.definitions(), node, &bodies); let nodes = hir::OwnerNodes { hash, node_hash, nodes, bodies }; + let attrs = { + let mut hcx = self.resolver.create_stable_hashing_context(); + let mut stable_hasher = StableHasher::new(); + attrs.hash_stable(&mut hcx, &mut stable_hasher); + let hash = stable_hasher.finish(); + hir::AttributeMap { map: attrs, hash } + }; hir::OwnerInfo { nodes, parenting, attrs, trait_map } } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 4c8157fee37..bb5c0bc1889 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -672,6 +672,23 @@ pub struct ParentedNode<'tcx> { pub node: Node<'tcx>, } +/// Attributes owner by a HIR owner. +#[derive(Debug)] +pub struct AttributeMap<'tcx> { + pub map: BTreeMap, + pub hash: Fingerprint, +} + +impl<'tcx> AttributeMap<'tcx> { + pub const EMPTY: &'static AttributeMap<'static> = + &AttributeMap { map: BTreeMap::new(), hash: Fingerprint::ZERO }; + + #[inline] + pub fn get(&self, id: ItemLocalId) -> &'tcx [Attribute] { + self.map.get(&id).copied().unwrap_or(&[]) + } +} + #[derive(Debug)] pub struct OwnerNodes<'tcx> { /// Pre-computed hash of the full HIR. @@ -691,8 +708,8 @@ pub struct OwnerInfo<'hir> { pub nodes: OwnerNodes<'hir>, /// Map from each nested owner to its parent's local id. pub parenting: FxHashMap, - - pub attrs: BTreeMap, + /// Collected attributes of the HIR nodes. + pub attrs: AttributeMap<'hir>, /// Map indicating what traits are in scope for places where this /// is relevant; generated by resolve. pub trait_map: FxHashMap>, diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index af8421aeb89..93224d388c0 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -2,6 +2,7 @@ //! //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html +#![feature(const_btree_new)] #![feature(crate_visibility_modifier)] #![feature(in_band_lifetimes)] #![feature(once_cell)] diff --git a/compiler/rustc_hir/src/stable_hash_impls.rs b/compiler/rustc_hir/src/stable_hash_impls.rs index ad73e363d7f..da2aeb9b311 100644 --- a/compiler/rustc_hir/src/stable_hash_impls.rs +++ b/compiler/rustc_hir/src/stable_hash_impls.rs @@ -1,8 +1,8 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey}; use crate::hir::{ - BodyId, Expr, ForeignItem, ForeignItemId, ImplItem, ImplItemId, Item, ItemId, Mod, OwnerNodes, - TraitItem, TraitItemId, Ty, VisibilityKind, + AttributeMap, BodyId, Expr, ForeignItem, ForeignItemId, ImplItem, ImplItemId, Item, ItemId, + Mod, OwnerNodes, TraitItem, TraitItemId, Ty, VisibilityKind, }; use crate::hir_id::{HirId, ItemLocalId}; use rustc_span::def_id::DefPathHash; @@ -218,3 +218,12 @@ impl HashStable for OwnerNodes<'tcx> { hash.hash_stable(hcx, hasher); } } + +impl HashStable for AttributeMap<'tcx> { + fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { + // We ignore the `map` since it refers to information included in `hash` which is hashed in + // the collector and used for the crate hash. + let AttributeMap { hash, map: _ } = *self; + hash.hash_stable(hcx, hasher); + } +} diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 834d5f964e1..af4c0e4843d 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -580,7 +580,7 @@ impl<'hir> Map<'hir> { let krate = self.krate(); for (owner, info) in krate.owners.iter_enumerated() { if let Some(info) = info { - for (&local_id, attrs) in info.attrs.iter() { + for (&local_id, attrs) in info.attrs.map.iter() { let id = HirId { owner, local_id }; for a in *attrs { visitor.visit_attribute(id, a) diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index 70179e73b19..f941981be79 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -8,14 +8,12 @@ pub mod place; use crate::ty::query::Providers; use crate::ty::TyCtxt; -use rustc_ast::Attribute; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_hir::def_id::LocalDefId; use rustc_hir::*; use rustc_query_system::ich::StableHashingContext; use rustc_span::DUMMY_SP; -use std::collections::BTreeMap; /// Top-level HIR node for current owner. This only contains the node for which /// `HirId::local_id == 0`, and excludes bodies. @@ -36,24 +34,6 @@ impl<'a, 'tcx> HashStable> for Owner<'tcx> { } } -/// Attributes owner by a HIR owner. -#[derive(Copy, Clone, Debug, HashStable)] -pub struct AttributeMap<'tcx> { - map: &'tcx BTreeMap, -} - -impl<'tcx> AttributeMap<'tcx> { - fn new(owner_info: &'tcx Option>) -> AttributeMap<'tcx> { - const FALLBACK: &'static BTreeMap = &BTreeMap::new(); - let map = owner_info.as_ref().map_or(FALLBACK, |info| &info.attrs); - AttributeMap { map } - } - - fn get(&self, id: ItemLocalId) -> &'tcx [Attribute] { - self.map.get(&id).copied().unwrap_or(&[]) - } -} - /// Gather the LocalDefId for each item-like within a module, including items contained within /// bodies. The Ids are in visitor order. This is used to partition a pass between modules. #[derive(Debug, HashStable)] @@ -105,7 +85,8 @@ pub fn provide(providers: &mut Providers) { }); parent }; - providers.hir_attrs = |tcx, id| AttributeMap::new(&tcx.hir_crate(()).owners[id]); + providers.hir_attrs = + |tcx, id| tcx.hir_crate(()).owners[id].as_ref().map_or(AttributeMap::EMPTY, |o| &o.attrs); providers.source_span = |tcx, def_id| tcx.resolutions(()).definitions.def_span(def_id); providers.def_span = |tcx, def_id| tcx.hir().span_if_local(def_id).unwrap_or(DUMMY_SP); providers.fn_arg_names = |tcx, id| { diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index e7219cc58a1..e41f5add457 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -30,7 +30,6 @@ #![feature(bool_to_option)] #![feature(box_patterns)] #![feature(core_intrinsics)] -#![feature(const_btree_new)] #![feature(discriminant_kind)] #![feature(exhaustive_patterns)] #![feature(if_let_guard)] diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index e604f59175e..eb4cc7c750c 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -77,7 +77,7 @@ rustc_queries! { /// /// This can be conveniently accessed by methods on `tcx.hir()`. /// Avoid calling this query directly. - query hir_attrs(key: LocalDefId) -> rustc_middle::hir::AttributeMap<'tcx> { + query hir_attrs(key: LocalDefId) -> &'tcx hir::AttributeMap<'tcx> { desc { |tcx| "HIR owner attributes in `{}`", tcx.def_path_str(key.to_def_id()) } }