Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/hir-def/src/expr_store/lower.rs34
-rw-r--r--crates/hir-def/src/expr_store/lower/path/tests.rs8
-rw-r--r--crates/hir-def/src/expr_store/tests/body/block.rs2
-rw-r--r--crates/hir-def/src/find_path.rs66
-rw-r--r--crates/hir-def/src/item_tree.rs8
-rw-r--r--crates/hir-def/src/lib.rs114
-rw-r--r--crates/hir-def/src/nameres.rs32
-rw-r--r--crates/hir-def/src/resolver.rs4
-rw-r--r--crates/hir-def/src/signatures.rs9
-rw-r--r--crates/hir-def/src/visibility.rs30
-rw-r--r--crates/hir-ty/src/lower.rs30
-rw-r--r--crates/hir-ty/src/method_resolution.rs47
-rw-r--r--crates/hir/src/lib.rs4
-rw-r--r--crates/hir/src/semantics/child_by_source.rs2
-rw-r--r--crates/hir/src/source_analyzer.rs20
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();