X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=crates%2Fhir_def%2Fsrc%2Fitem_scope.rs;h=258d1e0f6c5191a5c17cd97b5d3ef3ef31943344;hb=0db0dec9993b510efeb61cb1d8ff113270d4ca51;hp=9014468ea04f11fe5d4a261584f8da194d90c2bb;hpb=2ace128dd4c9c2e5d59d21402da53654acb0c7e4;p=rust.git diff --git a/crates/hir_def/src/item_scope.rs b/crates/hir_def/src/item_scope.rs index 9014468ea04..258d1e0f6c5 100644 --- a/crates/hir_def/src/item_scope.rs +++ b/crates/hir_def/src/item_scope.rs @@ -4,15 +4,17 @@ use std::collections::hash_map::Entry; use base_db::CrateId; -use hir_expand::name::Name; -use hir_expand::MacroDefKind; +use hir_expand::{name::Name, AstId, MacroCallId, MacroDefKind}; use once_cell::sync::Lazy; +use profile::Count; use rustc_hash::{FxHashMap, FxHashSet}; +use smallvec::{smallvec, SmallVec}; use stdx::format_to; +use syntax::ast; use crate::{ - db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, ConstId, ImplId, - LocalModuleId, MacroDefId, ModuleDefId, ModuleId, TraitId, + attr::AttrId, db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, + ConstId, ImplId, LocalModuleId, MacroDefId, ModuleDefId, ModuleId, TraitId, }; #[derive(Copy, Clone)] @@ -30,12 +32,20 @@ pub struct PerNsGlobImports { #[derive(Debug, Default, PartialEq, Eq)] pub struct ItemScope { + _c: Count, + + /// Defs visible in this scope. This includes `declarations`, but also + /// imports. types: FxHashMap, values: FxHashMap, macros: FxHashMap, unresolved: FxHashSet, - defs: Vec, + /// 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 _;`. @@ -53,12 +63,17 @@ pub struct ItemScope { // FIXME: Macro shadowing in one module is not properly handled. Non-item place macros will // be all resolved to the last one defined if shadowing happens. legacy_macros: FxHashMap, + attr_macros: FxHashMap, MacroCallId>, + /// 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(|| { BuiltinType::ALL .iter() - .map(|(name, ty)| (name.clone(), PerNs::types(ty.clone().into(), Visibility::Public))) + .map(|(name, ty)| (name.clone(), PerNs::types((*ty).into(), Visibility::Public))) .collect() }); @@ -88,7 +103,11 @@ pub fn entries<'a>(&'a self) -> impl Iterator + 'a { } pub fn declarations(&self) -> impl Iterator + '_ { - self.defs.iter().copied() + self.declarations.iter().copied() + } + + pub fn macro_declarations(&self) -> impl Iterator + '_ { + self.macro_declarations.iter().copied() } pub fn impls(&self) -> impl Iterator + ExactSizeIterator + '_ { @@ -101,12 +120,6 @@ pub fn values( self.values.values().copied() } - pub fn visibility_of(&self, def: ModuleDefId) -> Option { - self.name_of(ItemInNs::Types(def)) - .or_else(|| self.name_of(ItemInNs::Values(def))) - .map(|(_, v)| v) - } - pub fn unnamed_consts(&self) -> impl Iterator + '_ { self.unnamed_consts.iter().copied() } @@ -130,13 +143,19 @@ 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 { @@ -149,8 +168,12 @@ pub(crate) fn traits<'a>(&'a self) -> impl Iterator + 'a { .chain(self.unnamed_trait_imports.keys().copied()) } - pub(crate) fn define_def(&mut self, def: ModuleDefId) { - self.defs.push(def) + 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 { @@ -169,6 +192,52 @@ pub(crate) fn define_legacy_macro(&mut self, name: Name, mac: MacroDefId) { self.legacy_macros.insert(name, mac); } + pub(crate) fn add_attr_macro_invoc(&mut self, item: AstId, call: MacroCallId) { + self.attr_macros.insert(item, call); + } + + pub(crate) fn attr_macro_invocs( + &self, + ) -> impl Iterator, MacroCallId)> + '_ { + self.attr_macros.iter().map(|(k, v)| (*k, *v)) + } + + pub(crate) fn set_derive_macro_invoc( + &mut self, + 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(adt).or_default().push((attr_id, smallvec![None; len])); + } + + pub(crate) fn derive_macro_invocs( + &self, + ) -> 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 { self.unnamed_trait_imports.get(&tr).copied() } @@ -230,10 +299,8 @@ macro_rules! check_changed { check_changed!(changed, (self / def).values, glob_imports[lookup], def_import_type); check_changed!(changed, (self / def).macros, glob_imports[lookup], def_import_type); - if def.is_none() { - if self.unresolved.insert(lookup.1) { - changed = true; - } + if def.is_none() && self.unresolved.insert(lookup.1) { + changed = true; } changed @@ -298,25 +365,32 @@ pub(crate) fn dump(&self, buf: &mut String) { pub(crate) fn shrink_to_fit(&mut self) { // Exhaustive match to require handling new fields. let Self { + _c: _, types, values, macros, unresolved, - defs, + declarations, + macro_declarations, impls, unnamed_consts, unnamed_trait_imports, legacy_macros, + attr_macros, + derive_macros, } = self; types.shrink_to_fit(); 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(); legacy_macros.shrink_to_fit(); + attr_macros.shrink_to_fit(); + derive_macros.shrink_to_fit(); } } @@ -353,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),