Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-def/src/lib.rs')
| -rw-r--r-- | crates/hir-def/src/lib.rs | 207 |
1 files changed, 63 insertions, 144 deletions
diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs index ad247e0d68..e58cb7bad7 100644 --- a/crates/hir-def/src/lib.rs +++ b/crates/hir-def/src/lib.rs @@ -71,7 +71,6 @@ use hir_expand::{ name::Name, proc_macro::{CustomProcMacroExpander, ProcMacroKind}, }; -use la_arena::Idx; use nameres::DefMap; use span::{AstIdNode, Edition, FileAstId, SyntaxContext}; use stdx::impl_from; @@ -412,181 +411,111 @@ pub enum MacroExpander { #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct ProcMacroLoc { - pub container: CrateRootModuleId, + pub container: ModuleId, pub id: AstId<ast::Fn>, pub expander: CustomProcMacroExpander, pub kind: ProcMacroKind, pub edition: Edition, } impl_intern!(ProcMacroId, ProcMacroLoc, intern_proc_macro, lookup_intern_proc_macro); -impl_loc!(ProcMacroLoc, id: Fn, container: CrateRootModuleId); +impl_loc!(ProcMacroLoc, id: Fn, container: ModuleId); -#[derive(Debug, Hash, PartialEq, Eq, Clone)] -pub struct BlockLoc { +#[salsa_macros::tracked(debug)] +#[derive(PartialOrd, Ord)] +pub struct BlockIdLt<'db> { pub ast_id: AstId<ast::BlockExpr>, /// The containing module. - pub module: ModuleId, -} -impl_intern!(BlockId, BlockLoc, intern_block, lookup_intern_block); - -/// A `ModuleId` that is always a crate's root module. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct CrateRootModuleId { - krate: Crate, -} - -impl CrateRootModuleId { - pub fn def_map(self, db: &dyn DefDatabase) -> &DefMap { - crate_def_map(db, self.krate) - } - - pub(crate) fn local_def_map(self, db: &dyn DefDatabase) -> (&DefMap, &LocalDefMap) { - let def_map = crate_local_def_map(db, self.krate); - (def_map.def_map(db), def_map.local(db)) - } - - pub fn krate(self) -> Crate { - self.krate - } -} - -impl HasModule for CrateRootModuleId { - #[inline] - fn module(&self, _db: &dyn DefDatabase) -> ModuleId { - ModuleId { krate: self.krate, block: None, local_id: DefMap::ROOT } - } - - #[inline] - fn krate(&self, _db: &dyn DefDatabase) -> Crate { - self.krate - } -} - -impl PartialEq<ModuleId> for CrateRootModuleId { - fn eq(&self, other: &ModuleId) -> bool { - other.block.is_none() && other.local_id == DefMap::ROOT && self.krate == other.krate - } -} -impl PartialEq<CrateRootModuleId> for ModuleId { - fn eq(&self, other: &CrateRootModuleId) -> bool { - other == self - } -} - -impl From<CrateRootModuleId> for ModuleId { - fn from(CrateRootModuleId { krate }: CrateRootModuleId) -> Self { - ModuleId { krate, block: None, local_id: DefMap::ROOT } - } + pub module: ModuleIdLt<'db>, } +pub type BlockId = BlockIdLt<'static>; -impl From<CrateRootModuleId> for ModuleDefId { - fn from(value: CrateRootModuleId) -> Self { - ModuleDefId::ModuleId(value.into()) - } -} - -impl From<Crate> for CrateRootModuleId { - fn from(krate: Crate) -> Self { - CrateRootModuleId { krate } +impl BlockIdLt<'_> { + /// # Safety + /// + /// The caller must ensure that the `ModuleId` is not leaked outside of query computations. + pub unsafe fn to_static(self) -> BlockId { + unsafe { std::mem::transmute(self) } } } - -impl TryFrom<ModuleId> for CrateRootModuleId { - type Error = (); - - fn try_from(ModuleId { krate, block, local_id }: ModuleId) -> Result<Self, Self::Error> { - if block.is_none() && local_id == DefMap::ROOT { - Ok(CrateRootModuleId { krate }) - } else { - Err(()) - } +impl BlockId { + /// # Safety + /// + /// The caller must ensure that the `BlockId` comes from the given database. + pub unsafe fn to_db<'db>(self, _db: &'db dyn DefDatabase) -> BlockIdLt<'db> { + unsafe { std::mem::transmute(self) } } } -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct ModuleId { - krate: Crate, +#[salsa_macros::tracked(debug)] +#[derive(PartialOrd, Ord)] +pub struct ModuleIdLt<'db> { + /// The crate this module belongs to. + pub krate: Crate, /// If this `ModuleId` was derived from a `DefMap` for a block expression, this stores the /// `BlockId` of that block expression. If `None`, this module is part of the crate-level /// `DefMap` of `krate`. - block: Option<BlockId>, - /// The module's ID in its originating `DefMap`. - pub local_id: LocalModuleId, + pub block: Option<BlockIdLt<'db>>, } +pub type ModuleId = ModuleIdLt<'static>; -impl ModuleId { - pub fn def_map(self, db: &dyn DefDatabase) -> &DefMap { - match self.block { +impl<'db> ModuleIdLt<'db> { + /// # Safety + /// + /// The caller must ensure that the `ModuleId` is not leaked outside of query computations. + pub unsafe fn to_static(self) -> ModuleId { + unsafe { std::mem::transmute(self) } + } + + pub fn def_map(self, db: &'db dyn DefDatabase) -> &'db DefMap { + match self.block(db) { Some(block) => block_def_map(db, block), - None => crate_def_map(db, self.krate), + None => crate_def_map(db, self.krate(db)), } } - pub(crate) fn local_def_map(self, db: &dyn DefDatabase) -> (&DefMap, &LocalDefMap) { - match self.block { + pub(crate) fn local_def_map(self, db: &'db dyn DefDatabase) -> (&'db DefMap, &'db LocalDefMap) { + match self.block(db) { Some(block) => (block_def_map(db, block), self.only_local_def_map(db)), None => { - let def_map = crate_local_def_map(db, self.krate); + let def_map = crate_local_def_map(db, self.krate(db)); (def_map.def_map(db), def_map.local(db)) } } } - pub(crate) fn only_local_def_map(self, db: &dyn DefDatabase) -> &LocalDefMap { - crate_local_def_map(db, self.krate).local(db) - } - - pub fn crate_def_map(self, db: &dyn DefDatabase) -> &DefMap { - crate_def_map(db, self.krate) + pub(crate) fn only_local_def_map(self, db: &'db dyn DefDatabase) -> &'db LocalDefMap { + crate_local_def_map(db, self.krate(db)).local(db) } - pub fn krate(self) -> Crate { - self.krate + pub fn crate_def_map(self, db: &'db dyn DefDatabase) -> &'db DefMap { + crate_def_map(db, self.krate(db)) } - pub fn name(self, db: &dyn DefDatabase) -> Option<Name> { + pub fn name(self, db: &'db dyn DefDatabase) -> Option<Name> { let def_map = self.def_map(db); - let parent = def_map[self.local_id].parent?; + let parent = def_map[self].parent?; def_map[parent].children.iter().find_map(|(name, module_id)| { - if *module_id == self.local_id { Some(name.clone()) } else { None } + if *module_id == self { Some(name.clone()) } else { None } }) } /// Returns the module containing `self`, either the parent `mod`, or the module (or block) containing /// the block, if `self` corresponds to a block expression. - pub fn containing_module(self, db: &dyn DefDatabase) -> Option<ModuleId> { - self.def_map(db).containing_module(self.local_id) - } - - pub fn containing_block(self) -> Option<BlockId> { - self.block - } - - pub fn is_block_module(self) -> bool { - self.block.is_some() && self.local_id == DefMap::ROOT + pub fn containing_module(self, db: &'db dyn DefDatabase) -> Option<ModuleIdLt<'db>> { + self.def_map(db).containing_module(self) } - pub fn is_within_block(self) -> bool { - self.block.is_some() - } - - /// Returns the [`CrateRootModuleId`] for this module if it is the crate root module. - pub fn as_crate_root(&self) -> Option<CrateRootModuleId> { - if self.local_id == DefMap::ROOT && self.block.is_none() { - Some(CrateRootModuleId { krate: self.krate }) - } else { - None - } - } - - /// Returns the [`CrateRootModuleId`] for this module. - pub fn derive_crate_root(&self) -> CrateRootModuleId { - CrateRootModuleId { krate: self.krate } + pub fn is_block_module(self, db: &'db dyn DefDatabase) -> bool { + self.block(db).is_some() && self.def_map(db).root_module_id() == self } +} - /// Whether this module represents the crate root module - pub fn is_crate_root(&self) -> bool { - self.local_id == DefMap::ROOT && self.block.is_none() +impl ModuleId { + /// # Safety + /// + /// The caller must ensure that the `ModuleId` comes from the given database. + pub unsafe fn to_db<'db>(self, _db: &'db dyn DefDatabase) -> ModuleIdLt<'db> { + unsafe { std::mem::transmute(self) } } } @@ -597,9 +526,6 @@ impl HasModule for ModuleId { } } -/// An ID of a module, **local** to a `DefMap`. -pub type LocalModuleId = Idx<nameres::ModuleData>; - #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, salsa::Update)] pub struct FieldId { // FIXME: Store this as an erased `salsa::Id` to save space @@ -682,7 +608,7 @@ pub struct LifetimeParamId { pub local_id: LocalLifetimeParamId, } -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, salsa_macros::Supertype)] pub enum ItemContainerId { ExternBlockId(ExternBlockId), ModuleId(ModuleId), @@ -956,16 +882,9 @@ impl CallableDefId { } } -// FIXME: We probably should use this in more places. -/// This is used to avoid interning the whole `AttrDefId`, so we intern just modules and not everything. -#[salsa_macros::interned(debug, no_lifetime)] -pub struct InternedModuleId { - pub loc: ModuleId, -} - #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, salsa_macros::Supertype)] pub enum AttrDefId { - ModuleId(InternedModuleId), + ModuleId(ModuleId), AdtId(AdtId), FunctionId(FunctionId), EnumVariantId(EnumVariantId), @@ -1058,7 +977,7 @@ pub trait HasModule { #[inline] #[doc(alias = "crate")] fn krate(&self, db: &dyn DefDatabase) -> Crate { - self.module(db).krate + self.module(db).krate(db) } } @@ -1162,7 +1081,7 @@ impl HasModule for Macro2Id { impl HasModule for ProcMacroId { #[inline] fn module(&self, db: &dyn DefDatabase) -> ModuleId { - self.lookup(db).container.into() + self.lookup(db).container } } @@ -1235,7 +1154,7 @@ impl HasModule for GenericDefId { impl HasModule for AttrDefId { fn module(&self, db: &dyn DefDatabase) -> ModuleId { match self { - AttrDefId::ModuleId(it) => it.loc(db), + AttrDefId::ModuleId(it) => *it, AttrDefId::AdtId(it) => it.module(db), AttrDefId::FunctionId(it) => it.module(db), AttrDefId::EnumVariantId(it) => it.module(db), |