//! Defines database & queries for name resolution. use base_db::{Crate, RootQueryDb, SourceDatabase}; use hir_expand::{ EditionedFileId, HirFileId, InFile, Lookup, MacroCallId, MacroDefId, MacroDefKind, db::ExpandDatabase, }; use la_arena::ArenaMap; use triomphe::Arc; use crate::{ AssocItemId, AttrDefId, BlockId, BlockLoc, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, EnumVariantId, EnumVariantLoc, ExternBlockId, ExternBlockLoc, ExternCrateId, ExternCrateLoc, FunctionId, FunctionLoc, GenericDefId, ImplId, ImplLoc, LocalFieldId, Macro2Id, Macro2Loc, MacroExpander, MacroId, MacroRulesId, MacroRulesLoc, MacroRulesLocFlags, ProcMacroId, ProcMacroLoc, StaticId, StaticLoc, StructId, StructLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, UseId, UseLoc, VariantId, attrs::AttrFlags, expr_store::{ Body, BodySourceMap, ExpressionStore, ExpressionStoreSourceMap, scope::ExprScopes, }, hir::generics::GenericParams, import_map::ImportMap, item_tree::{ItemTree, file_item_tree_query}, nameres::crate_def_map, signatures::{ ConstSignature, EnumSignature, FunctionSignature, ImplSignature, StaticSignature, StructSignature, TraitSignature, TypeAliasSignature, UnionSignature, }, visibility::{self, Visibility}, }; use salsa::plumbing::AsId; #[query_group::query_group(InternDatabaseStorage)] pub trait InternDatabase: RootQueryDb { // region: items #[salsa::interned] fn intern_use(&self, loc: UseLoc) -> UseId; #[salsa::interned] fn intern_extern_crate(&self, loc: ExternCrateLoc) -> ExternCrateId; #[salsa::interned] fn intern_function(&self, loc: FunctionLoc) -> FunctionId; #[salsa::interned] fn intern_struct(&self, loc: StructLoc) -> StructId; #[salsa::interned] fn intern_union(&self, loc: UnionLoc) -> UnionId; #[salsa::interned] fn intern_enum(&self, loc: EnumLoc) -> EnumId; #[salsa::interned] fn intern_enum_variant(&self, loc: EnumVariantLoc) -> EnumVariantId; #[salsa::interned] fn intern_const(&self, loc: ConstLoc) -> ConstId; #[salsa::interned] fn intern_static(&self, loc: StaticLoc) -> StaticId; #[salsa::interned] fn intern_trait(&self, loc: TraitLoc) -> TraitId; #[salsa::interned] fn intern_type_alias(&self, loc: TypeAliasLoc) -> TypeAliasId; #[salsa::interned] fn intern_impl(&self, loc: ImplLoc) -> ImplId; #[salsa::interned] fn intern_extern_block(&self, loc: ExternBlockLoc) -> ExternBlockId; #[salsa::interned] fn intern_macro2(&self, loc: Macro2Loc) -> Macro2Id; #[salsa::interned] fn intern_proc_macro(&self, loc: ProcMacroLoc) -> ProcMacroId; #[salsa::interned] fn intern_macro_rules(&self, loc: MacroRulesLoc) -> MacroRulesId; // endregion: items #[salsa::interned] fn intern_block(&self, loc: BlockLoc) -> BlockId; } #[query_group::query_group] pub trait DefDatabase: InternDatabase + ExpandDatabase + SourceDatabase { /// Whether to expand procedural macros during name resolution. #[salsa::input] fn expand_proc_attr_macros(&self) -> bool; /// Computes an [`ItemTree`] for the given file or macro expansion. #[salsa::invoke(file_item_tree_query)] #[salsa::transparent] fn file_item_tree(&self, file_id: HirFileId) -> &ItemTree; /// Turns a MacroId into a MacroDefId, describing the macro's definition post name resolution. #[salsa::invoke(macro_def)] fn macro_def(&self, m: MacroId) -> MacroDefId; // region:data #[salsa::tracked] fn trait_signature(&self, trait_: TraitId) -> Arc { self.trait_signature_with_source_map(trait_).0 } #[salsa::tracked] fn impl_signature(&self, impl_: ImplId) -> Arc { self.impl_signature_with_source_map(impl_).0 } #[salsa::tracked] fn struct_signature(&self, struct_: StructId) -> Arc { self.struct_signature_with_source_map(struct_).0 } #[salsa::tracked] fn union_signature(&self, union_: UnionId) -> Arc { self.union_signature_with_source_map(union_).0 } #[salsa::tracked] fn enum_signature(&self, e: EnumId) -> Arc { self.enum_signature_with_source_map(e).0 } #[salsa::tracked] fn const_signature(&self, e: ConstId) -> Arc { self.const_signature_with_source_map(e).0 } #[salsa::tracked] fn static_signature(&self, e: StaticId) -> Arc { self.static_signature_with_source_map(e).0 } #[salsa::tracked] fn function_signature(&self, e: FunctionId) -> Arc { self.function_signature_with_source_map(e).0 } #[salsa::tracked] fn type_alias_signature(&self, e: TypeAliasId) -> Arc { self.type_alias_signature_with_source_map(e).0 } #[salsa::invoke(TraitSignature::query)] fn trait_signature_with_source_map( &self, trait_: TraitId, ) -> (Arc, Arc); #[salsa::invoke(ImplSignature::query)] fn impl_signature_with_source_map( &self, impl_: ImplId, ) -> (Arc, Arc); #[salsa::invoke(StructSignature::query)] fn struct_signature_with_source_map( &self, struct_: StructId, ) -> (Arc, Arc); #[salsa::invoke(UnionSignature::query)] fn union_signature_with_source_map( &self, union_: UnionId, ) -> (Arc, Arc); #[salsa::invoke(EnumSignature::query)] fn enum_signature_with_source_map( &self, e: EnumId, ) -> (Arc, Arc); #[salsa::invoke(ConstSignature::query)] fn const_signature_with_source_map( &self, e: ConstId, ) -> (Arc, Arc); #[salsa::invoke(StaticSignature::query)] fn static_signature_with_source_map( &self, e: StaticId, ) -> (Arc, Arc); #[salsa::invoke(FunctionSignature::query)] fn function_signature_with_source_map( &self, e: FunctionId, ) -> (Arc, Arc); #[salsa::invoke(TypeAliasSignature::query)] fn type_alias_signature_with_source_map( &self, e: TypeAliasId, ) -> (Arc, Arc); // endregion:data #[salsa::invoke(Body::body_with_source_map_query)] #[salsa::lru(512)] fn body_with_source_map(&self, def: DefWithBodyId) -> (Arc, Arc); #[salsa::invoke(Body::body_query)] fn body(&self, def: DefWithBodyId) -> Arc; #[salsa::invoke(ExprScopes::expr_scopes_query)] fn expr_scopes(&self, def: DefWithBodyId) -> Arc; #[salsa::transparent] #[salsa::invoke(GenericParams::new)] fn generic_params(&self, def: GenericDefId) -> Arc; #[salsa::transparent] #[salsa::invoke(GenericParams::generic_params_and_store)] fn generic_params_and_store( &self, def: GenericDefId, ) -> (Arc, Arc); #[salsa::transparent] #[salsa::invoke(GenericParams::generic_params_and_store_and_source_map)] fn generic_params_and_store_and_source_map( &self, def: GenericDefId, ) -> (Arc, Arc, Arc); #[salsa::invoke(ImportMap::import_map_query)] fn import_map(&self, krate: Crate) -> Arc; // region:visibilities #[salsa::invoke(visibility::field_visibilities_query)] fn field_visibilities(&self, var: VariantId) -> Arc>; #[salsa::invoke(visibility::assoc_visibility_query)] fn assoc_visibility(&self, def: AssocItemId) -> Visibility; // endregion:visibilities #[salsa::invoke(crate::lang_item::crate_notable_traits)] #[salsa::transparent] fn crate_notable_traits(&self, krate: Crate) -> Option<&[TraitId]>; #[salsa::invoke(crate_supports_no_std)] fn crate_supports_no_std(&self, crate_id: Crate) -> bool; #[salsa::invoke(include_macro_invoc)] fn include_macro_invoc(&self, crate_id: Crate) -> Arc<[(MacroCallId, EditionedFileId)]>; } // return: macro call id and include file id fn include_macro_invoc( db: &dyn DefDatabase, krate: Crate, ) -> Arc<[(MacroCallId, EditionedFileId)]> { crate_def_map(db, krate) .modules .values() .flat_map(|m| m.scope.iter_macro_invoc()) .filter_map(|invoc| { db.lookup_intern_macro_call(*invoc.1) .include_file_id(db, *invoc.1) .map(|x| (*invoc.1, x)) }) .collect() } fn crate_supports_no_std(db: &dyn DefDatabase, crate_id: Crate) -> bool { let root_module = crate_def_map(db, crate_id).root_module_id(); let attrs = AttrFlags::query(db, AttrDefId::ModuleId(root_module)); attrs.contains(AttrFlags::IS_NO_STD) } fn macro_def(db: &dyn DefDatabase, id: MacroId) -> MacroDefId { let kind = |expander, file_id, m| { let in_file = InFile::new(file_id, m); match expander { MacroExpander::Declarative { styles } => MacroDefKind::Declarative(in_file, styles), MacroExpander::BuiltIn(it) => MacroDefKind::BuiltIn(in_file, it), MacroExpander::BuiltInAttr(it) => MacroDefKind::BuiltInAttr(in_file, it), MacroExpander::BuiltInDerive(it) => MacroDefKind::BuiltInDerive(in_file, it), MacroExpander::BuiltInEager(it) => MacroDefKind::BuiltInEager(in_file, it), } }; match id { MacroId::Macro2Id(it) => { let loc: Macro2Loc = it.lookup(db); MacroDefId { krate: loc.container.krate(db), kind: kind(loc.expander, loc.id.file_id, loc.id.value.upcast()), local_inner: false, allow_internal_unsafe: loc.allow_internal_unsafe, edition: loc.edition, } } MacroId::MacroRulesId(it) => { let loc: MacroRulesLoc = it.lookup(db); MacroDefId { krate: loc.container.krate(db), kind: kind(loc.expander, loc.id.file_id, loc.id.value.upcast()), local_inner: loc.flags.contains(MacroRulesLocFlags::LOCAL_INNER), allow_internal_unsafe: loc .flags .contains(MacroRulesLocFlags::ALLOW_INTERNAL_UNSAFE), edition: loc.edition, } } MacroId::ProcMacroId(it) => { let loc = it.lookup(db); MacroDefId { krate: loc.container.krate(db), kind: MacroDefKind::ProcMacro(loc.id, loc.expander, loc.kind), local_inner: false, allow_internal_unsafe: false, edition: loc.edition, } } } }