Unnamed repository; edit this file 'description' to name the repository.
| -rw-r--r-- | crates/hir-def/src/expr_store/lower.rs | 34 | ||||
| -rw-r--r-- | crates/hir-def/src/expr_store/lower/path/tests.rs | 8 | ||||
| -rw-r--r-- | crates/hir-def/src/expr_store/tests/body/block.rs | 2 | ||||
| -rw-r--r-- | crates/hir-def/src/find_path.rs | 66 | ||||
| -rw-r--r-- | crates/hir-def/src/item_tree.rs | 8 | ||||
| -rw-r--r-- | crates/hir-def/src/lib.rs | 114 | ||||
| -rw-r--r-- | crates/hir-def/src/nameres.rs | 32 | ||||
| -rw-r--r-- | crates/hir-def/src/resolver.rs | 4 | ||||
| -rw-r--r-- | crates/hir-def/src/signatures.rs | 9 | ||||
| -rw-r--r-- | crates/hir-def/src/visibility.rs | 30 | ||||
| -rw-r--r-- | crates/hir-ty/src/lower.rs | 30 | ||||
| -rw-r--r-- | crates/hir-ty/src/method_resolution.rs | 47 | ||||
| -rw-r--r-- | crates/hir/src/lib.rs | 4 | ||||
| -rw-r--r-- | crates/hir/src/semantics/child_by_source.rs | 2 | ||||
| -rw-r--r-- | crates/hir/src/source_analyzer.rs | 20 |
15 files changed, 243 insertions, 167 deletions
diff --git a/crates/hir-def/src/expr_store/lower.rs b/crates/hir-def/src/expr_store/lower.rs index f3cf2f7d81..5cbcfe5f23 100644 --- a/crates/hir-def/src/expr_store/lower.rs +++ b/crates/hir-def/src/expr_store/lower.rs @@ -35,8 +35,9 @@ use thin_vec::ThinVec; use tt::TextRange; use crate::{ - AdtId, BlockId, BlockLoc, ConstId, DefWithBodyId, FunctionId, GenericDefId, ImplId, - ItemContainerId, MacroId, ModuleDefId, ModuleId, TraitId, TypeAliasId, UnresolvedMacro, + AdtId, BlockId, BlockIdLt, ConstId, DefWithBodyId, FunctionId, GenericDefId, ImplId, + ItemContainerId, LoweringMode, MacroId, ModuleDefId, ModuleId, TraitId, TypeAliasId, + UnresolvedMacro, attrs::AttrFlags, expr_store::{ Body, BodySourceMap, ExprPtr, ExprRoot, ExpressionStore, ExpressionStoreBuilder, @@ -85,7 +86,7 @@ pub(super) fn lower_body( let mut self_param = None; let mut source_map_self_param = None; let mut params = vec![]; - let mut collector = ExprCollector::new(db, module, current_file_id); + let mut collector = ExprCollector::new(db, module, current_file_id, LoweringMode::Analysis); let skip_body = AttrFlags::query( db, @@ -203,7 +204,8 @@ pub(crate) fn lower_type_ref( module: ModuleId, type_ref: InFile<Option<ast::Type>>, ) -> (ExpressionStore, ExpressionStoreSourceMap, TypeRefId) { - let mut expr_collector = ExprCollector::new(db, module, type_ref.file_id); + let mut expr_collector = + ExprCollector::new(db, module, type_ref.file_id, LoweringMode::Analysis); let type_ref = expr_collector.lower_type_ref_opt(type_ref.value, &mut ExprCollector::impl_trait_allocator); let (store, source_map) = expr_collector.store.finish(); @@ -217,8 +219,9 @@ pub fn lower_generic_params( file_id: HirFileId, param_list: Option<ast::GenericParamList>, where_clause: Option<ast::WhereClause>, + mode: LoweringMode, ) -> (ExpressionStore, GenericParams, ExpressionStoreSourceMap) { - let mut expr_collector = ExprCollector::new(db, module, file_id); + let mut expr_collector = ExprCollector::new(db, module, file_id, mode); let mut collector = generics::GenericParamsCollector::new(def); collector.lower(&mut expr_collector, param_list, where_clause); let params = collector.finish(); @@ -232,7 +235,8 @@ pub(crate) fn lower_impl( impl_syntax: InFile<ast::Impl>, impl_id: ImplId, ) -> (ExpressionStore, ExpressionStoreSourceMap, TypeRefId, Option<TraitRef>, GenericParams) { - let mut expr_collector = ExprCollector::new(db, module, impl_syntax.file_id); + let mut expr_collector = + ExprCollector::new(db, module, impl_syntax.file_id, LoweringMode::Analysis); let self_ty = expr_collector.lower_type_ref_opt_disallow_impl_trait(impl_syntax.value.self_ty()); let trait_ = impl_syntax.value.trait_().and_then(|it| match &it { @@ -260,7 +264,8 @@ pub(crate) fn lower_trait( trait_syntax: InFile<ast::Trait>, trait_id: TraitId, ) -> (ExpressionStore, ExpressionStoreSourceMap, GenericParams) { - let mut expr_collector = ExprCollector::new(db, module, trait_syntax.file_id); + let mut expr_collector = + ExprCollector::new(db, module, trait_syntax.file_id, LoweringMode::Analysis); let mut collector = generics::GenericParamsCollector::with_self_param( &mut expr_collector, trait_id.into(), @@ -283,7 +288,7 @@ pub(crate) fn lower_type_alias( type_alias_id: TypeAliasId, ) -> (ExpressionStore, ExpressionStoreSourceMap, GenericParams, Box<[TypeBound]>, Option<TypeRefId>) { - let mut expr_collector = ExprCollector::new(db, module, alias.file_id); + let mut expr_collector = ExprCollector::new(db, module, alias.file_id, LoweringMode::Analysis); let bounds = alias .value .type_bound_list() @@ -325,7 +330,7 @@ pub(crate) fn lower_function( bool, bool, ) { - let mut expr_collector = ExprCollector::new(db, module, fn_.file_id); + let mut expr_collector = ExprCollector::new(db, module, fn_.file_id, LoweringMode::Analysis); let mut collector = generics::GenericParamsCollector::new(function_id.into()); collector.lower(&mut expr_collector, fn_.value.generic_param_list(), fn_.value.where_clause()); let mut params = vec![]; @@ -449,6 +454,7 @@ pub struct ExprCollector<'db> { def_map: &'db DefMap, local_def_map: &'db LocalDefMap, module: ModuleId, + lowering_mode: LoweringMode, lang_items: OnceCell<&'db LangItems>, pub store: ExpressionStoreBuilder, pub named_lifetime_store: NamedLifetimeStore, @@ -605,6 +611,7 @@ impl<'db> ExprCollector<'db> { db: &dyn SourceDatabase, module: ModuleId, current_file_id: HirFileId, + lowering_mode: LoweringMode, ) -> ExprCollector<'_> { let (def_map, local_def_map) = module.local_def_map(db); let expander = Expander::new(db, current_file_id, def_map); @@ -613,6 +620,7 @@ impl<'db> ExprCollector<'db> { db, cfg_options: krate.cfg_options(db), module, + lowering_mode, def_map, local_def_map, lang_items: OnceCell::new(), @@ -2595,10 +2603,12 @@ impl<'db> ExprCollector<'db> { block: ast::BlockExpr, mk_block: impl FnOnce(&mut Self, Option<BlockId>, Box<[Statement]>, Option<ExprId>) -> Expr, ) -> ExprId { - let block_id = self.expander.ast_id_map().ast_id_for_block(&block).map(|file_local_id| { + let block_id = (|| { + let token = self.lowering_mode.allow_tracked_structs()?; + let file_local_id = self.expander.ast_id_map().ast_id_for_block(&block)?; let ast_id = self.expander.in_file(file_local_id); - BlockId::new(self.db, BlockLoc { ast_id, module: self.module }) - }); + Some(unsafe { BlockIdLt::new(self.db, ast_id, self.module, token).to_static() }) + })(); let (module, def_map) = match block_id.map(|block_id| (block_def_map(self.db, block_id), block_id)) { diff --git a/crates/hir-def/src/expr_store/lower/path/tests.rs b/crates/hir-def/src/expr_store/lower/path/tests.rs index f507841a91..b1d0ebb97d 100644 --- a/crates/hir-def/src/expr_store/lower/path/tests.rs +++ b/crates/hir-def/src/expr_store/lower/path/tests.rs @@ -20,8 +20,12 @@ use crate::{ fn lower_path(path: ast::Path) -> (TestDB, ExpressionStore, Option<Path>) { let (db, file_id) = TestDB::with_single_file(""); let krate = db.fetch_test_crate(); - let mut ctx = - ExprCollector::new(&db, crate_def_map(&db, krate).root_module_id(), file_id.into()); + let mut ctx = ExprCollector::new( + &db, + crate_def_map(&db, krate).root_module_id(), + file_id.into(), + crate::LoweringMode::Analysis, + ); let lowered_path = ctx.lower_path(path, &mut ExprCollector::impl_trait_allocator); let (store, _) = ctx.store.finish(); (db, store, lowered_path) diff --git a/crates/hir-def/src/expr_store/tests/body/block.rs b/crates/hir-def/src/expr_store/tests/body/block.rs index f02e0f349b..a39a00b7a7 100644 --- a/crates/hir-def/src/expr_store/tests/body/block.rs +++ b/crates/hir-def/src/expr_store/tests/body/block.rs @@ -196,7 +196,7 @@ fn f() { ), block: Some( BlockId( - 3c01, + Id(3c01), ), ), containing_module_inside_def_map: None, diff --git a/crates/hir-def/src/find_path.rs b/crates/hir-def/src/find_path.rs index 82ddaff189..f6bef86933 100644 --- a/crates/hir-def/src/find_path.rs +++ b/crates/hir-def/src/find_path.rs @@ -12,7 +12,7 @@ use intern::sym; use rustc_hash::FxHashSet; use crate::{ - ModuleDefId, ModuleId, + ModuleDefId, ModuleIdLt, import_map::ImportMap, item_scope::ItemInNs, nameres::DefMap, @@ -38,7 +38,7 @@ pub struct FindPathConfig { pub fn find_path( db: &dyn SourceDatabase, item: ItemInNs, - from: ModuleId, + from: ModuleIdLt<'_>, mut prefix_kind: PrefixKind, ignore_local_imports: bool, mut cfg: FindPathConfig, @@ -118,14 +118,14 @@ struct FindPathCtx<'db> { cfg: FindPathConfig, ignore_local_imports: bool, is_std_item: bool, - from: ModuleId, + from: ModuleIdLt<'db>, from_crate: Crate, - crate_root: ModuleId, + crate_root: ModuleIdLt<'db>, from_def_map: &'db DefMap, fuel: Cell<usize>, } -/// Attempts to find a path to refer to the given `item` visible from the `from` ModuleId +/// Attempts to find a path to refer to the given `item` visible from the `from` ModuleIdLt<'_> fn find_path_inner(ctx: &FindPathCtx<'_>, item: ItemInNs, max_len: usize) -> Option<ModPath> { // - if the item is a module, jump straight to module search if !ctx.is_std_item @@ -171,10 +171,10 @@ fn find_path_inner(ctx: &FindPathCtx<'_>, item: ItemInNs, max_len: usize) -> Opt } #[tracing::instrument(skip_all)] -fn find_path_for_module( - ctx: &FindPathCtx<'_>, - visited_modules: &mut FxHashSet<(ItemInNs, ModuleId)>, - module_id: ModuleId, +fn find_path_for_module<'db>( + ctx: &'db FindPathCtx<'db>, + visited_modules: &mut FxHashSet<(ItemInNs, ModuleIdLt<'db>)>, + module_id: ModuleIdLt<'db>, maybe_extern: bool, max_len: usize, ) -> Option<Choice> { @@ -231,7 +231,7 @@ fn find_path_for_module( ctx.db, ctx.from_def_map, ctx.from, - ItemInNs::Types(module_id.into()), + ItemInNs::Types(unsafe { module_id.to_static() }.into()), ctx.ignore_local_imports, ); if let Some(scope_name) = scope_name { @@ -253,7 +253,7 @@ fn find_path_for_module( } // - if the module is in the prelude, return it by that path - let item = ItemInNs::Types(module_id.into()); + let item = ItemInNs::Types(unsafe { module_id.to_static() }.into()); if let Some(choice) = find_in_prelude(ctx.db, ctx.from_def_map, item, ctx.from) { return Some(choice); } @@ -266,10 +266,10 @@ fn find_path_for_module( best_choice } -fn find_in_scope( - db: &dyn SourceDatabase, +fn find_in_scope<'db>( + db: &'db dyn SourceDatabase, def_map: &DefMap, - from: ModuleId, + from: ModuleIdLt<'db>, item: ItemInNs, ignore_local_imports: bool, ) -> Option<Name> { @@ -287,7 +287,7 @@ fn find_in_prelude( db: &dyn SourceDatabase, local_def_map: &DefMap, item: ItemInNs, - from: ModuleId, + from: ModuleIdLt<'_>, ) -> Option<Choice> { let (prelude_module, _) = local_def_map.prelude()?; let prelude_def_map = prelude_module.def_map(db); @@ -319,8 +319,8 @@ fn find_in_prelude( fn is_kw_kind_relative_to_from( db: &dyn SourceDatabase, def_map: &DefMap, - item: ModuleId, - from: ModuleId, + item: ModuleIdLt<'_>, + from: ModuleIdLt<'_>, ) -> Option<PathKind> { if item.krate(db) != from.krate(db) || item.block(db).is_some() || from.block(db).is_some() { return None; @@ -341,9 +341,9 @@ fn is_kw_kind_relative_to_from( } #[tracing::instrument(skip_all)] -fn calculate_best_path( - ctx: &FindPathCtx<'_>, - visited_modules: &mut FxHashSet<(ItemInNs, ModuleId)>, +fn calculate_best_path<'db>( + ctx: &'db FindPathCtx<'db>, + visited_modules: &mut FxHashSet<(ItemInNs, ModuleIdLt<'db>)>, item: ItemInNs, max_len: usize, best_choice: &mut Option<Choice>, @@ -381,9 +381,9 @@ fn calculate_best_path( } } -fn find_in_sysroot( - ctx: &FindPathCtx<'_>, - visited_modules: &mut FxHashSet<(ItemInNs, ModuleId)>, +fn find_in_sysroot<'db>( + ctx: &'db FindPathCtx<'db>, + visited_modules: &mut FxHashSet<(ItemInNs, ModuleIdLt<'db>)>, item: ItemInNs, max_len: usize, best_choice: &mut Option<Choice>, @@ -427,9 +427,9 @@ fn find_in_sysroot( }); } -fn find_in_dep( - ctx: &FindPathCtx<'_>, - visited_modules: &mut FxHashSet<(ItemInNs, ModuleId)>, +fn find_in_dep<'db>( + ctx: &'db FindPathCtx<'db>, + visited_modules: &mut FxHashSet<(ItemInNs, ModuleIdLt<'db>)>, item: ItemInNs, max_len: usize, best_choice: &mut Option<Choice>, @@ -464,9 +464,9 @@ fn find_in_dep( } } -fn calculate_best_path_local( - ctx: &FindPathCtx<'_>, - visited_modules: &mut FxHashSet<(ItemInNs, ModuleId)>, +fn calculate_best_path_local<'db>( + ctx: &'db FindPathCtx<'db>, + visited_modules: &mut FxHashSet<(ItemInNs, ModuleIdLt<'db>)>, item: ItemInNs, max_len: usize, best_choice: &mut Option<Choice>, @@ -563,11 +563,11 @@ fn path_kind_len(kind: PathKind) -> usize { } /// Finds locations in `from.krate` from which `item` can be imported by `from`. -fn find_local_import_locations( - ctx: &FindPathCtx<'_>, +fn find_local_import_locations<'db>( + ctx: &'db FindPathCtx<'db>, item: ItemInNs, - visited_modules: &mut FxHashSet<(ItemInNs, ModuleId)>, - mut cb: impl FnMut(&mut FxHashSet<(ItemInNs, ModuleId)>, &Name, ModuleId), + visited_modules: &mut FxHashSet<(ItemInNs, ModuleIdLt<'db>)>, + mut cb: impl FnMut(&mut FxHashSet<(ItemInNs, ModuleIdLt<'db>)>, &Name, ModuleIdLt<'db>), ) { let _p = tracing::info_span!("find_local_import_locations").entered(); let db = ctx.db; diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs index 8be44b0828..cb6941aaa4 100644 --- a/crates/hir-def/src/item_tree.rs +++ b/crates/hir-def/src/item_tree.rs @@ -63,7 +63,7 @@ use syntax::{SourceFile, SyntaxKind, ast, match_ast}; use thin_vec::ThinVec; use tt::TextRange; -use crate::{BlockId, Lookup, attrs::parse_extra_crate_attrs}; +use crate::{BlockId, attrs::parse_extra_crate_attrs}; pub(crate) use crate::item_tree::{ attrs::*, @@ -204,10 +204,10 @@ pub(crate) fn block_item_tree_query( krate: Crate, ) -> ItemTree { let _p = tracing::info_span!("block_item_tree_query", ?block).entered(); - let loc = block.lookup(db); - let block = loc.ast_id.to_node(db); + let ast_id = block.ast_id(db); + let block = ast_id.to_node(db); - let ctx = lower::Ctx::new(db, loc.ast_id.file_id, krate); + let ctx = lower::Ctx::new(db, ast_id.file_id, krate); let mut item_tree = ctx.lower_block(&block); item_tree.shrink_to_fit(); item_tree diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs index fa7cb525bb..8b93fe5e2f 100644 --- a/crates/hir-def/src/lib.rs +++ b/crates/hir-def/src/lib.rs @@ -50,7 +50,10 @@ mod macro_expansion_tests; #[cfg(test)] mod test_db; -use std::hash::{Hash, Hasher}; +use std::{ + fmt, + hash::{Hash, Hasher}, +}; use base_db::{Crate, SourceDatabase, impl_intern_key}; use hir_expand::{ @@ -462,13 +465,74 @@ pub struct ProcMacroLoc { impl_intern!(ProcMacroId, ProcMacroLoc); impl_loc!(ProcMacroLoc, id: Fn, container: ModuleId); -#[derive(Debug, Hash, PartialEq, Eq, Clone)] -pub struct BlockLoc { +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, salsa::Update)] +pub enum LoweringMode { + Analysis, + Ide, +} + +pub use self::tracked_struct_token::TrackedStructToken; +mod tracked_struct_token { + use super::LoweringMode; + + /// A token that is required to construct tracked structs. + /// This exists to prevent one from accidentally creating a tracked struct outside of a query which may happen for some codepaths. + pub struct TrackedStructToken { + // #[non_exhaustive] doesn't work for us here, we want it module focused. + _private: (), + } + + impl LoweringMode { + pub fn allow_tracked_structs(self) -> Option<TrackedStructToken> { + match self { + LoweringMode::Analysis => Some(TrackedStructToken { _private: () }), + LoweringMode::Ide => None, + } + } + } +} + +#[salsa_macros::tracked(constructor = new_)] +#[derive(PartialOrd, Ord)] +pub struct BlockIdLt<'db> { pub ast_id: AstId<ast::BlockExpr>, /// The containing module. - pub module: ModuleId, + pub module: ModuleIdLt<'db>, +} +pub type BlockId = BlockIdLt<'static>; + +impl<'db> fmt::Debug for BlockIdLt<'db> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("BlockId").field(&self.0).finish() + } +} + +impl<'db> BlockIdLt<'db> { + pub fn new( + db: &'db dyn SourceDatabase, + ast_id: AstId<ast::BlockExpr>, + module: ModuleIdLt<'db>, + token: TrackedStructToken, + ) -> Self { + _ = token; + BlockIdLt::new_(db, ast_id, module) + } + + /// # 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 BlockId { + /// # Safety + /// + /// The caller must ensure that the `BlockId` comes from the given database. + pub unsafe fn to_db<'db>(self, _db: &'db dyn SourceDatabase) -> BlockIdLt<'db> { + unsafe { std::mem::transmute(self) } + } } -impl_intern!(BlockId, BlockLoc); #[salsa_macros::tracked(debug)] #[derive(PartialOrd, Ord)] @@ -478,7 +542,7 @@ pub struct ModuleIdLt<'db> { /// 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`. - pub block: Option<BlockId>, + pub block: Option<BlockIdLt<'db>>, /// The parent module of this module, or `None` if this is the root module inside the def /// map (including for block def maps). pub containing_module_inside_def_map: Option<ModuleIdLt<'db>>, @@ -487,30 +551,25 @@ pub struct ModuleIdLt<'db> { } pub type ModuleId = ModuleIdLt<'static>; -impl ModuleIdLt<'_> { +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) } } -} -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 SourceDatabase) -> ModuleIdLt<'db> { - unsafe { std::mem::transmute(self) } - } - pub fn def_map(self, db: &dyn SourceDatabase) -> &DefMap { + pub fn def_map(self, db: &'db dyn SourceDatabase) -> &'db DefMap { match self.block(db) { Some(block) => block_def_map(db, block), None => crate_def_map(db, self.krate(db)), } } - pub(crate) fn local_def_map(self, db: &dyn SourceDatabase) -> (&DefMap, &LocalDefMap) { + pub(crate) fn local_def_map( + self, + db: &'db dyn SourceDatabase, + ) -> (&'db DefMap, &'db LocalDefMap) { match self.block(db) { Some(block) => (block_def_map(db, block), self.only_local_def_map(db)), None => { @@ -520,11 +579,11 @@ impl ModuleId { } } - pub(crate) fn only_local_def_map(self, db: &dyn SourceDatabase) -> &LocalDefMap { + pub(crate) fn only_local_def_map(self, db: &'db dyn SourceDatabase) -> &'db LocalDefMap { crate_local_def_map(db, self.krate(db)).local(db) } - pub fn crate_def_map(self, db: &dyn SourceDatabase) -> &DefMap { + pub fn crate_def_map(self, db: &'db dyn SourceDatabase) -> &'db DefMap { crate_def_map(db, self.krate(db)) } @@ -535,13 +594,9 @@ impl ModuleId { /// 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 SourceDatabase) -> Option<ModuleId> { + pub fn containing_module(self, db: &'db dyn SourceDatabase) -> Option<ModuleIdLt<'db>> { self.containing_module_inside_def_map(db) - .or_else(|| self.block(db).map(|block| block.loc(db).module)) - .map(|module| { - // SAFETY: Not sure. - unsafe { module.to_static() } - }) + .or_else(|| self.block(db).map(|block| block.module(db))) } pub fn is_block_module(self, db: &dyn SourceDatabase) -> bool { @@ -549,6 +604,15 @@ impl ModuleId { } } +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 SourceDatabase) -> ModuleIdLt<'db> { + unsafe { std::mem::transmute(self) } + } +} + impl HasModule for ModuleId { #[inline] fn module(&self, _db: &dyn SourceDatabase) -> ModuleId { diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs index 00d0698672..4b7856e0c1 100644 --- a/crates/hir-def/src/nameres.rs +++ b/crates/hir-def/src/nameres.rs @@ -76,7 +76,7 @@ use triomphe::Arc; use tt::TextRange; use crate::{ - AstId, BlockId, BlockLoc, BuiltinDeriveImplId, ExternCrateId, FunctionId, FxIndexMap, Lookup, + AstId, BlockId, BlockIdLt, BuiltinDeriveImplId, ExternCrateId, FunctionId, FxIndexMap, Lookup, MacroCallStyles, MacroExpander, MacroId, ModuleId, ModuleIdLt, ProcMacroId, UseId, item_scope::{BuiltinShadowMode, ItemScope}, item_tree::TreeId, @@ -272,12 +272,12 @@ struct BlockInfo { parent: ModuleId, } -impl std::ops::Index<ModuleId> for DefMap { +impl std::ops::Index<ModuleIdLt<'_>> for DefMap { type Output = ModuleData; - fn index(&self, id: ModuleId) -> &ModuleData { + fn index(&self, id: ModuleIdLt<'_>) -> &ModuleData { self.modules - .get(&id) + .get(&unsafe { id.to_static() }) .unwrap_or_else(|| panic!("ModuleId not found in ModulesMap {:#?}: {id:#?}", self.root)) } } @@ -425,8 +425,10 @@ pub(crate) fn crate_local_def_map(db: &dyn SourceDatabase, crate_id: Crate) -> D } #[salsa_macros::tracked(returns(ref))] -pub fn block_def_map(db: &dyn SourceDatabase, block_id: BlockId) -> DefMap { - let BlockLoc { ast_id, module } = *block_id.lookup(db); +pub fn block_def_map<'db>(db: &'db dyn SourceDatabase, block_id: BlockIdLt<'db>) -> DefMap { + let block_id = unsafe { block_id.to_static() }; + let ast_id = block_id.ast_id(db); + let module = unsafe { block_id.module(db).to_static() }; let visibility = Visibility::Module(module, VisibilityExplicitness::Implicit); let module_data = @@ -614,7 +616,7 @@ impl DefMap { /// Returns the module containing `local_mod`, either the parent `mod`, or the module (or block) containing /// the block, if `self` corresponds to a block expression. - pub fn containing_module(&self, local_mod: ModuleId) -> Option<ModuleId> { + pub fn containing_module(&self, local_mod: ModuleIdLt<'_>) -> Option<ModuleId> { match self[local_mod].parent { Some(parent) => Some(parent), None => self.block.map(|BlockInfo { parent, .. }| parent), @@ -725,11 +727,11 @@ impl DefMap { /// /// If `f` returns `Some(val)`, iteration is stopped and `Some(val)` is returned. If `f` returns /// `None`, iteration continues. - pub(crate) fn with_ancestor_maps<T>( + pub(crate) fn with_ancestor_maps<'db, T>( &self, - db: &dyn SourceDatabase, - local_mod: ModuleId, - f: &mut dyn FnMut(&DefMap, ModuleId) -> Option<T>, + db: &'db dyn SourceDatabase, + local_mod: ModuleIdLt<'db>, + f: &mut dyn FnMut(&DefMap, ModuleIdLt<'db>) -> Option<T>, ) -> Option<T> { if let Some(it) = f(self, local_mod) { return Some(it); @@ -916,11 +918,13 @@ impl DerefMut for ModulesMap { } } -impl Index<ModuleId> for ModulesMap { +impl Index<ModuleIdLt<'_>> for ModulesMap { type Output = ModuleData; - fn index(&self, id: ModuleId) -> &ModuleData { - self.inner.get(&id).unwrap_or_else(|| panic!("ModuleId not found in ModulesMap: {id:#?}")) + fn index(&self, id: ModuleIdLt<'_>) -> &ModuleData { + self.inner + .get(&unsafe { id.to_static() }) + .unwrap_or_else(|| panic!("ModuleId not found in ModulesMap: {id:#?}")) } } diff --git a/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs index b159b0142a..fc639133d4 100644 --- a/crates/hir-def/src/resolver.rs +++ b/crates/hir-def/src/resolver.rs @@ -901,7 +901,7 @@ impl<'db> Resolver<'db> { resolver.scopes.push(Scope::ExprScope(ExprScope { owner, expr_scopes, scope_id })); if let Some(block) = expr_scopes.block(scope_id) { let def_map = block_def_map(db, block); - let local_def_map = block.lookup(db).module.only_local_def_map(db); + let local_def_map = block.module(db).only_local_def_map(db); resolver.scopes.push(Scope::BlockScope(ModuleItemMap { def_map, local_def_map, @@ -1107,7 +1107,7 @@ fn resolver_for_scope_<'db>( for scope in scope_chain.into_iter().rev() { if let Some(block) = scopes.block(scope) { let def_map = block_def_map(db, block); - let local_def_map = block.lookup(db).module.only_local_def_map(db); + let local_def_map = block.module(db).only_local_def_map(db); // Using `DefMap::ROOT` is okay here since inside modules other than the root, // there can't directly be expressions. r = r.push_block_scope(def_map, local_def_map, def_map.root); diff --git a/crates/hir-def/src/signatures.rs b/crates/hir-def/src/signatures.rs index 9126105530..10a38ec71e 100644 --- a/crates/hir-def/src/signatures.rs +++ b/crates/hir-def/src/signatures.rs @@ -21,8 +21,8 @@ use triomphe::Arc; use crate::{ ConstId, EnumId, EnumVariantId, EnumVariantLoc, ExternBlockId, FunctionId, FxIndexMap, - HasModule, ImplId, ItemContainerId, ModuleId, StaticId, StructId, TraitId, TypeAliasId, - UnionId, VariantId, + HasModule, ImplId, ItemContainerId, LoweringMode, ModuleId, StaticId, StructId, TraitId, + TypeAliasId, UnionId, VariantId, attrs::AttrFlags, expr_store::{ Body, ExpressionStore, ExpressionStoreBuilder, ExpressionStoreSourceMap, @@ -117,6 +117,7 @@ impl StructSignature { file_id, source.generic_param_list(), source.where_clause(), + LoweringMode::Analysis, ); ( Arc::new(StructSignature { @@ -190,6 +191,7 @@ impl UnionSignature { file_id, source.generic_param_list(), source.where_clause(), + LoweringMode::Analysis, ); ( Arc::new(UnionSignature { @@ -265,6 +267,7 @@ impl EnumSignature { file_id, source.generic_param_list(), source.where_clause(), + LoweringMode::Analysis, ); ( @@ -987,7 +990,7 @@ fn lower_fields<Field: ast::HasAttrs + ast::HasVisibility>( override_visibility: Option<Option<ast::Visibility>>, ) -> Option<(Arena<FieldData>, ExpressionStore, ExpressionStoreSourceMap)> { let cfg_options = module.krate(db).cfg_options(db); - let mut col = ExprCollector::new(db, module, fields.file_id); + let mut col = ExprCollector::new(db, module, fields.file_id, crate::LoweringMode::Analysis); let override_visibility = override_visibility.map(|vis| { LazyCell::new(|| { let span_map = fields.file_id.span_map(db); diff --git a/crates/hir-def/src/visibility.rs b/crates/hir-def/src/visibility.rs index 632aa1b352..317be3432a 100644 --- a/crates/hir-def/src/visibility.rs +++ b/crates/hir-def/src/visibility.rs @@ -8,8 +8,8 @@ use la_arena::ArenaMap; use syntax::ast::{self, HasVisibility}; use crate::{ - AssocItemId, HasModule, ItemContainerId, LocalFieldId, ModuleId, TraitId, VariantId, - nameres::DefMap, resolver::HasResolver, signatures::VariantFields, src::HasSource, + AssocItemId, HasModule, ItemContainerId, LocalFieldId, ModuleId, ModuleIdLt, TraitId, + VariantId, nameres::DefMap, resolver::HasResolver, signatures::VariantFields, src::HasSource, }; pub use crate::item_tree::{RawVisibility, VisibilityExplicitness}; @@ -40,9 +40,13 @@ impl Visibility { } #[tracing::instrument(skip_all)] - pub fn is_visible_from(self, db: &dyn SourceDatabase, from_module: ModuleId) -> bool { + pub fn is_visible_from<'db>( + self, + db: &'db dyn SourceDatabase, + from_module: ModuleIdLt<'db>, + ) -> bool { let to_module = match self { - Visibility::Module(m, _) => m, + Visibility::Module(m, _) => unsafe { m.to_db(db) }, Visibility::PubCrate(krate) => return from_module.krate(db) == krate, Visibility::Public => return true, }; @@ -58,11 +62,11 @@ impl Visibility { Self::is_visible_from_def_map_(db, def_map, to_module, from_module) } - pub(crate) fn is_visible_from_def_map( + pub(crate) fn is_visible_from_def_map<'db>( self, - db: &dyn SourceDatabase, - def_map: &DefMap, - from_module: ModuleId, + db: &'db dyn SourceDatabase, + def_map: &'db DefMap, + from_module: ModuleIdLt<'db>, ) -> bool { if cfg!(debug_assertions) { _ = def_map.modules[from_module]; @@ -88,11 +92,11 @@ impl Visibility { Self::is_visible_from_def_map_(db, def_map, to_module, from_module) } - fn is_visible_from_def_map_( - db: &dyn SourceDatabase, - def_map: &DefMap, - mut to_module: ModuleId, - mut from_module: ModuleId, + fn is_visible_from_def_map_<'db>( + db: &'db dyn SourceDatabase, + def_map: &'db DefMap, + mut to_module: ModuleIdLt<'db>, + mut from_module: ModuleIdLt<'db>, ) -> bool { debug_assert_eq!(to_module.krate(db), def_map.krate()); // `to_module` might be the root module of a block expression. Those have the same diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index 656d39e5ad..e251fa84ed 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -55,6 +55,9 @@ use stdx::{impl_from, never}; use thin_vec::ThinVec; use tracing::debug; +pub use hir_def::LoweringMode; +pub(crate) use hir_def::TrackedStructToken; + use crate::{ ImplTraitId, Span, TyLoweringDiagnostic, consteval::{create_anon_const, path_to_const}, @@ -201,33 +204,6 @@ pub trait TyLoweringInferVarsCtx<'db> { } } -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum LoweringMode { - Analysis, - Ide, -} - -pub(crate) use self::tracked_struct_token::TrackedStructToken; -mod tracked_struct_token { - use super::LoweringMode; - - /// A token that is required to construct tracked structs. - /// This exists to prevent one from accidentally creating a tracked struct outside of a query which may happen for some codepaths. - pub(crate) struct TrackedStructToken { - // #[non_exhaustive] doesn't work for us here, we want it module focused. - _private: (), - } - - impl LoweringMode { - pub(crate) fn allow_tracked_structs(self) -> Option<TrackedStructToken> { - match self { - LoweringMode::Analysis => Some(TrackedStructToken { _private: () }), - LoweringMode::Ide => None, - } - } - } -} - pub struct TyLoweringContext<'db, 'a> { pub db: &'db dyn HirDatabase, pub(crate) interner: DbInterner<'db>, diff --git a/crates/hir-ty/src/method_resolution.rs b/crates/hir-ty/src/method_resolution.rs index bdfa6ab87a..c5868ab6b5 100644 --- a/crates/hir-ty/src/method_resolution.rs +++ b/crates/hir-ty/src/method_resolution.rs @@ -16,7 +16,7 @@ use tracing::{debug, instrument}; use base_db::Crate; use hir_def::{ - AssocItemId, BlockId, BuiltinDeriveImplId, ConstId, FunctionId, GenericParamId, HasModule, + AssocItemId, BlockIdLt, BuiltinDeriveImplId, ConstId, FunctionId, GenericParamId, HasModule, ImplId, ItemContainerId, ModuleId, TraitId, attrs::AttrFlags, builtin_derive::BuiltinDeriveImplMethod, @@ -562,9 +562,9 @@ pub struct InherentImpls { } #[salsa::tracked] -impl InherentImpls { +impl<'db> InherentImpls { #[salsa::tracked(returns(ref))] - pub fn for_crate(db: &dyn HirDatabase, krate: Crate) -> Self { + pub fn for_crate(db: &'db dyn HirDatabase, krate: Crate) -> Self { let _p = tracing::info_span!("inherent_impls_in_crate_query", ?krate).entered(); let crate_def_map = crate_def_map(db, krate); @@ -573,7 +573,7 @@ impl InherentImpls { } #[salsa::tracked(returns(ref))] - pub fn for_block(db: &dyn HirDatabase, block: BlockId) -> Option<Box<Self>> { + pub fn for_block(db: &'db dyn HirDatabase, block: BlockIdLt<'db>) -> Option<Box<Self>> { let _p = tracing::info_span!("inherent_impls_in_block_query").entered(); let block_def_map = block_def_map(db, block); @@ -626,13 +626,13 @@ impl InherentImpls { self.map.get(self_ty).map(|it| &**it).unwrap_or_default() } - pub fn for_each_crate_and_block( - db: &dyn HirDatabase, + pub fn for_each_crate_and_block<'db>( + db: &'db dyn HirDatabase, krate: Crate, - block: Option<BlockId>, + block: Option<BlockIdLt<'db>>, for_each: &mut dyn FnMut(&InherentImpls), ) { - let blocks = std::iter::successors(block, |block| block.loc(db).module.block(db)); + let blocks = std::iter::successors(block, |block| block.module(db).block(db)); blocks.filter_map(|block| Self::for_block(db, block).as_deref()).for_each(&mut *for_each); for_each(Self::for_crate(db, krate)); } @@ -671,9 +671,9 @@ pub struct TraitImpls { } #[salsa::tracked] -impl TraitImpls { +impl<'db> TraitImpls { #[salsa::tracked(returns(ref))] - pub fn for_crate(db: &dyn HirDatabase, krate: Crate) -> Arc<Self> { + pub fn for_crate(db: &'db dyn HirDatabase, krate: Crate) -> Arc<Self> { let _p = tracing::info_span!("inherent_impls_in_crate_query", ?krate).entered(); let crate_def_map = crate_def_map(db, krate); @@ -682,7 +682,7 @@ impl TraitImpls { } #[salsa::tracked(returns(as_deref))] - pub fn for_block(db: &dyn HirDatabase, block: BlockId) -> Option<Box<Self>> { + pub fn for_block(db: &'db dyn HirDatabase, block: BlockIdLt<'db>) -> Option<Box<Self>> { let _p = tracing::info_span!("inherent_impls_in_block_query").entered(); let block_def_map = block_def_map(db, block); @@ -691,7 +691,7 @@ impl TraitImpls { } #[salsa::tracked(returns(deref))] - pub fn for_crate_and_deps(db: &dyn HirDatabase, krate: Crate) -> Box<[Arc<Self>]> { + pub fn for_crate_and_deps(db: &'db dyn HirDatabase, krate: Crate) -> Box<[Arc<Self>]> { krate.transitive_deps(db).iter().map(|&dep| Self::for_crate(db, dep).clone()).collect() } } @@ -826,23 +826,23 @@ impl TraitImpls { } } - pub fn for_each_crate_and_block( - db: &dyn HirDatabase, + pub fn for_each_crate_and_block<'db>( + db: &'db dyn HirDatabase, krate: Crate, - block: Option<BlockId>, + block: Option<BlockIdLt<'db>>, for_each: &mut dyn FnMut(&TraitImpls), ) { - let blocks = std::iter::successors(block, |block| block.loc(db).module.block(db)); + let blocks = std::iter::successors(block, |block| block.module(db).block(db)); blocks.filter_map(|block| Self::for_block(db, block)).for_each(&mut *for_each); Self::for_crate_and_deps(db, krate).iter().map(|it| &**it).for_each(for_each); } /// Like [`Self::for_each_crate_and_block()`], but takes in account two blocks, one for a trait and one for a self type. - pub fn for_each_crate_and_block_trait_and_type( - db: &dyn HirDatabase, + pub fn for_each_crate_and_block_trait_and_type<'db>( + db: &'db dyn HirDatabase, krate: Crate, - type_block: Option<BlockId>, - trait_block: Option<BlockId>, + type_block: Option<BlockIdLt<'db>>, + trait_block: Option<BlockIdLt<'db>>, for_each: &mut dyn FnMut(&TraitImpls), ) { let in_self_and_deps = TraitImpls::for_crate_and_deps(db, krate); @@ -853,10 +853,11 @@ impl TraitImpls { // that means there can't be duplicate impls; if they meet, we stop the search of the deeper block. // This breaks when they are equal (both will stop immediately), therefore we handle this case // specifically. - let blocks_iter = |block: Option<BlockId>| { - std::iter::successors(block, |block| block.loc(db).module.block(db)) + let blocks_iter = |block: Option<BlockIdLt<'db>>| { + std::iter::successors(block, |block| block.module(db).block(db)) }; - let for_each_block = |current_block: Option<BlockId>, other_block: Option<BlockId>| { + let for_each_block = |current_block: Option<BlockIdLt<'db>>, + other_block: Option<BlockIdLt<'db>>| { blocks_iter(current_block) .take_while(move |&block| { other_block.is_none_or(|other_block| other_block != block) diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 9ff7a7f7da..a9eb487bd4 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -668,7 +668,7 @@ impl Module { while id.is_block_module(db) { id = id.containing_module(db).expect("block without parent module"); } - Module { id } + Module { id: unsafe { id.to_static() } } } pub fn path_to_root(self, db: &dyn HirDatabase) -> Vec<Module> { @@ -4714,7 +4714,7 @@ impl Impl { module.block(db), &mut |impls| extend_with_impls(Either::Left(impls.for_self_ty(&simplified_ty))), ); - iter::successors(module.block(db), |block| block.loc(db).module.block(db)) + std::iter::successors(module.block(db), |block| block.module(db).block(db)) .filter_map(|block| TraitImpls::for_block(db, block)) .for_each(|impls| impls.for_self_ty(&simplified_ty, &mut extend_with_impls)); for &krate in &*all_crates(db) { diff --git a/crates/hir/src/semantics/child_by_source.rs b/crates/hir/src/semantics/child_by_source.rs index bca8c8c503..19aa158131 100644 --- a/crates/hir/src/semantics/child_by_source.rs +++ b/crates/hir/src/semantics/child_by_source.rs @@ -228,7 +228,7 @@ impl ChildBySource for DefWithBodyId { // All block expressions are merged into the same map, because they logically all add // inner items to the containing `DefWithBodyId`. def_map[def_map.root].scope.child_by_source_to(db, res, file_id); - res[keys::BLOCK].insert(block.lookup(db).ast_id.to_ptr(db), block); + res[keys::BLOCK].insert(block.ast_id(db).to_ptr(db), block); } } } diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index 485d525516..db4e92098e 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs @@ -13,7 +13,8 @@ use std::{ use either::Either; use hir_def::{ AdtId, AssocItemId, CallableDefId, ConstId, DefWithBodyId, ExpressionStoreOwnerId, FieldId, - FunctionId, GenericDefId, HasModule, LocalFieldId, ModuleDefId, StructId, VariantId, + FunctionId, GenericDefId, HasModule, LocalFieldId, LoweringMode, ModuleDefId, StructId, + VariantId, expr_store::{ Body, BodySourceMap, ExpressionStore, ExpressionStoreSourceMap, HygieneId, lower::{ExprCollector, lower_generic_params}, @@ -378,8 +379,15 @@ impl<'db> SourceAnalyzer<'db> { }; let generic_def = owner.generic_def(db); let module = generic_def.module(db); - let (store, params, _) = - lower_generic_params(db, module, generic_def, self.file_id, None, Some(where_clause)); + let (store, params, _) = lower_generic_params( + db, + module, + generic_def, + self.file_id, + None, + Some(where_clause), + LoweringMode::Ide, + ); let predicates = params.where_predicates(); if predicates.is_empty() { return PredicateEvaluationResult::holds("predicate does not impose any obligations"); @@ -1275,7 +1283,8 @@ impl<'db> SourceAnalyzer<'db> { } // FIXME: collectiong here shouldnt be necessary? - let mut collector = ExprCollector::new(db, self.resolver.module(), self.file_id); + let mut collector = + ExprCollector::new(db, self.resolver.module(), self.file_id, LoweringMode::Ide); let hir_path = collector.lower_path(path.clone(), &mut ExprCollector::impl_trait_error_allocator)?; let parent_hir_path = path @@ -1480,7 +1489,8 @@ impl<'db> SourceAnalyzer<'db> { db: &dyn HirDatabase, path: &ast::Path, ) -> Option<PathResolutionPerNs> { - let mut collector = ExprCollector::new(db, self.resolver.module(), self.file_id); + let mut collector = + ExprCollector::new(db, self.resolver.module(), self.file_id, LoweringMode::Ide); let hir_path = collector.lower_path(path.clone(), &mut ExprCollector::impl_trait_error_allocator)?; let (store, _) = collector.store.finish(); |