X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=crates%2Fhir_def%2Fsrc%2Fitem_scope.rs;h=258d1e0f6c5191a5c17cd97b5d3ef3ef31943344;hb=0db0dec9993b510efeb61cb1d8ff113270d4ca51;hp=ec8c3a87c0f17318a68efd3c74a2b49c7851ee2d;hpb=97409e5fc83ab8a4460474f5dc5a119160873544;p=rust.git diff --git a/crates/hir_def/src/item_scope.rs b/crates/hir_def/src/item_scope.rs index ec8c3a87c0f..258d1e0f6c5 100644 --- a/crates/hir_def/src/item_scope.rs +++ b/crates/hir_def/src/item_scope.rs @@ -8,7 +8,7 @@ use once_cell::sync::Lazy; use profile::Count; use rustc_hash::{FxHashMap, FxHashSet}; -use smallvec::SmallVec; +use smallvec::{smallvec, SmallVec}; use stdx::format_to; use syntax::ast; @@ -44,6 +44,8 @@ pub struct ItemScope { /// The defs declared in this scope. Each def has a single scope where it is /// declared. declarations: Vec, + macro_declarations: Vec, + impls: Vec, unnamed_consts: Vec, /// Traits imported via `use Trait as _;`. @@ -62,7 +64,10 @@ pub struct ItemScope { // be all resolved to the last one defined if shadowing happens. legacy_macros: FxHashMap, attr_macros: FxHashMap, MacroCallId>, - derive_macros: FxHashMap, SmallVec<[(AttrId, MacroCallId); 1]>>, + /// The derive macro invocations in this scope, keyed by the owner item over the actual derive attributes + /// paired with the derive macro invocations for the specific attribute. + derive_macros: + FxHashMap, SmallVec<[(AttrId, SmallVec<[Option; 1]>); 1]>>, } pub(crate) static BUILTIN_SCOPE: Lazy> = Lazy::new(|| { @@ -101,6 +106,10 @@ pub fn declarations(&self) -> impl Iterator + '_ { self.declarations.iter().copied() } + pub fn macro_declarations(&self) -> impl Iterator + '_ { + self.macro_declarations.iter().copied() + } + pub fn impls(&self) -> impl Iterator + ExactSizeIterator + '_ { self.impls.iter().copied() } @@ -136,12 +145,17 @@ pub(crate) fn get(&self, name: &Name) -> PerNs { /// XXX: this is O(N) rather than O(1), try to not introduce new usages. pub(crate) fn name_of(&self, item: ItemInNs) -> Option<(&Name, Visibility)> { - for (name, per_ns) in self.entries() { - if let Some(vis) = item.match_with(per_ns) { - return Some((name, vis)); + let (def, mut iter) = match item { + ItemInNs::Macros(def) => { + return self + .macros + .iter() + .find_map(|(name, &(other_def, vis))| (other_def == def).then(|| (name, vis))); } - } - None + ItemInNs::Types(def) => (def, self.types.iter()), + ItemInNs::Values(def) => (def, self.values.iter()), + }; + iter.find_map(|(name, &(other_def, vis))| (other_def == def).then(|| (name, vis))) } pub(crate) fn traits<'a>(&'a self) -> impl Iterator + 'a { @@ -158,6 +172,10 @@ pub(crate) fn declare(&mut self, def: ModuleDefId) { self.declarations.push(def) } + pub(crate) fn declare_macro(&mut self, def: MacroDefId) { + self.macro_declarations.push(def); + } + pub(crate) fn get_legacy_macro(&self, name: &Name) -> Option { self.legacy_macros.get(name).copied() } @@ -184,19 +202,40 @@ pub(crate) fn attr_macro_invocs( self.attr_macros.iter().map(|(k, v)| (*k, *v)) } - pub(crate) fn add_derive_macro_invoc( + pub(crate) fn set_derive_macro_invoc( &mut self, - item: AstId, + adt: AstId, call: MacroCallId, attr_id: AttrId, + idx: usize, + ) { + if let Some(derives) = self.derive_macros.get_mut(&adt) { + if let Some((_, invocs)) = derives.iter_mut().find(|&&mut (id, _)| id == attr_id) { + invocs[idx] = Some(call); + } + } + } + + /// We are required to set this up front as derive invocation recording happens out of order + /// due to the fixed pointer iteration loop being able to record some derives later than others + /// independent of their indices. + pub(crate) fn init_derive_attribute( + &mut self, + adt: AstId, + attr_id: AttrId, + len: usize, ) { - self.derive_macros.entry(item).or_default().push((attr_id, call)); + self.derive_macros.entry(adt).or_default().push((attr_id, smallvec![None; len])); } pub(crate) fn derive_macro_invocs( &self, - ) -> impl Iterator, &[(AttrId, MacroCallId)])> + '_ { - self.derive_macros.iter().map(|(k, v)| (*k, v.as_ref())) + ) -> impl Iterator< + Item = (AstId, impl Iterator])>), + > + '_ { + self.derive_macros + .iter() + .map(|(k, v)| (*k, v.iter().map(|(attr_id, invocs)| (*attr_id, &**invocs)))) } pub(crate) fn unnamed_trait_vis(&self, tr: TraitId) -> Option { @@ -331,7 +370,8 @@ pub(crate) fn shrink_to_fit(&mut self) { values, macros, unresolved, - declarations: defs, + declarations, + macro_declarations, impls, unnamed_consts, unnamed_trait_imports, @@ -343,7 +383,8 @@ pub(crate) fn shrink_to_fit(&mut self) { values.shrink_to_fit(); macros.shrink_to_fit(); unresolved.shrink_to_fit(); - defs.shrink_to_fit(); + declarations.shrink_to_fit(); + macro_declarations.shrink_to_fit(); impls.shrink_to_fit(); unnamed_consts.shrink_to_fit(); unnamed_trait_imports.shrink_to_fit(); @@ -386,20 +427,6 @@ pub enum ItemInNs { } impl ItemInNs { - fn match_with(self, per_ns: PerNs) -> Option { - match self { - ItemInNs::Types(def) => { - per_ns.types.filter(|(other_def, _)| *other_def == def).map(|(_, vis)| vis) - } - ItemInNs::Values(def) => { - per_ns.values.filter(|(other_def, _)| *other_def == def).map(|(_, vis)| vis) - } - ItemInNs::Macros(def) => { - per_ns.macros.filter(|(other_def, _)| *other_def == def).map(|(_, vis)| vis) - } - } - } - pub fn as_module_def_id(self) -> Option { match self { ItemInNs::Types(id) | ItemInNs::Values(id) => Some(id),