mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-06 04:08:40 +00:00
commit
1c32387ce2
@ -28,7 +28,8 @@ use crate::{
|
|||||||
lang_item::LangItem,
|
lang_item::LangItem,
|
||||||
nameres::{ModuleOrigin, ModuleSource},
|
nameres::{ModuleOrigin, ModuleSource},
|
||||||
src::{HasChildSource, HasSource},
|
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.
|
/// Desugared attributes of an item post `cfg_attr` expansion.
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
use either::Either;
|
use either::Either;
|
||||||
use hir_expand::{attrs::collect_attrs, HirFileId};
|
use hir_expand::{attrs::collect_attrs, HirFileId};
|
||||||
|
use syntax::ast;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
db::DefDatabase,
|
db::DefDatabase,
|
||||||
@ -17,8 +18,9 @@ use crate::{
|
|||||||
item_tree::ItemTreeNode,
|
item_tree::ItemTreeNode,
|
||||||
nameres::DefMap,
|
nameres::DefMap,
|
||||||
src::{HasChildSource, HasSource},
|
src::{HasChildSource, HasSource},
|
||||||
AdtId, AssocItemId, DefWithBodyId, EnumId, FieldId, ImplId, ItemTreeLoc, Lookup, MacroId,
|
AdtId, AssocItemId, DefWithBodyId, EnumId, FieldId, GenericDefId, ImplId, ItemTreeLoc,
|
||||||
ModuleDefId, ModuleId, TraitId, VariantId,
|
LifetimeParamId, Lookup, MacroId, ModuleDefId, ModuleId, TraitId, TypeOrConstParamId,
|
||||||
|
VariantId,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub trait ChildBySource {
|
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 {
|
impl ChildBySource for ModuleId {
|
||||||
fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) {
|
fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) {
|
||||||
let def_map = self.def_map(db);
|
let def_map = self.def_map(db);
|
||||||
@ -118,14 +112,6 @@ impl ChildBySource for ItemScope {
|
|||||||
file_id: HirFileId,
|
file_id: HirFileId,
|
||||||
item: ModuleDefId,
|
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 {
|
match item {
|
||||||
ModuleDefId::FunctionId(id) => {
|
ModuleDefId::FunctionId(id) => {
|
||||||
insert_item_loc(db, map, file_id, id, keys::FUNCTION)
|
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),
|
AdtId::EnumId(id) => insert_item_loc(db, map, file_id, id, keys::ENUM),
|
||||||
},
|
},
|
||||||
ModuleDefId::MacroId(id) => match id {
|
ModuleDefId::MacroId(id) => match id {
|
||||||
MacroId::Macro2Id(id) => insert!(map[keys::MACRO2].insert(id)),
|
MacroId::Macro2Id(id) => insert_item_loc(db, map, file_id, id, keys::MACRO2),
|
||||||
MacroId::MacroRulesId(id) => insert!(map[keys::MACRO_RULES].insert(id)),
|
MacroId::MacroRulesId(id) => {
|
||||||
MacroId::ProcMacroId(id) => insert!(map[keys::PROC_MACRO].insert(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::ModuleId(_)
|
||||||
| ModuleDefId::EnumVariantId(_)
|
| 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>(
|
fn insert_item_loc<ID, N, Data>(
|
||||||
db: &dyn DefDatabase,
|
db: &dyn DefDatabase,
|
||||||
res: &mut DynMap,
|
res: &mut DynMap,
|
||||||
@ -224,3 +248,11 @@ fn insert_item_loc<ID, N, Data>(
|
|||||||
res[key].insert(loc.source(db).value, id)
|
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),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -10,7 +10,7 @@ use hir_expand::{
|
|||||||
HirFileId, InFile,
|
HirFileId, InFile,
|
||||||
};
|
};
|
||||||
use intern::Interned;
|
use intern::Interned;
|
||||||
use la_arena::{Arena, ArenaMap};
|
use la_arena::Arena;
|
||||||
use rustc_abi::{Align, Integer, IntegerType, ReprFlags, ReprOptions};
|
use rustc_abi::{Align, Integer, IntegerType, ReprFlags, ReprOptions};
|
||||||
use syntax::ast::{self, HasName, HasVisibility};
|
use syntax::ast::{self, HasName, HasVisibility};
|
||||||
use triomphe::Arc;
|
use triomphe::Arc;
|
||||||
@ -22,13 +22,11 @@ use crate::{
|
|||||||
lang_item::LangItem,
|
lang_item::LangItem,
|
||||||
lower::LowerCtx,
|
lower::LowerCtx,
|
||||||
nameres::diagnostics::{DefDiagnostic, DefDiagnostics},
|
nameres::diagnostics::{DefDiagnostic, DefDiagnostics},
|
||||||
src::HasChildSource,
|
|
||||||
src::HasSource,
|
|
||||||
trace::Trace,
|
trace::Trace,
|
||||||
tt::{Delimiter, DelimiterKind, Leaf, Subtree, TokenTree},
|
tt::{Delimiter, DelimiterKind, Leaf, Subtree, TokenTree},
|
||||||
type_ref::TypeRef,
|
type_ref::TypeRef,
|
||||||
visibility::RawVisibility,
|
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!
|
/// 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)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
pub enum StructKind {
|
pub enum StructKind {
|
||||||
Tuple,
|
Tuple,
|
||||||
@ -434,7 +392,7 @@ pub enum StructKind {
|
|||||||
Unit,
|
Unit,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_struct(
|
pub(crate) fn lower_struct(
|
||||||
db: &dyn DefDatabase,
|
db: &dyn DefDatabase,
|
||||||
trace: &mut Trace<FieldData, Either<ast::TupleField, ast::RecordField>>,
|
trace: &mut Trace<FieldData, Either<ast::TupleField, ast::RecordField>>,
|
||||||
ast: &InFile<ast::StructKind>,
|
ast: &InFile<ast::StructKind>,
|
||||||
|
@ -3,31 +3,27 @@
|
|||||||
//! generic parameters. See also the `Generics` type and the `generics_of` query
|
//! generic parameters. See also the `Generics` type and the `generics_of` query
|
||||||
//! in rustc.
|
//! in rustc.
|
||||||
|
|
||||||
use base_db::FileId;
|
|
||||||
use either::Either;
|
use either::Either;
|
||||||
use hir_expand::{
|
use hir_expand::{
|
||||||
name::{AsName, Name},
|
name::{AsName, Name},
|
||||||
ExpandResult, HirFileId, InFile,
|
ExpandResult,
|
||||||
};
|
};
|
||||||
use intern::Interned;
|
use intern::Interned;
|
||||||
use la_arena::{Arena, ArenaMap, Idx};
|
use la_arena::{Arena, Idx};
|
||||||
use once_cell::unsync::Lazy;
|
use once_cell::unsync::Lazy;
|
||||||
use stdx::impl_from;
|
use stdx::impl_from;
|
||||||
use syntax::ast::{self, HasGenericParams, HasName, HasTypeBounds};
|
use syntax::ast::{self, HasGenericParams, HasName, HasTypeBounds};
|
||||||
use triomphe::Arc;
|
use triomphe::Arc;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
child_by_source::ChildBySource,
|
|
||||||
db::DefDatabase,
|
db::DefDatabase,
|
||||||
dyn_map::{keys, DynMap},
|
|
||||||
expander::Expander,
|
expander::Expander,
|
||||||
item_tree::ItemTree,
|
item_tree::{GenericsItemTreeNode, ItemTree},
|
||||||
lower::LowerCtx,
|
lower::LowerCtx,
|
||||||
nameres::{DefMap, MacroSubNs},
|
nameres::{DefMap, MacroSubNs},
|
||||||
src::{HasChildSource, HasSource},
|
|
||||||
type_ref::{ConstRef, LifetimeRef, TypeBound, TypeRef},
|
type_ref::{ConstRef, LifetimeRef, TypeBound, TypeRef},
|
||||||
AdtId, ConstParamId, GenericDefId, HasModule, LifetimeParamId, LocalLifetimeParamId,
|
AdtId, ConstParamId, GenericDefId, HasModule, ItemTreeLoc, LocalTypeOrConstParamId, Lookup,
|
||||||
LocalTypeOrConstParamId, Lookup, TypeOrConstParamId, TypeParamId,
|
TypeOrConstParamId, TypeParamId,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Data about a generic type parameter (to a function, struct, impl, ...).
|
/// Data about a generic type parameter (to a function, struct, impl, ...).
|
||||||
@ -418,13 +414,18 @@ impl GenericParams {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
macro_rules! id_to_generics {
|
fn id_to_generics<Id: GenericsItemTreeNode>(
|
||||||
($id:ident) => {{
|
db: &dyn DefDatabase,
|
||||||
let id = $id.lookup(db).id;
|
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 tree = id.item_tree(db);
|
||||||
let item = &tree[id.value];
|
let item = &tree[id.value];
|
||||||
enabled_params(&item.generic_params, &tree)
|
enabled_params(item.generic_params(), &tree)
|
||||||
}};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
match def {
|
match def {
|
||||||
@ -457,13 +458,13 @@ impl GenericParams {
|
|||||||
Interned::new(generic_params.finish())
|
Interned::new(generic_params.finish())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GenericDefId::AdtId(AdtId::StructId(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!(id),
|
GenericDefId::AdtId(AdtId::EnumId(id)) => id_to_generics(db, id, enabled_params),
|
||||||
GenericDefId::AdtId(AdtId::UnionId(id)) => id_to_generics!(id),
|
GenericDefId::AdtId(AdtId::UnionId(id)) => id_to_generics(db, id, enabled_params),
|
||||||
GenericDefId::TraitId(id) => id_to_generics!(id),
|
GenericDefId::TraitId(id) => id_to_generics(db, id, enabled_params),
|
||||||
GenericDefId::TraitAliasId(id) => id_to_generics!(id),
|
GenericDefId::TraitAliasId(id) => id_to_generics(db, id, enabled_params),
|
||||||
GenericDefId::TypeAliasId(id) => id_to_generics!(id),
|
GenericDefId::TypeAliasId(id) => id_to_generics(db, id, enabled_params),
|
||||||
GenericDefId::ImplId(id) => id_to_generics!(id),
|
GenericDefId::ImplId(id) => id_to_generics(db, id, enabled_params),
|
||||||
GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => {
|
GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => {
|
||||||
Interned::new(GenericParams {
|
Interned::new(GenericParams {
|
||||||
type_or_consts: Default::default(),
|
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -347,6 +347,9 @@ pub trait ItemTreeNode: Clone {
|
|||||||
fn lookup(tree: &ItemTree, index: Idx<Self>) -> &Self;
|
fn lookup(tree: &ItemTree, index: Idx<Self>) -> &Self;
|
||||||
fn attr_owner(id: FileItemTreeId<Self>) -> AttrOwner;
|
fn attr_owner(id: FileItemTreeId<Self>) -> AttrOwner;
|
||||||
}
|
}
|
||||||
|
pub trait GenericsItemTreeNode: ItemTreeNode {
|
||||||
|
fn generic_params(&self) -> &Interned<GenericParams>;
|
||||||
|
}
|
||||||
|
|
||||||
pub struct FileItemTreeId<N>(Idx<N>);
|
pub struct FileItemTreeId<N>(Idx<N>);
|
||||||
|
|
||||||
@ -473,7 +476,7 @@ impl<N> Hash for ItemTreeId<N> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! mod_items {
|
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)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
||||||
pub enum ModItem {
|
pub enum ModItem {
|
||||||
$(
|
$(
|
||||||
@ -513,6 +516,14 @@ macro_rules! mod_items {
|
|||||||
&self.data().$fld[index]
|
&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,
|
Use in uses -> ast::Use,
|
||||||
ExternCrate in extern_crates -> ast::ExternCrate,
|
ExternCrate in extern_crates -> ast::ExternCrate,
|
||||||
ExternBlock in extern_blocks -> ast::ExternBlock,
|
ExternBlock in extern_blocks -> ast::ExternBlock,
|
||||||
Function in functions -> ast::Fn,
|
Function<explicit_generic_params> in functions -> ast::Fn,
|
||||||
Struct in structs -> ast::Struct,
|
Struct<generic_params> in structs -> ast::Struct,
|
||||||
Union in unions -> ast::Union,
|
Union<generic_params> in unions -> ast::Union,
|
||||||
Enum in enums -> ast::Enum,
|
Enum<generic_params> in enums -> ast::Enum,
|
||||||
Const in consts -> ast::Const,
|
Const in consts -> ast::Const,
|
||||||
Static in statics -> ast::Static,
|
Static in statics -> ast::Static,
|
||||||
Trait in traits -> ast::Trait,
|
Trait<generic_params> in traits -> ast::Trait,
|
||||||
TraitAlias in trait_aliases -> ast::TraitAlias,
|
TraitAlias<generic_params> in trait_aliases -> ast::TraitAlias,
|
||||||
Impl in impls -> ast::Impl,
|
Impl<generic_params> in impls -> ast::Impl,
|
||||||
TypeAlias in type_aliases -> ast::TypeAlias,
|
TypeAlias<generic_params> in type_aliases -> ast::TypeAlias,
|
||||||
Mod in mods -> ast::Module,
|
Mod in mods -> ast::Module,
|
||||||
MacroCall in macro_calls -> ast::MacroCall,
|
MacroCall in macro_calls -> ast::MacroCall,
|
||||||
MacroRules in macro_rules -> ast::MacroRules,
|
MacroRules in macro_rules -> ast::MacroRules,
|
||||||
|
@ -658,7 +658,7 @@ impl<'a> Ctx<'a> {
|
|||||||
|
|
||||||
fn lower_visibility(&mut self, item: &dyn ast::HasVisibility) -> RawVisibilityId {
|
fn lower_visibility(&mut self, item: &dyn ast::HasVisibility) -> RawVisibilityId {
|
||||||
let vis =
|
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)
|
self.data().vis.alloc(vis)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,7 +87,7 @@ use hir_expand::{
|
|||||||
use item_tree::ExternBlock;
|
use item_tree::ExternBlock;
|
||||||
use la_arena::Idx;
|
use la_arena::Idx;
|
||||||
use nameres::DefMap;
|
use nameres::DefMap;
|
||||||
use span::Span;
|
use span::{FileId, Span};
|
||||||
use stdx::impl_from;
|
use stdx::impl_from;
|
||||||
use syntax::{ast, AstNode};
|
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)]
|
#[derive(Debug)]
|
||||||
pub struct ItemLoc<N: ItemTreeNode> {
|
pub struct ItemLoc<N: ItemTreeNode> {
|
||||||
pub container: ModuleId,
|
pub container: ModuleId,
|
||||||
@ -322,35 +214,6 @@ pub type EnumLoc = ItemLoc<Enum>;
|
|||||||
impl_intern!(EnumId, EnumLoc, intern_enum, lookup_intern_enum);
|
impl_intern!(EnumId, EnumLoc, intern_enum, lookup_intern_enum);
|
||||||
impl_loc!(EnumLoc, id: Enum, container: ModuleId);
|
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)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub struct ConstId(salsa::InternId);
|
pub struct ConstId(salsa::InternId);
|
||||||
type ConstLoc = AssocItemLoc<Const>;
|
type ConstLoc = AssocItemLoc<Const>;
|
||||||
@ -406,13 +269,16 @@ impl_intern!(ExternBlockId, ExternBlockLoc, intern_extern_block, lookup_intern_e
|
|||||||
impl_loc!(ExternBlockLoc, id: ExternBlock, container: ModuleId);
|
impl_loc!(ExternBlockLoc, id: ExternBlock, container: ModuleId);
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub enum MacroExpander {
|
pub struct EnumVariantId(salsa::InternId);
|
||||||
Declarative,
|
|
||||||
BuiltIn(BuiltinFnLikeExpander),
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
BuiltInAttr(BuiltinAttrExpander),
|
pub struct EnumVariantLoc {
|
||||||
BuiltInDerive(BuiltinDeriveExpander),
|
pub id: ItemTreeId<Variant>,
|
||||||
BuiltInEager(EagerExpander),
|
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)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
|
||||||
pub struct Macro2Id(salsa::InternId);
|
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)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
|
||||||
pub struct ProcMacroId(salsa::InternId);
|
pub struct ProcMacroId(salsa::InternId);
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
@ -471,6 +345,146 @@ pub struct BlockLoc {
|
|||||||
}
|
}
|
||||||
impl_intern!(BlockId, BlockLoc, intern_block, lookup_intern_block);
|
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)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub struct TypeOrConstParamId {
|
pub struct TypeOrConstParamId {
|
||||||
pub parent: GenericDefId,
|
pub parent: GenericDefId,
|
||||||
@ -611,20 +625,6 @@ impl_from!(
|
|||||||
for ModuleDefId
|
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
|
/// Something that holds types, required for the current const arg lowering implementation as they
|
||||||
/// need to be able to query where they are defined.
|
/// need to be able to query where they are defined.
|
||||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
||||||
@ -892,6 +892,39 @@ impl_from!(
|
|||||||
for GenericDefId
|
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 {
|
impl From<AssocItemId> for GenericDefId {
|
||||||
fn from(item: AssocItemId) -> Self {
|
fn from(item: AssocItemId) -> Self {
|
||||||
match item {
|
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 {
|
impl ModuleDefId {
|
||||||
/// Returns the module containing `self` (or `self`, if `self` is itself a module).
|
/// 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
|
/// A helper trait for converting to MacroCallId
|
||||||
pub trait AsMacroCall {
|
pub trait AsMacroCall {
|
||||||
fn as_call_id(
|
fn as_call_id(
|
||||||
|
@ -27,9 +27,9 @@ use crate::{
|
|||||||
visibility::{RawVisibility, Visibility},
|
visibility::{RawVisibility, Visibility},
|
||||||
AdtId, ConstId, ConstParamId, CrateRootModuleId, DefWithBodyId, EnumId, EnumVariantId,
|
AdtId, ConstId, ConstParamId, CrateRootModuleId, DefWithBodyId, EnumId, EnumVariantId,
|
||||||
ExternBlockId, ExternCrateId, FunctionId, GenericDefId, GenericParamId, HasModule, ImplId,
|
ExternBlockId, ExternCrateId, FunctionId, GenericDefId, GenericParamId, HasModule, ImplId,
|
||||||
ItemContainerId, LifetimeParamId, LocalModuleId, Lookup, Macro2Id, MacroId, MacroRulesId,
|
ItemContainerId, ItemTreeLoc, LifetimeParamId, LocalModuleId, Lookup, Macro2Id, MacroId,
|
||||||
ModuleDefId, ModuleId, ProcMacroId, StaticId, StructId, TraitAliasId, TraitId, TypeAliasId,
|
MacroRulesId, ModuleDefId, ModuleId, ProcMacroId, StaticId, StructId, TraitAliasId, TraitId,
|
||||||
TypeOrConstParamId, TypeOwnerId, TypeParamId, UseId, VariantId,
|
TypeAliasId, TypeOrConstParamId, TypeOwnerId, TypeParamId, UseId, VariantId,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@ -248,6 +248,7 @@ impl Resolver {
|
|||||||
RawVisibility::Public => Some(Visibility::Public),
|
RawVisibility::Public => Some(Visibility::Public),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resolve_path_in_value_ns(
|
pub fn resolve_path_in_value_ns(
|
||||||
&self,
|
&self,
|
||||||
db: &dyn DefDatabase,
|
db: &dyn DefDatabase,
|
||||||
@ -1014,13 +1015,13 @@ impl HasResolver for CrateRootModuleId {
|
|||||||
|
|
||||||
impl HasResolver for TraitId {
|
impl HasResolver for TraitId {
|
||||||
fn resolver(self, db: &dyn DefDatabase) -> Resolver {
|
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 {
|
impl HasResolver for TraitAliasId {
|
||||||
fn resolver(self, db: &dyn DefDatabase) -> Resolver {
|
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 {
|
impl HasResolver for FunctionId {
|
||||||
fn resolver(self, db: &dyn DefDatabase) -> Resolver {
|
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 {
|
impl HasResolver for ConstId {
|
||||||
fn resolver(self, db: &dyn DefDatabase) -> Resolver {
|
fn resolver(self, db: &dyn DefDatabase) -> Resolver {
|
||||||
self.lookup(db).container.resolver(db)
|
lookup_resolver(db, self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HasResolver for StaticId {
|
impl HasResolver for StaticId {
|
||||||
fn resolver(self, db: &dyn DefDatabase) -> Resolver {
|
fn resolver(self, db: &dyn DefDatabase) -> Resolver {
|
||||||
self.lookup(db).container.resolver(db)
|
lookup_resolver(db, self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HasResolver for TypeAliasId {
|
impl HasResolver for TypeAliasId {
|
||||||
fn resolver(self, db: &dyn DefDatabase) -> Resolver {
|
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 {
|
impl HasResolver for ExternBlockId {
|
||||||
fn resolver(self, db: &dyn DefDatabase) -> Resolver {
|
fn resolver(self, db: &dyn DefDatabase) -> Resolver {
|
||||||
// Same as parent's
|
// Same as parent's
|
||||||
self.lookup(db).container.resolver(db)
|
lookup_resolver(db, self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HasResolver for ExternCrateId {
|
impl HasResolver for ExternCrateId {
|
||||||
fn resolver(self, db: &dyn DefDatabase) -> Resolver {
|
fn resolver(self, db: &dyn DefDatabase) -> Resolver {
|
||||||
self.lookup(db).container.resolver(db)
|
lookup_resolver(db, self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HasResolver for UseId {
|
impl HasResolver for UseId {
|
||||||
fn resolver(self, db: &dyn DefDatabase) -> Resolver {
|
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 {
|
impl HasResolver for Macro2Id {
|
||||||
fn resolver(self, db: &dyn DefDatabase) -> Resolver {
|
fn resolver(self, db: &dyn DefDatabase) -> Resolver {
|
||||||
self.lookup(db).container.resolver(db)
|
lookup_resolver(db, self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HasResolver for ProcMacroId {
|
impl HasResolver for ProcMacroId {
|
||||||
fn resolver(self, db: &dyn DefDatabase) -> Resolver {
|
fn resolver(self, db: &dyn DefDatabase) -> Resolver {
|
||||||
self.lookup(db).container.resolver(db)
|
lookup_resolver(db, self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HasResolver for MacroRulesId {
|
impl HasResolver for MacroRulesId {
|
||||||
fn resolver(self, db: &dyn DefDatabase) -> Resolver {
|
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)
|
||||||
|
}
|
||||||
|
@ -1,10 +1,15 @@
|
|||||||
//! Utilities for mapping between hir IDs and the surface syntax.
|
//! Utilities for mapping between hir IDs and the surface syntax.
|
||||||
|
|
||||||
|
use either::Either;
|
||||||
use hir_expand::InFile;
|
use hir_expand::InFile;
|
||||||
use la_arena::ArenaMap;
|
use la_arena::ArenaMap;
|
||||||
use syntax::ast;
|
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 {
|
pub trait HasSource {
|
||||||
type Value;
|
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())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
//! projections.
|
//! projections.
|
||||||
use la_arena::{Arena, ArenaMap, Idx, RawIdx};
|
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> {
|
pub(crate) struct Trace<T, V> {
|
||||||
arena: Option<Arena<T>>,
|
arena: Option<Arena<T>>,
|
||||||
map: Option<ArenaMap<Idx<T>, V>>,
|
map: Option<ArenaMap<Idx<T>, V>>,
|
||||||
|
@ -37,10 +37,14 @@ impl RawVisibility {
|
|||||||
db: &dyn DefDatabase,
|
db: &dyn DefDatabase,
|
||||||
node: InFile<Option<ast::Visibility>>,
|
node: InFile<Option<ast::Visibility>>,
|
||||||
) -> RawVisibility {
|
) -> 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())
|
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,
|
db: &dyn DefDatabase,
|
||||||
node: Option<ast::Visibility>,
|
node: Option<ast::Visibility>,
|
||||||
span_map: SpanMapRef<'_>,
|
span_map: SpanMapRef<'_>,
|
||||||
@ -49,30 +53,29 @@ impl RawVisibility {
|
|||||||
None => return RawVisibility::private(),
|
None => return RawVisibility::private(),
|
||||||
Some(node) => node,
|
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) => {
|
ast::VisibilityKind::In(path) => {
|
||||||
let path = ModPath::from_src(db.upcast(), path, span_map);
|
let path = ModPath::from_src(db.upcast(), path, span_map);
|
||||||
let path = match path {
|
match path {
|
||||||
None => return RawVisibility::private(),
|
None => return RawVisibility::private(),
|
||||||
Some(path) => path,
|
Some(path) => path,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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)
|
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,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn resolve(
|
pub fn resolve(
|
||||||
&self,
|
&self,
|
||||||
@ -94,6 +97,10 @@ pub enum Visibility {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Visibility {
|
impl Visibility {
|
||||||
|
pub(crate) fn is_visible_from_other_crate(self) -> bool {
|
||||||
|
matches!(self, Visibility::Public)
|
||||||
|
}
|
||||||
|
|
||||||
#[tracing::instrument(skip_all)]
|
#[tracing::instrument(skip_all)]
|
||||||
pub fn is_visible_from(self, db: &dyn DefDatabase, from_module: ModuleId) -> bool {
|
pub fn is_visible_from(self, db: &dyn DefDatabase, from_module: ModuleId) -> bool {
|
||||||
let to_module = match self {
|
let to_module = match self {
|
||||||
@ -105,24 +112,33 @@ impl Visibility {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
let def_map = from_module.def_map(db);
|
let def_map = from_module.def_map(db);
|
||||||
self.is_visible_from_def_map(db, &def_map, from_module.local_id)
|
Self::is_visible_from_def_map_(db, &def_map, to_module, from_module.local_id)
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn is_visible_from_other_crate(self) -> bool {
|
|
||||||
matches!(self, Visibility::Public)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn is_visible_from_def_map(
|
pub(crate) fn is_visible_from_def_map(
|
||||||
self,
|
self,
|
||||||
db: &dyn DefDatabase,
|
db: &dyn DefDatabase,
|
||||||
def_map: &DefMap,
|
def_map: &DefMap,
|
||||||
mut from_module: LocalModuleId,
|
from_module: LocalModuleId,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let mut to_module = match self {
|
let to_module = match self {
|
||||||
Visibility::Module(m, _) => m,
|
Visibility::Module(m, _) => m,
|
||||||
Visibility::Public => return true,
|
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
|
// `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
|
// visibility as the containing module (even though no items are directly nameable from
|
||||||
// there, getting this right is important for method resolution).
|
// there, getting this right is important for method resolution).
|
||||||
@ -130,21 +146,26 @@ impl Visibility {
|
|||||||
|
|
||||||
// Additional complication: `to_module` might be in `from_module`'s `DefMap`, which we're
|
// 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.
|
// 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 {
|
loop {
|
||||||
let to_module_def_map =
|
match (to_module.block, def_map_block) {
|
||||||
if to_module.krate == def_map.krate() && to_module.block == def_map.block_id() {
|
// 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);
|
cov_mark::hit!(is_visible_from_same_block_def_map);
|
||||||
def_map
|
if let Some(parent) = def_map.parent() {
|
||||||
} else {
|
to_module = parent;
|
||||||
arc = to_module.def_map(db);
|
|
||||||
&arc
|
|
||||||
};
|
|
||||||
match to_module_def_map.parent() {
|
|
||||||
Some(parent) => to_module = parent,
|
|
||||||
None => break,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_ => {
|
||||||
|
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
|
// from_module needs to be a descendant of to_module
|
||||||
let mut def_map = def_map;
|
let mut def_map = def_map;
|
||||||
@ -176,30 +197,25 @@ impl Visibility {
|
|||||||
/// visible in unrelated modules).
|
/// visible in unrelated modules).
|
||||||
pub(crate) fn max(self, other: Visibility, def_map: &DefMap) -> Option<Visibility> {
|
pub(crate) fn max(self, other: Visibility, def_map: &DefMap) -> Option<Visibility> {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(Visibility::Module(_, _) | Visibility::Public, Visibility::Public)
|
(_, Visibility::Public) | (Visibility::Public, _) => Some(Visibility::Public),
|
||||||
| (Visibility::Public, Visibility::Module(_, _)) => Some(Visibility::Public),
|
(Visibility::Module(mod_a, expl_a), Visibility::Module(mod_b, expl_b)) => {
|
||||||
(Visibility::Module(mod_a, vis_a), Visibility::Module(mod_b, vis_b)) => {
|
|
||||||
if mod_a.krate != mod_b.krate {
|
if mod_a.krate != mod_b.krate {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut a_ancestors = iter::successors(Some(mod_a.local_id), |&m| {
|
let mut a_ancestors =
|
||||||
let parent_id = def_map[m].parent?;
|
iter::successors(Some(mod_a.local_id), |&m| def_map[m].parent);
|
||||||
Some(parent_id)
|
let mut b_ancestors =
|
||||||
});
|
iter::successors(Some(mod_b.local_id), |&m| def_map[m].parent);
|
||||||
let mut b_ancestors = iter::successors(Some(mod_b.local_id), |&m| {
|
|
||||||
let parent_id = def_map[m].parent?;
|
|
||||||
Some(parent_id)
|
|
||||||
});
|
|
||||||
|
|
||||||
if a_ancestors.any(|m| m == mod_b.local_id) {
|
if a_ancestors.any(|m| m == mod_b.local_id) {
|
||||||
// B is above A
|
// 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) {
|
if b_ancestors.any(|m| m == mod_a.local_id) {
|
||||||
// A is above B
|
// A is above B
|
||||||
return Some(Visibility::Module(mod_a, vis_a));
|
return Some(Visibility::Module(mod_a, expl_a));
|
||||||
}
|
}
|
||||||
|
|
||||||
None
|
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)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
pub enum VisibilityExplicitness {
|
pub enum VisibilityExplicitness {
|
||||||
Explicit,
|
Explicit,
|
||||||
|
@ -83,6 +83,32 @@ fn main() {
|
|||||||
};
|
};
|
||||||
strukt.field;
|
strukt.field;
|
||||||
}
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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;
|
||||||
|
}
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user