Unnamed repository; edit this file 'description' to name the repository.
Auto merge of #16526 - Veykril:item-loc, r=Veykril
internal: Cleanup 🧹
bors 2024-02-10
parent 0878cde · parent 36fb140 · commit 1c32387
-rw-r--r--crates/hir-def/src/attr.rs3
-rw-r--r--crates/hir-def/src/child_by_source.rs74
-rw-r--r--crates/hir-def/src/data/adt.rs48
-rw-r--r--crates/hir-def/src/generics.rs174
-rw-r--r--crates/hir-def/src/item_tree.rs29
-rw-r--r--crates/hir-def/src/item_tree/lower.rs2
-rw-r--r--crates/hir-def/src/lib.rs405
-rw-r--r--crates/hir-def/src/resolver.rs41
-rw-r--r--crates/hir-def/src/src.rs109
-rw-r--r--crates/hir-def/src/trace.rs2
-rw-r--r--crates/hir-def/src/visibility.rs119
-rw-r--r--crates/ide-diagnostics/src/handlers/private_field.rs26
12 files changed, 552 insertions, 480 deletions
diff --git a/crates/hir-def/src/attr.rs b/crates/hir-def/src/attr.rs
index 85c0542ad3..c91a549726 100644
--- a/crates/hir-def/src/attr.rs
+++ b/crates/hir-def/src/attr.rs
@@ -28,7 +28,8 @@ use crate::{
lang_item::LangItem,
nameres::{ModuleOrigin, ModuleSource},
src::{HasChildSource, HasSource},
- AdtId, AttrDefId, GenericParamId, ItemTreeLoc, LocalFieldId, Lookup, MacroId, VariantId,
+ AdtId, AttrDefId, GenericParamId, HasModule, ItemTreeLoc, LocalFieldId, Lookup, MacroId,
+ VariantId,
};
/// Desugared attributes of an item post `cfg_attr` expansion.
diff --git a/crates/hir-def/src/child_by_source.rs b/crates/hir-def/src/child_by_source.rs
index 5efa3e8d9e..ba7d06272a 100644
--- a/crates/hir-def/src/child_by_source.rs
+++ b/crates/hir-def/src/child_by_source.rs
@@ -6,6 +6,7 @@
use either::Either;
use hir_expand::{attrs::collect_attrs, HirFileId};
+use syntax::ast;
use crate::{
db::DefDatabase,
@@ -17,8 +18,9 @@ use crate::{
item_tree::ItemTreeNode,
nameres::DefMap,
src::{HasChildSource, HasSource},
- AdtId, AssocItemId, DefWithBodyId, EnumId, FieldId, ImplId, ItemTreeLoc, Lookup, MacroId,
- ModuleDefId, ModuleId, TraitId, VariantId,
+ AdtId, AssocItemId, DefWithBodyId, EnumId, FieldId, GenericDefId, ImplId, ItemTreeLoc,
+ LifetimeParamId, Lookup, MacroId, ModuleDefId, ModuleId, TraitId, TypeOrConstParamId,
+ VariantId,
};
pub trait ChildBySource {
@@ -59,14 +61,6 @@ impl ChildBySource for ImplId {
}
}
-fn add_assoc_item(db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId, item: AssocItemId) {
- match item {
- AssocItemId::FunctionId(func) => insert_item_loc(db, res, file_id, func, keys::FUNCTION),
- AssocItemId::ConstId(konst) => insert_item_loc(db, res, file_id, konst, keys::CONST),
- AssocItemId::TypeAliasId(ty) => insert_item_loc(db, res, file_id, ty, keys::TYPE_ALIAS),
- }
-}
-
impl ChildBySource for ModuleId {
fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) {
let def_map = self.def_map(db);
@@ -118,14 +112,6 @@ impl ChildBySource for ItemScope {
file_id: HirFileId,
item: ModuleDefId,
) {
- macro_rules! insert {
- ($map:ident[$key:path].$insert:ident($id:ident)) => {{
- let loc = $id.lookup(db);
- if loc.id.file_id() == file_id {
- $map[$key].$insert(loc.source(db).value, $id)
- }
- }};
- }
match item {
ModuleDefId::FunctionId(id) => {
insert_item_loc(db, map, file_id, id, keys::FUNCTION)
@@ -145,9 +131,13 @@ impl ChildBySource for ItemScope {
AdtId::EnumId(id) => insert_item_loc(db, map, file_id, id, keys::ENUM),
},
ModuleDefId::MacroId(id) => match id {
- MacroId::Macro2Id(id) => insert!(map[keys::MACRO2].insert(id)),
- MacroId::MacroRulesId(id) => insert!(map[keys::MACRO_RULES].insert(id)),
- MacroId::ProcMacroId(id) => insert!(map[keys::PROC_MACRO].insert(id)),
+ MacroId::Macro2Id(id) => insert_item_loc(db, map, file_id, id, keys::MACRO2),
+ MacroId::MacroRulesId(id) => {
+ insert_item_loc(db, map, file_id, id, keys::MACRO_RULES)
+ }
+ MacroId::ProcMacroId(id) => {
+ insert_item_loc(db, map, file_id, id, keys::PROC_MACRO)
+ }
},
ModuleDefId::ModuleId(_)
| ModuleDefId::EnumVariantId(_)
@@ -207,6 +197,40 @@ impl ChildBySource for DefWithBodyId {
}
}
+impl ChildBySource for GenericDefId {
+ fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) {
+ let (gfile_id, generic_params_list) = self.file_id_and_params_of(db);
+ if gfile_id != file_id {
+ return;
+ }
+
+ let generic_params = db.generic_params(*self);
+ let mut toc_idx_iter = generic_params.type_or_consts.iter().map(|(idx, _)| idx);
+ let lts_idx_iter = generic_params.lifetimes.iter().map(|(idx, _)| idx);
+
+ // For traits the first type index is `Self`, skip it.
+ if let GenericDefId::TraitId(_) = *self {
+ toc_idx_iter.next().unwrap(); // advance_by(1);
+ }
+
+ if let Some(generic_params_list) = generic_params_list {
+ for (local_id, ast_param) in
+ toc_idx_iter.zip(generic_params_list.type_or_const_params())
+ {
+ let id = TypeOrConstParamId { parent: *self, local_id };
+ match ast_param {
+ ast::TypeOrConstParam::Type(a) => res[keys::TYPE_PARAM].insert(a, id),
+ ast::TypeOrConstParam::Const(a) => res[keys::CONST_PARAM].insert(a, id),
+ }
+ }
+ for (local_id, ast_param) in lts_idx_iter.zip(generic_params_list.lifetime_params()) {
+ let id = LifetimeParamId { parent: *self, local_id };
+ res[keys::LIFETIME_PARAM].insert(ast_param, id);
+ }
+ }
+ }
+}
+
fn insert_item_loc<ID, N, Data>(
db: &dyn DefDatabase,
res: &mut DynMap,
@@ -224,3 +248,11 @@ fn insert_item_loc<ID, N, Data>(
res[key].insert(loc.source(db).value, id)
}
}
+
+fn add_assoc_item(db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId, item: AssocItemId) {
+ match item {
+ AssocItemId::FunctionId(func) => insert_item_loc(db, res, file_id, func, keys::FUNCTION),
+ AssocItemId::ConstId(konst) => insert_item_loc(db, res, file_id, konst, keys::CONST),
+ AssocItemId::TypeAliasId(ty) => insert_item_loc(db, res, file_id, ty, keys::TYPE_ALIAS),
+ }
+}
diff --git a/crates/hir-def/src/data/adt.rs b/crates/hir-def/src/data/adt.rs
index 5986b7df3d..540f643ae7 100644
--- a/crates/hir-def/src/data/adt.rs
+++ b/crates/hir-def/src/data/adt.rs
@@ -10,7 +10,7 @@ use hir_expand::{
HirFileId, InFile,
};
use intern::Interned;
-use la_arena::{Arena, ArenaMap};
+use la_arena::Arena;
use rustc_abi::{Align, Integer, IntegerType, ReprFlags, ReprOptions};
use syntax::ast::{self, HasName, HasVisibility};
use triomphe::Arc;
@@ -22,13 +22,11 @@ use crate::{
lang_item::LangItem,
lower::LowerCtx,
nameres::diagnostics::{DefDiagnostic, DefDiagnostics},
- src::HasChildSource,
- src::HasSource,
trace::Trace,
tt::{Delimiter, DelimiterKind, Leaf, Subtree, TokenTree},
type_ref::TypeRef,
visibility::RawVisibility,
- EnumId, EnumVariantId, LocalFieldId, LocalModuleId, Lookup, StructId, UnionId, VariantId,
+ EnumId, EnumVariantId, LocalFieldId, LocalModuleId, Lookup, StructId, UnionId,
};
/// Note that we use `StructData` for unions as well!
@@ -387,46 +385,6 @@ impl VariantData {
}
}
-impl HasChildSource<LocalFieldId> for VariantId {
- type Value = Either<ast::TupleField, ast::RecordField>;
-
- fn child_source(&self, db: &dyn DefDatabase) -> InFile<ArenaMap<LocalFieldId, Self::Value>> {
- let item_tree;
- let (src, fields, container) = match *self {
- VariantId::EnumVariantId(it) => {
- let lookup = it.lookup(db);
- item_tree = lookup.id.item_tree(db);
- (
- lookup.source(db).map(|it| it.kind()),
- &item_tree[lookup.id.value].fields,
- lookup.parent.lookup(db).container,
- )
- }
- VariantId::StructId(it) => {
- let lookup = it.lookup(db);
- item_tree = lookup.id.item_tree(db);
- (
- lookup.source(db).map(|it| it.kind()),
- &item_tree[lookup.id.value].fields,
- lookup.container,
- )
- }
- VariantId::UnionId(it) => {
- let lookup = it.lookup(db);
- item_tree = lookup.id.item_tree(db);
- (
- lookup.source(db).map(|it| it.kind()),
- &item_tree[lookup.id.value].fields,
- lookup.container,
- )
- }
- };
- let mut trace = Trace::new_for_map();
- lower_struct(db, &mut trace, &src, container.krate, &item_tree, fields);
- src.with_value(trace.into_map())
- }
-}
-
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum StructKind {
Tuple,
@@ -434,7 +392,7 @@ pub enum StructKind {
Unit,
}
-fn lower_struct(
+pub(crate) fn lower_struct(
db: &dyn DefDatabase,
trace: &mut Trace<FieldData, Either<ast::TupleField, ast::RecordField>>,
ast: &InFile<ast::StructKind>,
diff --git a/crates/hir-def/src/generics.rs b/crates/hir-def/src/generics.rs
index 0edd5e6168..1d2c7c3a55 100644
--- a/crates/hir-def/src/generics.rs
+++ b/crates/hir-def/src/generics.rs
@@ -3,31 +3,27 @@
//! generic parameters. See also the `Generics` type and the `generics_of` query
//! in rustc.
-use base_db::FileId;
use either::Either;
use hir_expand::{
name::{AsName, Name},
- ExpandResult, HirFileId, InFile,
+ ExpandResult,
};
use intern::Interned;
-use la_arena::{Arena, ArenaMap, Idx};
+use la_arena::{Arena, Idx};
use once_cell::unsync::Lazy;
use stdx::impl_from;
use syntax::ast::{self, HasGenericParams, HasName, HasTypeBounds};
use triomphe::Arc;
use crate::{
- child_by_source::ChildBySource,
db::DefDatabase,
- dyn_map::{keys, DynMap},
expander::Expander,
- item_tree::ItemTree,
+ item_tree::{GenericsItemTreeNode, ItemTree},
lower::LowerCtx,
nameres::{DefMap, MacroSubNs},
- src::{HasChildSource, HasSource},
type_ref::{ConstRef, LifetimeRef, TypeBound, TypeRef},
- AdtId, ConstParamId, GenericDefId, HasModule, LifetimeParamId, LocalLifetimeParamId,
- LocalTypeOrConstParamId, Lookup, TypeOrConstParamId, TypeParamId,
+ AdtId, ConstParamId, GenericDefId, HasModule, ItemTreeLoc, LocalTypeOrConstParamId, Lookup,
+ TypeOrConstParamId, TypeParamId,
};
/// Data about a generic type parameter (to a function, struct, impl, ...).
@@ -418,13 +414,18 @@ impl GenericParams {
})
}
};
- macro_rules! id_to_generics {
- ($id:ident) => {{
- let id = $id.lookup(db).id;
- let tree = id.item_tree(db);
- let item = &tree[id.value];
- enabled_params(&item.generic_params, &tree)
- }};
+ fn id_to_generics<Id: GenericsItemTreeNode>(
+ db: &dyn DefDatabase,
+ id: impl for<'db> Lookup<
+ Database<'db> = dyn DefDatabase + 'db,
+ Data = impl ItemTreeLoc<Id = Id>,
+ >,
+ enabled_params: impl Fn(&Interned<GenericParams>, &ItemTree) -> Interned<GenericParams>,
+ ) -> Interned<GenericParams> {
+ let id = id.lookup(db).item_tree_id();
+ let tree = id.item_tree(db);
+ let item = &tree[id.value];
+ enabled_params(item.generic_params(), &tree)
}
match def {
@@ -457,13 +458,13 @@ impl GenericParams {
Interned::new(generic_params.finish())
}
}
- GenericDefId::AdtId(AdtId::StructId(id)) => id_to_generics!(id),
- GenericDefId::AdtId(AdtId::EnumId(id)) => id_to_generics!(id),
- GenericDefId::AdtId(AdtId::UnionId(id)) => id_to_generics!(id),
- GenericDefId::TraitId(id) => id_to_generics!(id),
- GenericDefId::TraitAliasId(id) => id_to_generics!(id),
- GenericDefId::TypeAliasId(id) => id_to_generics!(id),
- GenericDefId::ImplId(id) => id_to_generics!(id),
+ GenericDefId::AdtId(AdtId::StructId(id)) => id_to_generics(db, id, enabled_params),
+ GenericDefId::AdtId(AdtId::EnumId(id)) => id_to_generics(db, id, enabled_params),
+ GenericDefId::AdtId(AdtId::UnionId(id)) => id_to_generics(db, id, enabled_params),
+ GenericDefId::TraitId(id) => id_to_generics(db, id, enabled_params),
+ GenericDefId::TraitAliasId(id) => id_to_generics(db, id, enabled_params),
+ GenericDefId::TypeAliasId(id) => id_to_generics(db, id, enabled_params),
+ GenericDefId::ImplId(id) => id_to_generics(db, id, enabled_params),
GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => {
Interned::new(GenericParams {
type_or_consts: Default::default(),
@@ -507,130 +508,3 @@ impl GenericParams {
})
}
}
-
-fn file_id_and_params_of(
- db: &dyn DefDatabase,
- def: GenericDefId,
-) -> (HirFileId, Option<ast::GenericParamList>) {
- match def {
- GenericDefId::FunctionId(it) => file_id_and_params_of_item_loc(db, it),
- GenericDefId::TypeAliasId(it) => file_id_and_params_of_item_loc(db, it),
- GenericDefId::ConstId(_) => (FileId::BOGUS.into(), None),
- GenericDefId::AdtId(AdtId::StructId(it)) => file_id_and_params_of_item_loc(db, it),
- GenericDefId::AdtId(AdtId::UnionId(it)) => file_id_and_params_of_item_loc(db, it),
- GenericDefId::AdtId(AdtId::EnumId(it)) => file_id_and_params_of_item_loc(db, it),
- GenericDefId::TraitId(it) => file_id_and_params_of_item_loc(db, it),
- GenericDefId::TraitAliasId(it) => file_id_and_params_of_item_loc(db, it),
- GenericDefId::ImplId(it) => file_id_and_params_of_item_loc(db, it),
- // We won't be using this ID anyway
- GenericDefId::EnumVariantId(_) => (FileId::BOGUS.into(), None),
- }
-}
-
-fn file_id_and_params_of_item_loc<Loc>(
- db: &dyn DefDatabase,
- def: impl for<'db> Lookup<Database<'db> = dyn DefDatabase + 'db, Data = Loc>,
-) -> (HirFileId, Option<ast::GenericParamList>)
-where
- Loc: HasSource,
- Loc::Value: HasGenericParams,
-{
- let src = def.lookup(db).source(db);
- (src.file_id, src.value.generic_param_list())
-}
-
-impl HasChildSource<LocalTypeOrConstParamId> for GenericDefId {
- type Value = Either<ast::TypeOrConstParam, ast::TraitOrAlias>;
- fn child_source(
- &self,
- db: &dyn DefDatabase,
- ) -> InFile<ArenaMap<LocalTypeOrConstParamId, Self::Value>> {
- let generic_params = db.generic_params(*self);
- let mut idx_iter = generic_params.type_or_consts.iter().map(|(idx, _)| idx);
-
- let (file_id, generic_params_list) = file_id_and_params_of(db, *self);
-
- let mut params = ArenaMap::default();
-
- // For traits and trait aliases the first type index is `Self`, we need to add it before
- // the other params.
- match *self {
- GenericDefId::TraitId(id) => {
- let trait_ref = id.lookup(db).source(db).value;
- let idx = idx_iter.next().unwrap();
- params.insert(idx, Either::Right(ast::TraitOrAlias::Trait(trait_ref)));
- }
- GenericDefId::TraitAliasId(id) => {
- let alias = id.lookup(db).source(db).value;
- let idx = idx_iter.next().unwrap();
- params.insert(idx, Either::Right(ast::TraitOrAlias::TraitAlias(alias)));
- }
- _ => {}
- }
-
- if let Some(generic_params_list) = generic_params_list {
- for (idx, ast_param) in idx_iter.zip(generic_params_list.type_or_const_params()) {
- params.insert(idx, Either::Left(ast_param));
- }
- }
-
- InFile::new(file_id, params)
- }
-}
-
-impl HasChildSource<LocalLifetimeParamId> for GenericDefId {
- type Value = ast::LifetimeParam;
- fn child_source(
- &self,
- db: &dyn DefDatabase,
- ) -> InFile<ArenaMap<LocalLifetimeParamId, Self::Value>> {
- let generic_params = db.generic_params(*self);
- let idx_iter = generic_params.lifetimes.iter().map(|(idx, _)| idx);
-
- let (file_id, generic_params_list) = file_id_and_params_of(db, *self);
-
- let mut params = ArenaMap::default();
-
- if let Some(generic_params_list) = generic_params_list {
- for (idx, ast_param) in idx_iter.zip(generic_params_list.lifetime_params()) {
- params.insert(idx, ast_param);
- }
- }
-
- InFile::new(file_id, params)
- }
-}
-
-impl ChildBySource for GenericDefId {
- fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) {
- let (gfile_id, generic_params_list) = file_id_and_params_of(db, *self);
- if gfile_id != file_id {
- return;
- }
-
- let generic_params = db.generic_params(*self);
- let mut toc_idx_iter = generic_params.type_or_consts.iter().map(|(idx, _)| idx);
- let lts_idx_iter = generic_params.lifetimes.iter().map(|(idx, _)| idx);
-
- // For traits the first type index is `Self`, skip it.
- if let GenericDefId::TraitId(_) = *self {
- toc_idx_iter.next().unwrap(); // advance_by(1);
- }
-
- if let Some(generic_params_list) = generic_params_list {
- for (local_id, ast_param) in
- toc_idx_iter.zip(generic_params_list.type_or_const_params())
- {
- let id = TypeOrConstParamId { parent: *self, local_id };
- match ast_param {
- ast::TypeOrConstParam::Type(a) => res[keys::TYPE_PARAM].insert(a, id),
- ast::TypeOrConstParam::Const(a) => res[keys::CONST_PARAM].insert(a, id),
- }
- }
- for (local_id, ast_param) in lts_idx_iter.zip(generic_params_list.lifetime_params()) {
- let id = LifetimeParamId { parent: *self, local_id };
- res[keys::LIFETIME_PARAM].insert(ast_param, id);
- }
- }
- }
-}
diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs
index 96b606ec1d..be16a5e31a 100644
--- a/crates/hir-def/src/item_tree.rs
+++ b/crates/hir-def/src/item_tree.rs
@@ -347,6 +347,9 @@ pub trait ItemTreeNode: Clone {
fn lookup(tree: &ItemTree, index: Idx<Self>) -> &Self;
fn attr_owner(id: FileItemTreeId<Self>) -> AttrOwner;
}
+pub trait GenericsItemTreeNode: ItemTreeNode {
+ fn generic_params(&self) -> &Interned<GenericParams>;
+}
pub struct FileItemTreeId<N>(Idx<N>);
@@ -473,7 +476,7 @@ impl<N> Hash for ItemTreeId<N> {
}
macro_rules! mod_items {
- ( $( $typ:ident in $fld:ident -> $ast:ty ),+ $(,)? ) => {
+ ( $( $typ:ident $(<$generic_params:ident>)? in $fld:ident -> $ast:ty ),+ $(,)? ) => {
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum ModItem {
$(
@@ -513,6 +516,14 @@ macro_rules! mod_items {
&self.data().$fld[index]
}
}
+
+ $(
+ impl GenericsItemTreeNode for $typ {
+ fn generic_params(&self) -> &Interned<GenericParams> {
+ &self.$generic_params
+ }
+ }
+ )?
)+
};
}
@@ -521,16 +532,16 @@ mod_items! {
Use in uses -> ast::Use,
ExternCrate in extern_crates -> ast::ExternCrate,
ExternBlock in extern_blocks -> ast::ExternBlock,
- Function in functions -> ast::Fn,
- Struct in structs -> ast::Struct,
- Union in unions -> ast::Union,
- Enum in enums -> ast::Enum,
+ Function<explicit_generic_params> in functions -> ast::Fn,
+ Struct<generic_params> in structs -> ast::Struct,
+ Union<generic_params> in unions -> ast::Union,
+ Enum<generic_params> in enums -> ast::Enum,
Const in consts -> ast::Const,
Static in statics -> ast::Static,
- Trait in traits -> ast::Trait,
- TraitAlias in trait_aliases -> ast::TraitAlias,
- Impl in impls -> ast::Impl,
- TypeAlias in type_aliases -> ast::TypeAlias,
+ Trait<generic_params> in traits -> ast::Trait,
+ TraitAlias<generic_params> in trait_aliases -> ast::TraitAlias,
+ Impl<generic_params> in impls -> ast::Impl,
+ TypeAlias<generic_params> in type_aliases -> ast::TypeAlias,
Mod in mods -> ast::Module,
MacroCall in macro_calls -> ast::MacroCall,
MacroRules in macro_rules -> ast::MacroRules,
diff --git a/crates/hir-def/src/item_tree/lower.rs b/crates/hir-def/src/item_tree/lower.rs
index 1cc8158909..e0aa3ae612 100644
--- a/crates/hir-def/src/item_tree/lower.rs
+++ b/crates/hir-def/src/item_tree/lower.rs
@@ -658,7 +658,7 @@ impl<'a> Ctx<'a> {
fn lower_visibility(&mut self, item: &dyn ast::HasVisibility) -> RawVisibilityId {
let vis =
- RawVisibility::from_ast_with_span_map(self.db, item.visibility(), self.span_map());
+ RawVisibility::from_opt_ast_with_span_map(self.db, item.visibility(), self.span_map());
self.data().vis.alloc(vis)
}
diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs
index df1f61ae5f..589e57cb6b 100644
--- a/crates/hir-def/src/lib.rs
+++ b/crates/hir-def/src/lib.rs
@@ -87,7 +87,7 @@ use hir_expand::{
use item_tree::ExternBlock;
use la_arena::Idx;
use nameres::DefMap;
-use span::Span;
+use span::{FileId, Span};
use stdx::impl_from;
use syntax::{ast, AstNode};
@@ -103,114 +103,6 @@ use crate::{
},
};
-/// A `ModuleId` that is always a crate's root module.
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-pub struct CrateRootModuleId {
- krate: CrateId,
-}
-
-impl CrateRootModuleId {
- pub fn def_map(&self, db: &dyn DefDatabase) -> Arc<DefMap> {
- db.crate_def_map(self.krate)
- }
-
- pub fn krate(self) -> CrateId {
- 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 }
- }
-}
-
-impl From<CrateRootModuleId> for ModuleDefId {
- fn from(value: CrateRootModuleId) -> Self {
- ModuleDefId::ModuleId(value.into())
- }
-}
-
-impl From<CrateId> for CrateRootModuleId {
- fn from(krate: CrateId) -> Self {
- CrateRootModuleId { krate }
- }
-}
-
-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(())
- }
- }
-}
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
-pub struct ModuleId {
- krate: CrateId,
- /// 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,
-}
-
-impl ModuleId {
- pub fn def_map(self, db: &dyn DefDatabase) -> Arc<DefMap> {
- match self.block {
- Some(block) => db.block_def_map(block),
- None => db.crate_def_map(self.krate),
- }
- }
-
- pub fn krate(self) -> CrateId {
- self.krate
- }
-
- pub fn name(self, db: &dyn DefDatabase) -> Option<Name> {
- let def_map = self.def_map(db);
- let parent = def_map[self.local_id].parent?;
- def_map[parent].children.iter().find_map(|(name, module_id)| {
- if *module_id == self.local_id {
- Some(name.clone())
- } else {
- None
- }
- })
- }
-
- 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
- }
-}
-
-/// An ID of a module, **local** to a `DefMap`.
-pub type LocalModuleId = Idx<nameres::ModuleData>;
-
#[derive(Debug)]
pub struct ItemLoc<N: ItemTreeNode> {
pub container: ModuleId,
@@ -323,35 +215,6 @@ impl_intern!(EnumId, EnumLoc, intern_enum, lookup_intern_enum);
impl_loc!(EnumLoc, id: Enum, container: ModuleId);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-pub struct EnumVariantId(salsa::InternId);
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-pub struct EnumVariantLoc {
- pub id: ItemTreeId<Variant>,
- pub parent: EnumId,
- pub index: u32,
-}
-impl_intern!(EnumVariantId, EnumVariantLoc, intern_enum_variant, lookup_intern_enum_variant);
-impl_loc!(EnumVariantLoc, id: Variant, parent: EnumId);
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-pub struct FieldId {
- pub parent: VariantId,
- pub local_id: LocalFieldId,
-}
-
-pub type LocalFieldId = Idx<data::adt::FieldData>;
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-pub struct TupleId(pub u32);
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-pub struct TupleFieldId {
- pub tuple: TupleId,
- pub index: u32,
-}
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ConstId(salsa::InternId);
type ConstLoc = AssocItemLoc<Const>;
impl_intern!(ConstId, ConstLoc, intern_const, lookup_intern_const);
@@ -406,13 +269,16 @@ impl_intern!(ExternBlockId, ExternBlockLoc, intern_extern_block, lookup_intern_e
impl_loc!(ExternBlockLoc, id: ExternBlock, container: ModuleId);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-pub enum MacroExpander {
- Declarative,
- BuiltIn(BuiltinFnLikeExpander),
- BuiltInAttr(BuiltinAttrExpander),
- BuiltInDerive(BuiltinDeriveExpander),
- BuiltInEager(EagerExpander),
+pub struct EnumVariantId(salsa::InternId);
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct EnumVariantLoc {
+ pub id: ItemTreeId<Variant>,
+ pub parent: EnumId,
+ pub index: u32,
}
+impl_intern!(EnumVariantId, EnumVariantLoc, intern_enum_variant, lookup_intern_enum_variant);
+impl_loc!(EnumVariantLoc, id: Variant, parent: EnumId);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
pub struct Macro2Id(salsa::InternId);
@@ -448,6 +314,14 @@ bitflags::bitflags! {
}
}
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub enum MacroExpander {
+ Declarative,
+ BuiltIn(BuiltinFnLikeExpander),
+ BuiltInAttr(BuiltinAttrExpander),
+ BuiltInDerive(BuiltinDeriveExpander),
+ BuiltInEager(EagerExpander),
+}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
pub struct ProcMacroId(salsa::InternId);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -471,6 +345,146 @@ pub struct BlockLoc {
}
impl_intern!(BlockId, BlockLoc, intern_block, lookup_intern_block);
+/// Id of the anonymous const block expression and patterns. This is very similar to `ClosureId` and
+/// shouldn't be a `DefWithBodyId` since its type inference is dependent on its parent.
+#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
+pub struct ConstBlockId(salsa::InternId);
+impl_intern!(ConstBlockId, ConstBlockLoc, intern_anonymous_const, lookup_intern_anonymous_const);
+
+#[derive(Debug, Hash, PartialEq, Eq, Clone)]
+pub struct ConstBlockLoc {
+ /// The parent of the anonymous const block.
+ pub parent: DefWithBodyId,
+ /// The root expression of this const block in the parent body.
+ pub root: hir::ExprId,
+}
+
+/// A `ModuleId` that is always a crate's root module.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct CrateRootModuleId {
+ krate: CrateId,
+}
+
+impl CrateRootModuleId {
+ pub fn def_map(&self, db: &dyn DefDatabase) -> Arc<DefMap> {
+ db.crate_def_map(self.krate)
+ }
+
+ pub fn krate(self) -> CrateId {
+ 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 From<CrateId> for CrateRootModuleId {
+ fn from(krate: CrateId) -> Self {
+ CrateRootModuleId { krate }
+ }
+}
+
+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(())
+ }
+ }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
+pub struct ModuleId {
+ krate: CrateId,
+ /// 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,
+}
+
+impl ModuleId {
+ pub fn def_map(self, db: &dyn DefDatabase) -> Arc<DefMap> {
+ match self.block {
+ Some(block) => db.block_def_map(block),
+ None => db.crate_def_map(self.krate),
+ }
+ }
+
+ pub fn krate(self) -> CrateId {
+ self.krate
+ }
+
+ pub fn name(self, db: &dyn DefDatabase) -> Option<Name> {
+ let def_map = self.def_map(db);
+ let parent = def_map[self.local_id].parent?;
+ def_map[parent].children.iter().find_map(|(name, module_id)| {
+ if *module_id == self.local_id {
+ Some(name.clone())
+ } else {
+ None
+ }
+ })
+ }
+
+ 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
+ }
+}
+
+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 }
+ }
+}
+
+impl From<CrateRootModuleId> for ModuleDefId {
+ fn from(value: CrateRootModuleId) -> Self {
+ ModuleDefId::ModuleId(value.into())
+ }
+}
+
+/// An ID of a module, **local** to a `DefMap`.
+pub type LocalModuleId = Idx<nameres::ModuleData>;
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct FieldId {
+ pub parent: VariantId,
+ pub local_id: LocalFieldId,
+}
+
+pub type LocalFieldId = Idx<data::adt::FieldData>;
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct TupleId(pub u32);
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct TupleFieldId {
+ pub tuple: TupleId,
+ pub index: u32,
+}
+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct TypeOrConstParamId {
pub parent: GenericDefId,
@@ -611,20 +625,6 @@ impl_from!(
for ModuleDefId
);
-/// Id of the anonymous const block expression and patterns. This is very similar to `ClosureId` and
-/// shouldn't be a `DefWithBodyId` since its type inference is dependent on its parent.
-#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
-pub struct ConstBlockId(salsa::InternId);
-impl_intern!(ConstBlockId, ConstBlockLoc, intern_anonymous_const, lookup_intern_anonymous_const);
-
-#[derive(Debug, Hash, PartialEq, Eq, Clone)]
-pub struct ConstBlockLoc {
- /// The parent of the anonymous const block.
- pub parent: DefWithBodyId,
- /// The root expression of this const block in the parent body.
- pub root: hir::ExprId,
-}
-
/// Something that holds types, required for the current const arg lowering implementation as they
/// need to be able to query where they are defined.
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
@@ -892,6 +892,39 @@ impl_from!(
for GenericDefId
);
+impl GenericDefId {
+ fn file_id_and_params_of(
+ self,
+ db: &dyn DefDatabase,
+ ) -> (HirFileId, Option<ast::GenericParamList>) {
+ fn file_id_and_params_of_item_loc<Loc>(
+ db: &dyn DefDatabase,
+ def: impl for<'db> Lookup<Database<'db> = dyn DefDatabase + 'db, Data = Loc>,
+ ) -> (HirFileId, Option<ast::GenericParamList>)
+ where
+ Loc: src::HasSource,
+ Loc::Value: ast::HasGenericParams,
+ {
+ let src = def.lookup(db).source(db);
+ (src.file_id, ast::HasGenericParams::generic_param_list(&src.value))
+ }
+
+ match self {
+ GenericDefId::FunctionId(it) => file_id_and_params_of_item_loc(db, it),
+ GenericDefId::TypeAliasId(it) => file_id_and_params_of_item_loc(db, it),
+ GenericDefId::ConstId(_) => (FileId::BOGUS.into(), None),
+ GenericDefId::AdtId(AdtId::StructId(it)) => file_id_and_params_of_item_loc(db, it),
+ GenericDefId::AdtId(AdtId::UnionId(it)) => file_id_and_params_of_item_loc(db, it),
+ GenericDefId::AdtId(AdtId::EnumId(it)) => file_id_and_params_of_item_loc(db, it),
+ GenericDefId::TraitId(it) => file_id_and_params_of_item_loc(db, it),
+ GenericDefId::TraitAliasId(it) => file_id_and_params_of_item_loc(db, it),
+ GenericDefId::ImplId(it) => file_id_and_params_of_item_loc(db, it),
+ // We won't be using this ID anyway
+ GenericDefId::EnumVariantId(_) => (FileId::BOGUS.into(), None),
+ }
+ }
+}
+
impl From<AssocItemId> for GenericDefId {
fn from(item: AssocItemId) -> Self {
match item {
@@ -1224,6 +1257,34 @@ impl HasModule for GenericDefId {
}
}
+impl HasModule for AttrDefId {
+ fn module(&self, db: &dyn DefDatabase) -> ModuleId {
+ match self {
+ AttrDefId::ModuleId(it) => *it,
+ AttrDefId::FieldId(it) => it.parent.module(db),
+ AttrDefId::AdtId(it) => it.module(db),
+ AttrDefId::FunctionId(it) => it.module(db),
+ AttrDefId::EnumVariantId(it) => it.module(db),
+ AttrDefId::StaticId(it) => it.module(db),
+ AttrDefId::ConstId(it) => it.module(db),
+ AttrDefId::TraitId(it) => it.module(db),
+ AttrDefId::TraitAliasId(it) => it.module(db),
+ AttrDefId::TypeAliasId(it) => it.module(db),
+ AttrDefId::ImplId(it) => it.module(db),
+ AttrDefId::ExternBlockId(it) => it.module(db),
+ AttrDefId::GenericParamId(it) => match it {
+ GenericParamId::TypeParamId(it) => it.parent(),
+ GenericParamId::ConstParamId(it) => it.parent(),
+ GenericParamId::LifetimeParamId(it) => it.parent,
+ }
+ .module(db),
+ AttrDefId::MacroId(it) => it.module(db),
+ AttrDefId::ExternCrateId(it) => it.module(db),
+ AttrDefId::UseId(it) => it.module(db),
+ }
+ }
+}
+
impl ModuleDefId {
/// Returns the module containing `self` (or `self`, if `self` is itself a module).
///
@@ -1245,34 +1306,6 @@ impl ModuleDefId {
}
}
-impl AttrDefId {
- pub fn krate(&self, db: &dyn DefDatabase) -> CrateId {
- match *self {
- AttrDefId::ModuleId(it) => it.krate,
- AttrDefId::FieldId(it) => it.parent.krate(db),
- AttrDefId::AdtId(it) => it.krate(db),
- AttrDefId::FunctionId(it) => it.krate(db),
- AttrDefId::EnumVariantId(it) => it.krate(db),
- AttrDefId::StaticId(it) => it.krate(db),
- AttrDefId::ConstId(it) => it.krate(db),
- AttrDefId::TraitId(it) => it.krate(db),
- AttrDefId::TraitAliasId(it) => it.krate(db),
- AttrDefId::TypeAliasId(it) => it.krate(db),
- AttrDefId::ImplId(it) => it.krate(db),
- AttrDefId::ExternBlockId(it) => it.krate(db),
- AttrDefId::GenericParamId(it) => match it {
- GenericParamId::TypeParamId(it) => it.parent(),
- GenericParamId::ConstParamId(it) => it.parent(),
- GenericParamId::LifetimeParamId(it) => it.parent,
- }
- .krate(db),
- AttrDefId::MacroId(it) => it.krate(db),
- AttrDefId::ExternCrateId(it) => it.krate(db),
- AttrDefId::UseId(it) => it.krate(db),
- }
- }
-}
-
/// A helper trait for converting to MacroCallId
pub trait AsMacroCall {
fn as_call_id(
diff --git a/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs
index 7a9c4ea016..db47d743c5 100644
--- a/crates/hir-def/src/resolver.rs
+++ b/crates/hir-def/src/resolver.rs
@@ -27,9 +27,9 @@ use crate::{
visibility::{RawVisibility, Visibility},
AdtId, ConstId, ConstParamId, CrateRootModuleId, DefWithBodyId, EnumId, EnumVariantId,
ExternBlockId, ExternCrateId, FunctionId, GenericDefId, GenericParamId, HasModule, ImplId,
- ItemContainerId, LifetimeParamId, LocalModuleId, Lookup, Macro2Id, MacroId, MacroRulesId,
- ModuleDefId, ModuleId, ProcMacroId, StaticId, StructId, TraitAliasId, TraitId, TypeAliasId,
- TypeOrConstParamId, TypeOwnerId, TypeParamId, UseId, VariantId,
+ ItemContainerId, ItemTreeLoc, LifetimeParamId, LocalModuleId, Lookup, Macro2Id, MacroId,
+ MacroRulesId, ModuleDefId, ModuleId, ProcMacroId, StaticId, StructId, TraitAliasId, TraitId,
+ TypeAliasId, TypeOrConstParamId, TypeOwnerId, TypeParamId, UseId, VariantId,
};
#[derive(Debug, Clone)]
@@ -248,6 +248,7 @@ impl Resolver {
RawVisibility::Public => Some(Visibility::Public),
}
}
+
pub fn resolve_path_in_value_ns(
&self,
db: &dyn DefDatabase,
@@ -1014,13 +1015,13 @@ impl HasResolver for CrateRootModuleId {
impl HasResolver for TraitId {
fn resolver(self, db: &dyn DefDatabase) -> Resolver {
- self.lookup(db).container.resolver(db).push_generic_params_scope(db, self.into())
+ lookup_resolver(db, self).push_generic_params_scope(db, self.into())
}
}
impl HasResolver for TraitAliasId {
fn resolver(self, db: &dyn DefDatabase) -> Resolver {
- self.lookup(db).container.resolver(db).push_generic_params_scope(db, self.into())
+ lookup_resolver(db, self).push_generic_params_scope(db, self.into())
}
}
@@ -1036,25 +1037,25 @@ impl<T: Into<AdtId> + Copy> HasResolver for T {
impl HasResolver for FunctionId {
fn resolver(self, db: &dyn DefDatabase) -> Resolver {
- self.lookup(db).container.resolver(db).push_generic_params_scope(db, self.into())
+ lookup_resolver(db, self).push_generic_params_scope(db, self.into())
}
}
impl HasResolver for ConstId {
fn resolver(self, db: &dyn DefDatabase) -> Resolver {
- self.lookup(db).container.resolver(db)
+ lookup_resolver(db, self)
}
}
impl HasResolver for StaticId {
fn resolver(self, db: &dyn DefDatabase) -> Resolver {
- self.lookup(db).container.resolver(db)
+ lookup_resolver(db, self)
}
}
impl HasResolver for TypeAliasId {
fn resolver(self, db: &dyn DefDatabase) -> Resolver {
- self.lookup(db).container.resolver(db).push_generic_params_scope(db, self.into())
+ lookup_resolver(db, self).push_generic_params_scope(db, self.into())
}
}
@@ -1071,19 +1072,19 @@ impl HasResolver for ImplId {
impl HasResolver for ExternBlockId {
fn resolver(self, db: &dyn DefDatabase) -> Resolver {
// Same as parent's
- self.lookup(db).container.resolver(db)
+ lookup_resolver(db, self)
}
}
impl HasResolver for ExternCrateId {
fn resolver(self, db: &dyn DefDatabase) -> Resolver {
- self.lookup(db).container.resolver(db)
+ lookup_resolver(db, self)
}
}
impl HasResolver for UseId {
fn resolver(self, db: &dyn DefDatabase) -> Resolver {
- self.lookup(db).container.resolver(db)
+ lookup_resolver(db, self)
}
}
@@ -1170,18 +1171,28 @@ impl HasResolver for MacroId {
impl HasResolver for Macro2Id {
fn resolver(self, db: &dyn DefDatabase) -> Resolver {
- self.lookup(db).container.resolver(db)
+ lookup_resolver(db, self)
}
}
impl HasResolver for ProcMacroId {
fn resolver(self, db: &dyn DefDatabase) -> Resolver {
- self.lookup(db).container.resolver(db)
+ lookup_resolver(db, self)
}
}
impl HasResolver for MacroRulesId {
fn resolver(self, db: &dyn DefDatabase) -> Resolver {
- self.lookup(db).container.resolver(db)
+ lookup_resolver(db, self)
}
}
+
+fn lookup_resolver<'db>(
+ db: &(dyn DefDatabase + 'db),
+ lookup: impl Lookup<
+ Database<'db> = dyn DefDatabase + 'db,
+ Data = impl ItemTreeLoc<Container = impl HasResolver>,
+ >,
+) -> Resolver {
+ lookup.lookup(db).container().resolver(db)
+}
diff --git a/crates/hir-def/src/src.rs b/crates/hir-def/src/src.rs
index d820456b92..4283f003f8 100644
--- a/crates/hir-def/src/src.rs
+++ b/crates/hir-def/src/src.rs
@@ -1,10 +1,15 @@
//! Utilities for mapping between hir IDs and the surface syntax.
+use either::Either;
use hir_expand::InFile;
use la_arena::ArenaMap;
use syntax::ast;
-use crate::{db::DefDatabase, item_tree::ItemTreeNode, ItemTreeLoc, Lookup, UseId};
+use crate::{
+ data::adt::lower_struct, db::DefDatabase, item_tree::ItemTreeNode, trace::Trace, GenericDefId,
+ ItemTreeLoc, LocalFieldId, LocalLifetimeParamId, LocalTypeOrConstParamId, Lookup, UseId,
+ VariantId,
+};
pub trait HasSource {
type Value;
@@ -49,3 +54,105 @@ impl HasChildSource<la_arena::Idx<ast::UseTree>> for UseId {
)
}
}
+
+impl HasChildSource<LocalTypeOrConstParamId> for GenericDefId {
+ type Value = Either<ast::TypeOrConstParam, ast::TraitOrAlias>;
+ fn child_source(
+ &self,
+ db: &dyn DefDatabase,
+ ) -> InFile<ArenaMap<LocalTypeOrConstParamId, Self::Value>> {
+ let generic_params = db.generic_params(*self);
+ let mut idx_iter = generic_params.type_or_consts.iter().map(|(idx, _)| idx);
+
+ let (file_id, generic_params_list) = self.file_id_and_params_of(db);
+
+ let mut params = ArenaMap::default();
+
+ // For traits and trait aliases the first type index is `Self`, we need to add it before
+ // the other params.
+ match *self {
+ GenericDefId::TraitId(id) => {
+ let trait_ref = id.lookup(db).source(db).value;
+ let idx = idx_iter.next().unwrap();
+ params.insert(idx, Either::Right(ast::TraitOrAlias::Trait(trait_ref)));
+ }
+ GenericDefId::TraitAliasId(id) => {
+ let alias = id.lookup(db).source(db).value;
+ let idx = idx_iter.next().unwrap();
+ params.insert(idx, Either::Right(ast::TraitOrAlias::TraitAlias(alias)));
+ }
+ _ => {}
+ }
+
+ if let Some(generic_params_list) = generic_params_list {
+ for (idx, ast_param) in idx_iter.zip(generic_params_list.type_or_const_params()) {
+ params.insert(idx, Either::Left(ast_param));
+ }
+ }
+
+ InFile::new(file_id, params)
+ }
+}
+
+impl HasChildSource<LocalLifetimeParamId> for GenericDefId {
+ type Value = ast::LifetimeParam;
+ fn child_source(
+ &self,
+ db: &dyn DefDatabase,
+ ) -> InFile<ArenaMap<LocalLifetimeParamId, Self::Value>> {
+ let generic_params = db.generic_params(*self);
+ let idx_iter = generic_params.lifetimes.iter().map(|(idx, _)| idx);
+
+ let (file_id, generic_params_list) = self.file_id_and_params_of(db);
+
+ let mut params = ArenaMap::default();
+
+ if let Some(generic_params_list) = generic_params_list {
+ for (idx, ast_param) in idx_iter.zip(generic_params_list.lifetime_params()) {
+ params.insert(idx, ast_param);
+ }
+ }
+
+ InFile::new(file_id, params)
+ }
+}
+
+impl HasChildSource<LocalFieldId> for VariantId {
+ type Value = Either<ast::TupleField, ast::RecordField>;
+
+ fn child_source(&self, db: &dyn DefDatabase) -> InFile<ArenaMap<LocalFieldId, Self::Value>> {
+ let item_tree;
+ let (src, fields, container) = match *self {
+ VariantId::EnumVariantId(it) => {
+ let lookup = it.lookup(db);
+ item_tree = lookup.id.item_tree(db);
+ (
+ lookup.source(db).map(|it| it.kind()),
+ &item_tree[lookup.id.value].fields,
+ lookup.parent.lookup(db).container,
+ )
+ }
+ VariantId::StructId(it) => {
+ let lookup = it.lookup(db);
+ item_tree = lookup.id.item_tree(db);
+ (
+ lookup.source(db).map(|it| it.kind()),
+ &item_tree[lookup.id.value].fields,
+ lookup.container,
+ )
+ }
+ VariantId::UnionId(it) => {
+ let lookup = it.lookup(db);
+ item_tree = lookup.id.item_tree(db);
+ (
+ lookup.source(db).map(|it| it.kind()),
+ &item_tree[lookup.id.value].fields,
+ lookup.container,
+ )
+ }
+ };
+ let mut trace = Trace::new_for_map();
+ lower_struct(db, &mut trace, &src, container.krate, &item_tree, fields);
+ src.with_value(trace.into_map())
+ }
+}
diff --git a/crates/hir-def/src/trace.rs b/crates/hir-def/src/trace.rs
index 04d5b26619..da50ee8dc7 100644
--- a/crates/hir-def/src/trace.rs
+++ b/crates/hir-def/src/trace.rs
@@ -11,6 +11,8 @@
//! projections.
use la_arena::{Arena, ArenaMap, Idx, RawIdx};
+// FIXME: This isn't really used anymore, at least not in a way where it does anything useful.
+// Check if we should get rid of this or make proper use of it instead.
pub(crate) struct Trace<T, V> {
arena: Option<Arena<T>>,
map: Option<ArenaMap<Idx<T>, V>>,
diff --git a/crates/hir-def/src/visibility.rs b/crates/hir-def/src/visibility.rs
index 7ed48237f4..0f3fac1cec 100644
--- a/crates/hir-def/src/visibility.rs
+++ b/crates/hir-def/src/visibility.rs
@@ -37,10 +37,14 @@ impl RawVisibility {
db: &dyn DefDatabase,
node: InFile<Option<ast::Visibility>>,
) -> RawVisibility {
+ let node = match node.transpose() {
+ None => return RawVisibility::private(),
+ Some(node) => node,
+ };
Self::from_ast_with_span_map(db, node.value, db.span_map(node.file_id).as_ref())
}
- pub(crate) fn from_ast_with_span_map(
+ pub(crate) fn from_opt_ast_with_span_map(
db: &dyn DefDatabase,
node: Option<ast::Visibility>,
span_map: SpanMapRef<'_>,
@@ -49,29 +53,28 @@ impl RawVisibility {
None => return RawVisibility::private(),
Some(node) => node,
};
- match node.kind() {
+ Self::from_ast_with_span_map(db, node, span_map)
+ }
+
+ fn from_ast_with_span_map(
+ db: &dyn DefDatabase,
+ node: ast::Visibility,
+ span_map: SpanMapRef<'_>,
+ ) -> RawVisibility {
+ let path = match node.kind() {
ast::VisibilityKind::In(path) => {
let path = ModPath::from_src(db.upcast(), path, span_map);
- let path = match path {
+ match path {
None => return RawVisibility::private(),
Some(path) => path,
- };
- RawVisibility::Module(path, VisibilityExplicitness::Explicit)
- }
- ast::VisibilityKind::PubCrate => {
- let path = ModPath::from_kind(PathKind::Crate);
- RawVisibility::Module(path, VisibilityExplicitness::Explicit)
- }
- ast::VisibilityKind::PubSuper => {
- let path = ModPath::from_kind(PathKind::Super(1));
- RawVisibility::Module(path, VisibilityExplicitness::Explicit)
- }
- ast::VisibilityKind::PubSelf => {
- let path = ModPath::from_kind(PathKind::Super(0));
- RawVisibility::Module(path, VisibilityExplicitness::Explicit)
+ }
}
- ast::VisibilityKind::Pub => RawVisibility::Public,
- }
+ ast::VisibilityKind::PubCrate => ModPath::from_kind(PathKind::Crate),
+ ast::VisibilityKind::PubSuper => ModPath::from_kind(PathKind::Super(1)),
+ ast::VisibilityKind::PubSelf => ModPath::from_kind(PathKind::Super(0)),
+ ast::VisibilityKind::Pub => return RawVisibility::Public,
+ };
+ RawVisibility::Module(path, VisibilityExplicitness::Explicit)
}
pub fn resolve(
@@ -94,6 +97,10 @@ pub enum Visibility {
}
impl Visibility {
+ pub(crate) fn is_visible_from_other_crate(self) -> bool {
+ matches!(self, Visibility::Public)
+ }
+
#[tracing::instrument(skip_all)]
pub fn is_visible_from(self, db: &dyn DefDatabase, from_module: ModuleId) -> bool {
let to_module = match self {
@@ -105,24 +112,33 @@ impl Visibility {
return false;
}
let def_map = from_module.def_map(db);
- self.is_visible_from_def_map(db, &def_map, from_module.local_id)
- }
-
- pub(crate) fn is_visible_from_other_crate(self) -> bool {
- matches!(self, Visibility::Public)
+ Self::is_visible_from_def_map_(db, &def_map, to_module, from_module.local_id)
}
pub(crate) fn is_visible_from_def_map(
self,
db: &dyn DefDatabase,
def_map: &DefMap,
- mut from_module: LocalModuleId,
+ from_module: LocalModuleId,
) -> bool {
- let mut to_module = match self {
+ let to_module = match self {
Visibility::Module(m, _) => m,
Visibility::Public => return true,
};
+ // if they're not in the same crate, it can't be visible
+ if def_map.krate() != to_module.krate {
+ return false;
+ }
+ Self::is_visible_from_def_map_(db, def_map, to_module, from_module)
+ }
+ fn is_visible_from_def_map_(
+ db: &dyn DefDatabase,
+ def_map: &DefMap,
+ mut to_module: ModuleId,
+ mut from_module: LocalModuleId,
+ ) -> bool {
+ debug_assert_eq!(to_module.krate, def_map.krate());
// `to_module` might be the root module of a block expression. Those have the same
// visibility as the containing module (even though no items are directly nameable from
// there, getting this right is important for method resolution).
@@ -130,20 +146,25 @@ impl Visibility {
// Additional complication: `to_module` might be in `from_module`'s `DefMap`, which we're
// currently computing, so we must not call the `def_map` query for it.
- let mut arc;
+ let def_map_block = def_map.block_id();
loop {
- let to_module_def_map =
- if to_module.krate == def_map.krate() && to_module.block == def_map.block_id() {
+ match (to_module.block, def_map_block) {
+ // to_module is not a block, so there is no parent def map to use
+ (None, _) => (),
+ (Some(a), Some(b)) if a == b => {
cov_mark::hit!(is_visible_from_same_block_def_map);
- def_map
- } else {
- arc = to_module.def_map(db);
- &arc
- };
- match to_module_def_map.parent() {
- Some(parent) => to_module = parent,
- None => break,
+ if let Some(parent) = def_map.parent() {
+ to_module = parent;
+ }
+ }
+ _ => {
+ if let Some(parent) = to_module.def_map(db).parent() {
+ to_module = parent;
+ continue;
+ }
+ }
}
+ break;
}
// from_module needs to be a descendant of to_module
@@ -176,30 +197,25 @@ impl Visibility {
/// visible in unrelated modules).
pub(crate) fn max(self, other: Visibility, def_map: &DefMap) -> Option<Visibility> {
match (self, other) {
- (Visibility::Module(_, _) | Visibility::Public, Visibility::Public)
- | (Visibility::Public, Visibility::Module(_, _)) => Some(Visibility::Public),
- (Visibility::Module(mod_a, vis_a), Visibility::Module(mod_b, vis_b)) => {
+ (_, Visibility::Public) | (Visibility::Public, _) => Some(Visibility::Public),
+ (Visibility::Module(mod_a, expl_a), Visibility::Module(mod_b, expl_b)) => {
if mod_a.krate != mod_b.krate {
return None;
}
- let mut a_ancestors = iter::successors(Some(mod_a.local_id), |&m| {
- let parent_id = def_map[m].parent?;
- Some(parent_id)
- });
- let mut b_ancestors = iter::successors(Some(mod_b.local_id), |&m| {
- let parent_id = def_map[m].parent?;
- Some(parent_id)
- });
+ let mut a_ancestors =
+ iter::successors(Some(mod_a.local_id), |&m| def_map[m].parent);
+ let mut b_ancestors =
+ iter::successors(Some(mod_b.local_id), |&m| def_map[m].parent);
if a_ancestors.any(|m| m == mod_b.local_id) {
// B is above A
- return Some(Visibility::Module(mod_b, vis_b));
+ return Some(Visibility::Module(mod_b, expl_b));
}
if b_ancestors.any(|m| m == mod_a.local_id) {
// A is above B
- return Some(Visibility::Module(mod_a, vis_a));
+ return Some(Visibility::Module(mod_a, expl_a));
}
None
@@ -208,7 +224,8 @@ impl Visibility {
}
}
-/// Whether the item was imported through `pub(crate) use` or just `use`.
+/// Whether the item was imported through an explicit `pub(crate) use` or just a `use` without
+/// visibility.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum VisibilityExplicitness {
Explicit,
diff --git a/crates/ide-diagnostics/src/handlers/private_field.rs b/crates/ide-diagnostics/src/handlers/private_field.rs
index 3179a632e2..e91e64c81b 100644
--- a/crates/ide-diagnostics/src/handlers/private_field.rs
+++ b/crates/ide-diagnostics/src/handlers/private_field.rs
@@ -86,4 +86,30 @@ fn main() {
"#,
);
}
+
+ #[test]
+ fn block_module_madness2() {
+ check_diagnostics(
+ r#"
+fn main() {
+ use crate as ForceParentBlockDefMap;
+ let strukt = {
+ use crate as ForceParentBlockDefMap;
+ {
+ pub struct Struct {
+ field: (),
+ }
+ {
+ use crate as ForceParentBlockDefMap;
+ {
+ Struct { field: () }
+ }
+ }
+ }
+ };
+ strukt.field;
+}
+"#,
+ );
+ }
}