Merge commit 'ddf105b646' into sync-from-ra

This commit is contained in:
Laurențiu Nicola 2024-02-11 08:40:19 +02:00
parent 0816d49d83
commit e41ab350d6
378 changed files with 14720 additions and 3111 deletions

View file

@ -24,11 +24,11 @@ use triomphe::Arc;
use crate::{
db::DefDatabase,
item_tree::{AttrOwner, Fields, ItemTreeId, ItemTreeModItemNode},
item_tree::{AttrOwner, Fields, ItemTreeNode},
lang_item::LangItem,
nameres::{ModuleOrigin, ModuleSource},
src::{HasChildSource, HasSource},
AdtId, AssocItemLoc, AttrDefId, GenericParamId, ItemLoc, LocalFieldId, Lookup, MacroId,
AdtId, AttrDefId, GenericParamId, HasModule, ItemTreeLoc, LocalFieldId, Lookup, MacroId,
VariantId,
};
@ -317,7 +317,7 @@ fn parse_comma_sep<S>(subtree: &tt::Subtree<S>) -> Vec<SmolStr> {
}
impl AttrsWithOwner {
pub fn attrs_with_owner(db: &dyn DefDatabase, owner: AttrDefId) -> Self {
pub fn new(db: &dyn DefDatabase, owner: AttrDefId) -> Self {
Self { attrs: db.attrs(owner), owner }
}
@ -356,12 +356,7 @@ impl AttrsWithOwner {
AttrDefId::FieldId(it) => {
return db.fields_attrs(it.parent)[it.local_id].clone();
}
// FIXME: DRY this up
AttrDefId::EnumVariantId(it) => {
let id = it.lookup(db).id;
let tree = id.item_tree(db);
tree.raw_attrs(id.value.into()).clone()
}
AttrDefId::EnumVariantId(it) => attrs_from_item_tree_loc(db, it),
AttrDefId::AdtId(it) => match it {
AdtId::StructId(it) => attrs_from_item_tree_loc(db, it),
AdtId::EnumId(it) => attrs_from_item_tree_loc(db, it),
@ -370,15 +365,15 @@ impl AttrsWithOwner {
AttrDefId::TraitId(it) => attrs_from_item_tree_loc(db, it),
AttrDefId::TraitAliasId(it) => attrs_from_item_tree_loc(db, it),
AttrDefId::MacroId(it) => match it {
MacroId::Macro2Id(it) => attrs_from_item_tree(db, it.lookup(db).id),
MacroId::MacroRulesId(it) => attrs_from_item_tree(db, it.lookup(db).id),
MacroId::ProcMacroId(it) => attrs_from_item_tree(db, it.lookup(db).id),
MacroId::Macro2Id(it) => attrs_from_item_tree_loc(db, it),
MacroId::MacroRulesId(it) => attrs_from_item_tree_loc(db, it),
MacroId::ProcMacroId(it) => attrs_from_item_tree_loc(db, it),
},
AttrDefId::ImplId(it) => attrs_from_item_tree_loc(db, it),
AttrDefId::ConstId(it) => attrs_from_item_tree_assoc(db, it),
AttrDefId::StaticId(it) => attrs_from_item_tree_assoc(db, it),
AttrDefId::FunctionId(it) => attrs_from_item_tree_assoc(db, it),
AttrDefId::TypeAliasId(it) => attrs_from_item_tree_assoc(db, it),
AttrDefId::ConstId(it) => attrs_from_item_tree_loc(db, it),
AttrDefId::StaticId(it) => attrs_from_item_tree_loc(db, it),
AttrDefId::FunctionId(it) => attrs_from_item_tree_loc(db, it),
AttrDefId::TypeAliasId(it) => attrs_from_item_tree_loc(db, it),
AttrDefId::GenericParamId(it) => match it {
GenericParamId::ConstParamId(it) => {
let src = it.parent().child_source(db);
@ -603,29 +598,14 @@ fn any_has_attrs<'db>(
id.lookup(db).source(db).map(ast::AnyHasAttrs::new)
}
fn attrs_from_item_tree<N: ItemTreeModItemNode>(
db: &dyn DefDatabase,
id: ItemTreeId<N>,
fn attrs_from_item_tree_loc<'db, N: ItemTreeNode>(
db: &(dyn DefDatabase + 'db),
lookup: impl Lookup<Database<'db> = dyn DefDatabase + 'db, Data = impl ItemTreeLoc<Id = N>>,
) -> RawAttrs {
let id = lookup.lookup(db).item_tree_id();
let tree = id.item_tree(db);
let mod_item = N::id_to_mod_item(id.value);
tree.raw_attrs(mod_item.into()).clone()
}
fn attrs_from_item_tree_loc<'db, N: ItemTreeModItemNode>(
db: &(dyn DefDatabase + 'db),
lookup: impl Lookup<Database<'db> = dyn DefDatabase + 'db, Data = ItemLoc<N>>,
) -> RawAttrs {
let id = lookup.lookup(db).id;
attrs_from_item_tree(db, id)
}
fn attrs_from_item_tree_assoc<'db, N: ItemTreeModItemNode>(
db: &(dyn DefDatabase + 'db),
lookup: impl Lookup<Database<'db> = dyn DefDatabase + 'db, Data = AssocItemLoc<N>>,
) -> RawAttrs {
let id = lookup.lookup(db).id;
attrs_from_item_tree(db, id)
let attr_owner = N::attr_owner(id.value);
tree.raw_attrs(attr_owner).clone()
}
pub(crate) fn fields_attrs_source_map(

View file

@ -283,9 +283,6 @@ pub const INERT_ATTRIBUTES: &[BuiltinAttribute] = &[
experimental!(optimize),
),
gated!(
ffi_returns_twice, Normal, template!(Word), WarnFollowing, experimental!(ffi_returns_twice)
),
gated!(ffi_pure, Normal, template!(Word), WarnFollowing, experimental!(ffi_pure)),
gated!(ffi_const, Normal, template!(Word), WarnFollowing, experimental!(ffi_const)),
gated!(

View file

@ -1980,10 +1980,7 @@ fn pat_literal_to_hir(lit: &ast::LiteralPat) -> Option<(Literal, ast::Literal)>
let ast_lit = lit.literal()?;
let mut hir_lit: Literal = ast_lit.kind().into();
if lit.minus_token().is_some() {
let Some(h) = hir_lit.negate() else {
return None;
};
hir_lit = h;
hir_lit = hir_lit.negate()?;
}
Some((hir_lit, ast_lit))
}

View file

@ -29,11 +29,11 @@ pub(super) fn print_body_hir(db: &dyn DefDatabase, body: &Body, owner: DefWithBo
"const {} = ",
match &it.name {
Some(name) => name.display(db.upcast()).to_string(),
None => "_".to_string(),
None => "_".to_owned(),
}
)
}),
DefWithBodyId::InTypeConstId(_) => "In type const = ".to_string(),
DefWithBodyId::InTypeConstId(_) => "In type const = ".to_owned(),
DefWithBodyId::VariantId(it) => {
let loc = it.lookup(db);
let enum_loc = loc.parent.lookup(db);
@ -123,7 +123,7 @@ impl Printer<'_> {
wln!(self);
f(self);
self.indent_level -= 1;
self.buf = self.buf.trim_end_matches('\n').to_string();
self.buf = self.buf.trim_end_matches('\n').to_owned();
}
fn whitespace(&mut self) {

View file

@ -6,15 +6,21 @@
use either::Either;
use hir_expand::{attrs::collect_attrs, HirFileId};
use syntax::ast;
use crate::{
db::DefDatabase,
dyn_map::{keys, DynMap},
dyn_map::{
keys::{self, Key},
DynMap,
},
item_scope::ItemScope,
item_tree::ItemTreeNode,
nameres::DefMap,
src::{HasChildSource, HasSource},
AdtId, AssocItemId, DefWithBodyId, EnumId, ExternCrateId, FieldId, ImplId, Lookup, MacroId,
ModuleDefId, ModuleId, TraitId, UseId, VariantId,
AdtId, AssocItemId, DefWithBodyId, EnumId, FieldId, GenericDefId, ImplId, ItemTreeLoc,
LifetimeParamId, Lookup, MacroId, ModuleDefId, ModuleId, TraitId, TypeOrConstParamId,
VariantId,
};
pub trait ChildBySource {
@ -55,29 +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) => {
let loc = func.lookup(db);
if loc.id.file_id() == file_id {
res[keys::FUNCTION].insert(loc.source(db).value, func)
}
}
AssocItemId::ConstId(konst) => {
let loc = konst.lookup(db);
if loc.id.file_id() == file_id {
res[keys::CONST].insert(loc.source(db).value, konst)
}
}
AssocItemId::TypeAliasId(ty) => {
let loc = ty.lookup(db);
if loc.id.file_id() == file_id {
res[keys::TYPE_ALIAS].insert(loc.source(db).value, ty)
}
}
}
}
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);
@ -89,15 +72,12 @@ impl ChildBySource for ModuleId {
impl ChildBySource for ItemScope {
fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) {
self.declarations().for_each(|item| add_module_def(db, res, file_id, item));
self.impls().for_each(|imp| add_impl(db, res, file_id, imp));
self.extern_crate_decls().for_each(|ext| add_extern_crate(db, res, file_id, ext));
self.use_decls().for_each(|ext| add_use(db, res, file_id, ext));
self.unnamed_consts(db).for_each(|konst| {
let loc = konst.lookup(db);
if loc.id.file_id() == file_id {
res[keys::CONST].insert(loc.source(db).value, konst);
}
});
self.impls().for_each(|imp| insert_item_loc(db, res, file_id, imp, keys::IMPL));
self.extern_crate_decls()
.for_each(|ext| insert_item_loc(db, res, file_id, ext, keys::EXTERN_CRATE));
self.use_decls().for_each(|ext| insert_item_loc(db, res, file_id, ext, keys::USE));
self.unnamed_consts(db)
.for_each(|konst| insert_item_loc(db, res, file_id, konst, keys::CONST));
self.attr_macro_invocs().filter(|(id, _)| id.file_id == file_id).for_each(
|(ast_id, call_id)| {
res[keys::ATTR_MACRO_CALL].insert(ast_id.to_node(db.upcast()), call_id);
@ -132,59 +112,38 @@ 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!(map[keys::FUNCTION].insert(id)),
ModuleDefId::ConstId(id) => insert!(map[keys::CONST].insert(id)),
ModuleDefId::StaticId(id) => insert!(map[keys::STATIC].insert(id)),
ModuleDefId::TypeAliasId(id) => insert!(map[keys::TYPE_ALIAS].insert(id)),
ModuleDefId::TraitId(id) => insert!(map[keys::TRAIT].insert(id)),
ModuleDefId::TraitAliasId(id) => insert!(map[keys::TRAIT_ALIAS].insert(id)),
ModuleDefId::FunctionId(id) => {
insert_item_loc(db, map, file_id, id, keys::FUNCTION)
}
ModuleDefId::ConstId(id) => insert_item_loc(db, map, file_id, id, keys::CONST),
ModuleDefId::TypeAliasId(id) => {
insert_item_loc(db, map, file_id, id, keys::TYPE_ALIAS)
}
ModuleDefId::StaticId(id) => insert_item_loc(db, map, file_id, id, keys::STATIC),
ModuleDefId::TraitId(id) => insert_item_loc(db, map, file_id, id, keys::TRAIT),
ModuleDefId::TraitAliasId(id) => {
insert_item_loc(db, map, file_id, id, keys::TRAIT_ALIAS)
}
ModuleDefId::AdtId(adt) => match adt {
AdtId::StructId(id) => insert!(map[keys::STRUCT].insert(id)),
AdtId::UnionId(id) => insert!(map[keys::UNION].insert(id)),
AdtId::EnumId(id) => insert!(map[keys::ENUM].insert(id)),
AdtId::StructId(id) => insert_item_loc(db, map, file_id, id, keys::STRUCT),
AdtId::UnionId(id) => insert_item_loc(db, map, file_id, id, keys::UNION),
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(_)
| ModuleDefId::BuiltinType(_) => (),
}
}
fn add_impl(db: &dyn DefDatabase, map: &mut DynMap, file_id: HirFileId, imp: ImplId) {
let loc = imp.lookup(db);
if loc.id.file_id() == file_id {
map[keys::IMPL].insert(loc.source(db).value, imp)
}
}
fn add_extern_crate(
db: &dyn DefDatabase,
map: &mut DynMap,
file_id: HirFileId,
ext: ExternCrateId,
) {
let loc = ext.lookup(db);
if loc.id.file_id() == file_id {
map[keys::EXTERN_CRATE].insert(loc.source(db).value, ext)
}
}
fn add_use(db: &dyn DefDatabase, map: &mut DynMap, file_id: HirFileId, ext: UseId) {
let loc = ext.lookup(db);
if loc.id.file_id() == file_id {
map[keys::USE].insert(loc.source(db).value, ext)
}
}
}
}
@ -237,3 +196,63 @@ 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,
file_id: HirFileId,
id: ID,
key: Key<N::Source, ID>,
) where
ID: for<'db> Lookup<Database<'db> = dyn DefDatabase + 'db, Data = Data> + 'static,
Data: ItemTreeLoc<Id = N>,
N: ItemTreeNode,
N::Source: 'static,
{
let loc = id.lookup(db);
if loc.item_tree_id().file_id() == file_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),
}
}

View file

@ -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>,

View file

@ -171,6 +171,7 @@ fn find_path_inner(ctx: FindPathCtx<'_>, item: ItemInNs, from: ModuleId) -> Opti
.map(|(item, _)| item)
}
#[tracing::instrument(skip_all)]
fn find_path_for_module(
ctx: FindPathCtx<'_>,
def_map: &DefMap,
@ -312,6 +313,7 @@ fn find_self_super(def_map: &DefMap, item: ModuleId, from: ModuleId) -> Option<M
}
}
#[tracing::instrument(skip_all)]
fn calculate_best_path(
ctx: FindPathCtx<'_>,
def_map: &DefMap,

View file

@ -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, ...).
@ -264,7 +260,7 @@ impl GenericParamsCollector {
self.add_where_predicate_from_bound(
lower_ctx,
bound,
lifetimes.as_ref(),
lifetimes.as_deref(),
target.clone(),
);
}
@ -275,14 +271,14 @@ impl GenericParamsCollector {
&mut self,
lower_ctx: &LowerCtx<'_>,
bound: ast::TypeBound,
hrtb_lifetimes: Option<&Box<[Name]>>,
hrtb_lifetimes: Option<&[Name]>,
target: Either<TypeRef, LifetimeRef>,
) {
let bound = TypeBound::from_ast(lower_ctx, bound);
let predicate = match (target, bound) {
(Either::Left(type_ref), bound) => match hrtb_lifetimes {
Some(hrtb_lifetimes) => WherePredicate::ForLifetime {
lifetimes: hrtb_lifetimes.clone(),
lifetimes: hrtb_lifetimes.to_vec().into_boxed_slice(),
target: WherePredicateTypeTarget::TypeRef(Interned::new(type_ref)),
bound: Interned::new(bound),
},
@ -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,141 +508,3 @@ impl GenericParams {
})
}
}
fn file_id_and_params_of(
def: GenericDefId,
db: &dyn DefDatabase,
) -> (HirFileId, Option<ast::GenericParamList>) {
match def {
GenericDefId::FunctionId(it) => {
let src = it.lookup(db).source(db);
(src.file_id, src.value.generic_param_list())
}
GenericDefId::AdtId(AdtId::StructId(it)) => {
let src = it.lookup(db).source(db);
(src.file_id, src.value.generic_param_list())
}
GenericDefId::AdtId(AdtId::UnionId(it)) => {
let src = it.lookup(db).source(db);
(src.file_id, src.value.generic_param_list())
}
GenericDefId::AdtId(AdtId::EnumId(it)) => {
let src = it.lookup(db).source(db);
(src.file_id, src.value.generic_param_list())
}
GenericDefId::TraitId(it) => {
let src = it.lookup(db).source(db);
(src.file_id, src.value.generic_param_list())
}
GenericDefId::TraitAliasId(it) => {
let src = it.lookup(db).source(db);
(src.file_id, src.value.generic_param_list())
}
GenericDefId::TypeAliasId(it) => {
let src = it.lookup(db).source(db);
(src.file_id, src.value.generic_param_list())
}
GenericDefId::ImplId(it) => {
let src = it.lookup(db).source(db);
(src.file_id, src.value.generic_param_list())
}
// We won't be using this ID anyway
GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => (FileId::BOGUS.into(), None),
}
}
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(*self, 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) = file_id_and_params_of(*self, 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 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(*self, 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);
}
}
}
}

View file

@ -859,7 +859,7 @@ mod tests {
check_search(
ra_fixture,
"main",
Query::new("fmt".to_string()).fuzzy(),
Query::new("fmt".to_owned()).fuzzy(),
expect![[r#"
dep::fmt (t)
dep::fmt::Display::FMT_CONST (a)
@ -888,9 +888,7 @@ mod tests {
check_search(
ra_fixture,
"main",
Query::new("fmt".to_string())
.fuzzy()
.assoc_search_mode(AssocSearchMode::AssocItemsOnly),
Query::new("fmt".to_owned()).fuzzy().assoc_search_mode(AssocSearchMode::AssocItemsOnly),
expect![[r#"
dep::fmt::Display::FMT_CONST (a)
dep::fmt::Display::format_function (a)
@ -901,7 +899,7 @@ mod tests {
check_search(
ra_fixture,
"main",
Query::new("fmt".to_string()).fuzzy().assoc_search_mode(AssocSearchMode::Exclude),
Query::new("fmt".to_owned()).fuzzy().assoc_search_mode(AssocSearchMode::Exclude),
expect![[r#"
dep::fmt (t)
"#]],
@ -937,7 +935,7 @@ pub mod fmt {
check_search(
ra_fixture,
"main",
Query::new("fmt".to_string()).fuzzy(),
Query::new("fmt".to_owned()).fuzzy(),
expect![[r#"
dep::Fmt (m)
dep::Fmt (t)
@ -951,7 +949,7 @@ pub mod fmt {
check_search(
ra_fixture,
"main",
Query::new("fmt".to_string()),
Query::new("fmt".to_owned()),
expect![[r#"
dep::Fmt (m)
dep::Fmt (t)
@ -991,7 +989,7 @@ pub mod fmt {
check_search(
ra_fixture,
"main",
Query::new("fmt".to_string()),
Query::new("fmt".to_owned()),
expect![[r#"
dep::Fmt (m)
dep::Fmt (t)
@ -1015,7 +1013,7 @@ pub mod fmt {
check_search(
ra_fixture,
"main",
Query::new("FMT".to_string()),
Query::new("FMT".to_owned()),
expect![[r#"
dep::FMT (t)
dep::FMT (v)
@ -1027,7 +1025,7 @@ pub mod fmt {
check_search(
ra_fixture,
"main",
Query::new("FMT".to_string()).case_sensitive(),
Query::new("FMT".to_owned()).case_sensitive(),
expect![[r#"
dep::FMT (t)
dep::FMT (v)

View file

@ -222,17 +222,15 @@ impl ItemScope {
self.declarations.iter().copied()
}
pub fn extern_crate_decls(
&self,
) -> impl Iterator<Item = ExternCrateId> + ExactSizeIterator + '_ {
pub fn extern_crate_decls(&self) -> impl ExactSizeIterator<Item = ExternCrateId> + '_ {
self.extern_crate_decls.iter().copied()
}
pub fn use_decls(&self) -> impl Iterator<Item = UseId> + ExactSizeIterator + '_ {
pub fn use_decls(&self) -> impl ExactSizeIterator<Item = UseId> + '_ {
self.use_decls.iter().copied()
}
pub fn impls(&self) -> impl Iterator<Item = ImplId> + ExactSizeIterator + '_ {
pub fn impls(&self) -> impl ExactSizeIterator<Item = ImplId> + '_ {
self.impls.iter().copied()
}
@ -674,7 +672,7 @@ impl ItemScope {
format_to!(
buf,
"{}:",
name.map_or("_".to_string(), |name| name.display(db).to_string())
name.map_or("_".to_owned(), |name| name.display(db).to_string())
);
if let Some((.., i)) = def.types {

View file

@ -337,20 +337,18 @@ from_attrs!(
LifetimeParamData(Idx<LifetimeParamData>),
);
/// Trait implemented by all item nodes in the item tree.
pub trait ItemTreeModItemNode: Clone {
type Source: AstIdNode + Into<ast::Item>;
/// Trait implemented by all nodes in the item tree.
pub trait ItemTreeNode: Clone {
type Source: AstIdNode;
fn ast_id(&self) -> FileAstId<Self::Source>;
/// Looks up an instance of `Self` in an item tree.
fn lookup(tree: &ItemTree, index: Idx<Self>) -> &Self;
/// Downcasts a `ModItem` to a `FileItemTreeId` specific to this type.
fn id_from_mod_item(mod_item: ModItem) -> Option<FileItemTreeId<Self>>;
/// Upcasts a `FileItemTreeId` to a generic `ModItem`.
fn id_to_mod_item(id: FileItemTreeId<Self>) -> ModItem;
fn attr_owner(id: FileItemTreeId<Self>) -> AttrOwner;
}
pub trait GenericsItemTreeNode: ItemTreeNode {
fn generic_params(&self) -> &Interned<GenericParams>;
}
pub struct FileItemTreeId<N>(Idx<N>);
@ -372,7 +370,7 @@ impl<N> FileItemTreeId<N> {
impl<N> Clone for FileItemTreeId<N> {
fn clone(&self) -> Self {
Self(self.0)
*self
}
}
impl<N> Copy for FileItemTreeId<N> {}
@ -478,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 {
$(
@ -495,7 +493,7 @@ macro_rules! mod_items {
)+
$(
impl ItemTreeModItemNode for $typ {
impl ItemTreeNode for $typ {
type Source = $ast;
fn ast_id(&self) -> FileAstId<Self::Source> {
@ -506,15 +504,8 @@ macro_rules! mod_items {
&tree.data().$fld[index]
}
fn id_from_mod_item(mod_item: ModItem) -> Option<FileItemTreeId<Self>> {
match mod_item {
ModItem::$typ(id) => Some(id),
_ => None,
}
}
fn id_to_mod_item(id: FileItemTreeId<Self>) -> ModItem {
ModItem::$typ(id)
fn attr_owner(id: FileItemTreeId<Self>) -> AttrOwner {
AttrOwner::ModItem(ModItem::$typ(id))
}
}
@ -525,6 +516,14 @@ macro_rules! mod_items {
&self.data().$fld[index]
}
}
$(
impl GenericsItemTreeNode for $typ {
fn generic_params(&self) -> &Interned<GenericParams> {
&self.$generic_params
}
}
)?
)+
};
}
@ -533,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,
@ -578,17 +577,26 @@ impl Index<RawVisibilityId> for ItemTree {
}
}
impl<N: ItemTreeModItemNode> Index<FileItemTreeId<N>> for ItemTree {
impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree {
type Output = N;
fn index(&self, id: FileItemTreeId<N>) -> &N {
N::lookup(self, id.index())
}
}
impl Index<FileItemTreeId<Variant>> for ItemTree {
type Output = Variant;
fn index(&self, id: FileItemTreeId<Variant>) -> &Variant {
&self[id.index()]
impl ItemTreeNode for Variant {
type Source = ast::Variant;
fn ast_id(&self) -> FileAstId<Self::Source> {
self.ast_id
}
fn lookup(tree: &ItemTree, index: Idx<Self>) -> &Self {
&tree.data().variants[index]
}
fn attr_owner(id: FileItemTreeId<Self>) -> AttrOwner {
AttrOwner::Variant(id)
}
}
@ -1027,7 +1035,7 @@ impl AssocItem {
}
}
#[derive(Debug, Eq, PartialEq)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Variant {
pub name: Name,
pub fields: Fields,

View file

@ -13,7 +13,7 @@ use crate::{
use super::*;
fn id<N: ItemTreeModItemNode>(index: Idx<N>) -> FileItemTreeId<N> {
fn id<N: ItemTreeNode>(index: Idx<N>) -> FileItemTreeId<N> {
FileItemTreeId(index)
}
@ -267,7 +267,7 @@ impl<'a> Ctx<'a> {
if let Some(data) = self.lower_variant(&variant) {
let idx = self.data().variants.alloc(data);
self.add_attrs(
FileItemTreeId(idx).into(),
id(idx).into(),
RawAttrs::new(self.db.upcast(), &variant, self.span_map()),
);
}
@ -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)
}

View file

@ -24,7 +24,7 @@ pub(super) fn print_item_tree(db: &dyn DefDatabase, tree: &ItemTree) -> String {
p.print_mod_item(*item);
}
let mut s = p.buf.trim_end_matches('\n').to_string();
let mut s = p.buf.trim_end_matches('\n').to_owned();
s.push('\n');
s
}
@ -58,7 +58,7 @@ impl Printer<'_> {
wln!(self);
f(self);
self.indent_level -= 1;
self.buf = self.buf.trim_end_matches('\n').to_string();
self.buf = self.buf.trim_end_matches('\n').to_owned();
}
/// Ensures that a blank line is output before the next text.

View file

@ -70,7 +70,11 @@ use std::{
panic::{RefUnwindSafe, UnwindSafe},
};
use base_db::{impl_intern_key, salsa, CrateId, Edition};
use base_db::{
impl_intern_key,
salsa::{self, impl_intern_value_trivial},
CrateId, Edition,
};
use hir_expand::{
ast_id_map::{AstIdNode, FileAstId},
builtin_attr_macro::BuiltinAttrExpander,
@ -87,7 +91,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};
@ -98,11 +102,268 @@ use crate::{
data::adt::VariantData,
db::DefDatabase,
item_tree::{
Const, Enum, ExternCrate, Function, Impl, ItemTreeId, ItemTreeModItemNode, Macro2,
MacroRules, Static, Struct, Trait, TraitAlias, TypeAlias, Union, Use, Variant,
Const, Enum, ExternCrate, Function, Impl, ItemTreeId, ItemTreeNode, Macro2, MacroRules,
Static, Struct, Trait, TraitAlias, TypeAlias, Union, Use, Variant,
},
};
#[derive(Debug)]
pub struct ItemLoc<N: ItemTreeNode> {
pub container: ModuleId,
pub id: ItemTreeId<N>,
}
impl<N: ItemTreeNode> Clone for ItemLoc<N> {
fn clone(&self) -> Self {
*self
}
}
impl<N: ItemTreeNode> Copy for ItemLoc<N> {}
impl<N: ItemTreeNode> PartialEq for ItemLoc<N> {
fn eq(&self, other: &Self) -> bool {
self.container == other.container && self.id == other.id
}
}
impl<N: ItemTreeNode> Eq for ItemLoc<N> {}
impl<N: ItemTreeNode> Hash for ItemLoc<N> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.container.hash(state);
self.id.hash(state);
}
}
#[derive(Debug)]
pub struct AssocItemLoc<N: ItemTreeNode> {
pub container: ItemContainerId,
pub id: ItemTreeId<N>,
}
impl<N: ItemTreeNode> Clone for AssocItemLoc<N> {
fn clone(&self) -> Self {
*self
}
}
impl<N: ItemTreeNode> Copy for AssocItemLoc<N> {}
impl<N: ItemTreeNode> PartialEq for AssocItemLoc<N> {
fn eq(&self, other: &Self) -> bool {
self.container == other.container && self.id == other.id
}
}
impl<N: ItemTreeNode> Eq for AssocItemLoc<N> {}
impl<N: ItemTreeNode> Hash for AssocItemLoc<N> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.container.hash(state);
self.id.hash(state);
}
}
pub trait ItemTreeLoc {
type Container;
type Id;
fn item_tree_id(&self) -> ItemTreeId<Self::Id>;
fn container(&self) -> Self::Container;
}
macro_rules! impl_intern {
($id:ident, $loc:ident, $intern:ident, $lookup:ident) => {
impl_intern_key!($id);
impl_intern_value_trivial!($loc);
impl_intern_lookup!(DefDatabase, $id, $loc, $intern, $lookup);
};
}
macro_rules! impl_loc {
($loc:ident, $id:ident: $id_ty:ident, $container:ident: $container_type:ident) => {
impl ItemTreeLoc for $loc {
type Container = $container_type;
type Id = $id_ty;
fn item_tree_id(&self) -> ItemTreeId<Self::Id> {
self.$id
}
fn container(&self) -> Self::Container {
self.$container
}
}
};
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct FunctionId(salsa::InternId);
type FunctionLoc = AssocItemLoc<Function>;
impl_intern!(FunctionId, FunctionLoc, intern_function, lookup_intern_function);
impl_loc!(FunctionLoc, id: Function, container: ItemContainerId);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct StructId(salsa::InternId);
type StructLoc = ItemLoc<Struct>;
impl_intern!(StructId, StructLoc, intern_struct, lookup_intern_struct);
impl_loc!(StructLoc, id: Struct, container: ModuleId);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct UnionId(salsa::InternId);
pub type UnionLoc = ItemLoc<Union>;
impl_intern!(UnionId, UnionLoc, intern_union, lookup_intern_union);
impl_loc!(UnionLoc, id: Union, container: ModuleId);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct EnumId(salsa::InternId);
pub type EnumLoc = ItemLoc<Enum>;
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 ConstId(salsa::InternId);
type ConstLoc = AssocItemLoc<Const>;
impl_intern!(ConstId, ConstLoc, intern_const, lookup_intern_const);
impl_loc!(ConstLoc, id: Const, container: ItemContainerId);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct StaticId(salsa::InternId);
pub type StaticLoc = AssocItemLoc<Static>;
impl_intern!(StaticId, StaticLoc, intern_static, lookup_intern_static);
impl_loc!(StaticLoc, id: Static, container: ItemContainerId);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct TraitId(salsa::InternId);
pub type TraitLoc = ItemLoc<Trait>;
impl_intern!(TraitId, TraitLoc, intern_trait, lookup_intern_trait);
impl_loc!(TraitLoc, id: Trait, container: ModuleId);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct TraitAliasId(salsa::InternId);
pub type TraitAliasLoc = ItemLoc<TraitAlias>;
impl_intern!(TraitAliasId, TraitAliasLoc, intern_trait_alias, lookup_intern_trait_alias);
impl_loc!(TraitAliasLoc, id: TraitAlias, container: ModuleId);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct TypeAliasId(salsa::InternId);
type TypeAliasLoc = AssocItemLoc<TypeAlias>;
impl_intern!(TypeAliasId, TypeAliasLoc, intern_type_alias, lookup_intern_type_alias);
impl_loc!(TypeAliasLoc, id: TypeAlias, container: ItemContainerId);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
pub struct ImplId(salsa::InternId);
type ImplLoc = ItemLoc<Impl>;
impl_intern!(ImplId, ImplLoc, intern_impl, lookup_intern_impl);
impl_loc!(ImplLoc, id: Impl, container: ModuleId);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
pub struct UseId(salsa::InternId);
type UseLoc = ItemLoc<Use>;
impl_intern!(UseId, UseLoc, intern_use, lookup_intern_use);
impl_loc!(UseLoc, id: Use, container: ModuleId);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
pub struct ExternCrateId(salsa::InternId);
type ExternCrateLoc = ItemLoc<ExternCrate>;
impl_intern!(ExternCrateId, ExternCrateLoc, intern_extern_crate, lookup_intern_extern_crate);
impl_loc!(ExternCrateLoc, id: ExternCrate, container: ModuleId);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
pub struct ExternBlockId(salsa::InternId);
type ExternBlockLoc = ItemLoc<ExternBlock>;
impl_intern!(ExternBlockId, ExternBlockLoc, intern_extern_block, lookup_intern_extern_block);
impl_loc!(ExternBlockLoc, id: ExternBlock, 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, Ord, PartialOrd)]
pub struct Macro2Id(salsa::InternId);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Macro2Loc {
pub container: ModuleId,
pub id: ItemTreeId<Macro2>,
pub expander: MacroExpander,
pub allow_internal_unsafe: bool,
pub edition: Edition,
}
impl_intern!(Macro2Id, Macro2Loc, intern_macro2, lookup_intern_macro2);
impl_loc!(Macro2Loc, id: Macro2, container: ModuleId);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
pub struct MacroRulesId(salsa::InternId);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct MacroRulesLoc {
pub container: ModuleId,
pub id: ItemTreeId<MacroRules>,
pub expander: MacroExpander,
pub flags: MacroRulesLocFlags,
pub edition: Edition,
}
impl_intern!(MacroRulesId, MacroRulesLoc, intern_macro_rules, lookup_intern_macro_rules);
impl_loc!(MacroRulesLoc, id: MacroRules, container: ModuleId);
bitflags::bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct MacroRulesLocFlags: u8 {
const ALLOW_INTERNAL_UNSAFE = 1 << 0;
const LOCAL_INNER = 1 << 1;
}
}
#[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)]
pub struct ProcMacroLoc {
pub container: CrateRootModuleId,
pub id: ItemTreeId<Function>,
pub expander: CustomProcMacroExpander,
pub kind: ProcMacroKind,
pub edition: Edition,
}
impl_intern!(ProcMacroId, ProcMacroLoc, intern_proc_macro, lookup_intern_proc_macro);
impl_loc!(ProcMacroLoc, id: Function, container: CrateRootModuleId);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
pub struct BlockId(salsa::InternId);
#[derive(Debug, Hash, PartialEq, Eq, Clone)]
pub struct BlockLoc {
ast_id: AstId<ast::BlockExpr>,
/// The containing module.
module: ModuleId,
}
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 {
@ -124,23 +385,6 @@ impl PartialEq<ModuleId> for CrateRootModuleId {
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 {
@ -208,105 +452,27 @@ impl ModuleId {
}
}
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)]
pub struct ItemLoc<N: ItemTreeModItemNode> {
pub container: ModuleId,
pub id: ItemTreeId<N>,
}
impl<N: ItemTreeModItemNode> Clone for ItemLoc<N> {
fn clone(&self) -> Self {
Self { container: self.container, id: self.id }
}
}
impl<N: ItemTreeModItemNode> Copy for ItemLoc<N> {}
impl<N: ItemTreeModItemNode> PartialEq for ItemLoc<N> {
fn eq(&self, other: &Self) -> bool {
self.container == other.container && self.id == other.id
}
}
impl<N: ItemTreeModItemNode> Eq for ItemLoc<N> {}
impl<N: ItemTreeModItemNode> Hash for ItemLoc<N> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.container.hash(state);
self.id.hash(state);
}
}
#[derive(Debug)]
pub struct AssocItemLoc<N: ItemTreeModItemNode> {
pub container: ItemContainerId,
pub id: ItemTreeId<N>,
}
impl<N: ItemTreeModItemNode> Clone for AssocItemLoc<N> {
fn clone(&self) -> Self {
Self { container: self.container, id: self.id }
}
}
impl<N: ItemTreeModItemNode> Copy for AssocItemLoc<N> {}
impl<N: ItemTreeModItemNode> PartialEq for AssocItemLoc<N> {
fn eq(&self, other: &Self) -> bool {
self.container == other.container && self.id == other.id
}
}
impl<N: ItemTreeModItemNode> Eq for AssocItemLoc<N> {}
impl<N: ItemTreeModItemNode> Hash for AssocItemLoc<N> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.container.hash(state);
self.id.hash(state);
}
}
macro_rules! impl_intern {
($id:ident, $loc:ident, $intern:ident, $lookup:ident) => {
impl_intern_key!($id);
impl_intern_lookup!(DefDatabase, $id, $loc, $intern, $lookup);
};
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct FunctionId(salsa::InternId);
type FunctionLoc = AssocItemLoc<Function>;
impl_intern!(FunctionId, FunctionLoc, intern_function, lookup_intern_function);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct StructId(salsa::InternId);
type StructLoc = ItemLoc<Struct>;
impl_intern!(StructId, StructLoc, intern_struct, lookup_intern_struct);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct UnionId(salsa::InternId);
pub type UnionLoc = ItemLoc<Union>;
impl_intern!(UnionId, UnionLoc, intern_union, lookup_intern_union);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct EnumId(salsa::InternId);
pub type EnumLoc = ItemLoc<Enum>;
impl_intern!(EnumId, EnumLoc, intern_enum, lookup_intern_enum);
#[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);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct FieldId {
pub parent: VariantId,
@ -324,119 +490,12 @@ pub struct TupleFieldId {
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);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct StaticId(salsa::InternId);
pub type StaticLoc = AssocItemLoc<Static>;
impl_intern!(StaticId, StaticLoc, intern_static, lookup_intern_static);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct TraitId(salsa::InternId);
pub type TraitLoc = ItemLoc<Trait>;
impl_intern!(TraitId, TraitLoc, intern_trait, lookup_intern_trait);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct TraitAliasId(salsa::InternId);
pub type TraitAliasLoc = ItemLoc<TraitAlias>;
impl_intern!(TraitAliasId, TraitAliasLoc, intern_trait_alias, lookup_intern_trait_alias);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct TypeAliasId(salsa::InternId);
type TypeAliasLoc = AssocItemLoc<TypeAlias>;
impl_intern!(TypeAliasId, TypeAliasLoc, intern_type_alias, lookup_intern_type_alias);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
pub struct ImplId(salsa::InternId);
type ImplLoc = ItemLoc<Impl>;
impl_intern!(ImplId, ImplLoc, intern_impl, lookup_intern_impl);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
pub struct UseId(salsa::InternId);
type UseLoc = ItemLoc<Use>;
impl_intern!(UseId, UseLoc, intern_use, lookup_intern_use);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
pub struct ExternCrateId(salsa::InternId);
type ExternCrateLoc = ItemLoc<ExternCrate>;
impl_intern!(ExternCrateId, ExternCrateLoc, intern_extern_crate, lookup_intern_extern_crate);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
pub struct ExternBlockId(salsa::InternId);
type ExternBlockLoc = ItemLoc<ExternBlock>;
impl_intern!(ExternBlockId, ExternBlockLoc, intern_extern_block, lookup_intern_extern_block);
#[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 Macro2Id(salsa::InternId);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Macro2Loc {
pub container: ModuleId,
pub id: ItemTreeId<Macro2>,
pub expander: MacroExpander,
pub allow_internal_unsafe: bool,
pub edition: Edition,
}
impl_intern!(Macro2Id, Macro2Loc, intern_macro2, lookup_intern_macro2);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
pub struct MacroRulesId(salsa::InternId);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct MacroRulesLoc {
pub container: ModuleId,
pub id: ItemTreeId<MacroRules>,
pub expander: MacroExpander,
pub flags: MacroRulesLocFlags,
pub edition: Edition,
}
impl_intern!(MacroRulesId, MacroRulesLoc, intern_macro_rules, lookup_intern_macro_rules);
bitflags::bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct MacroRulesLocFlags: u8 {
const ALLOW_INTERNAL_UNSAFE = 1 << 0;
const LOCAL_INNER = 1 << 1;
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
pub struct ProcMacroId(salsa::InternId);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ProcMacroLoc {
pub container: CrateRootModuleId,
pub id: ItemTreeId<Function>,
pub expander: CustomProcMacroExpander,
pub kind: ProcMacroKind,
pub edition: Edition,
}
impl_intern!(ProcMacroId, ProcMacroLoc, intern_proc_macro, lookup_intern_proc_macro);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
pub struct BlockId(salsa::InternId);
#[derive(Debug, Hash, PartialEq, Eq, Clone)]
pub struct BlockLoc {
ast_id: AstId<ast::BlockExpr>,
/// The containing module.
module: ModuleId,
}
impl_intern!(BlockId, BlockLoc, intern_block, lookup_intern_block);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct TypeOrConstParamId {
pub parent: GenericDefId,
pub local_id: LocalTypeOrConstParamId,
}
impl_intern_value_trivial!(TypeOrConstParamId);
/// A TypeOrConstParamId with an invariant that it actually belongs to a type
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@ -498,6 +557,7 @@ pub struct LifetimeParamId {
pub local_id: LocalLifetimeParamId,
}
pub type LocalLifetimeParamId = Idx<generics::LifetimeParamData>;
impl_intern_value_trivial!(LifetimeParamId);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ItemContainerId {
@ -572,20 +632,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)]
@ -721,6 +767,9 @@ impl Clone for Box<dyn OpaqueInternableThing> {
pub struct InTypeConstId(salsa::InternId);
impl_intern!(InTypeConstId, InTypeConstLoc, intern_in_type_const, lookup_intern_in_type_const);
// We would like to set `derive(PartialEq)`
// but the compiler complains about that `.expected_ty` does not implement the `Copy` trait.
#[allow(clippy::derived_hash_with_manual_eq)]
#[derive(Debug, Hash, Eq, Clone)]
pub struct InTypeConstLoc {
pub id: AstId<ast::ConstArg>,
@ -850,6 +899,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 {
@ -983,44 +1065,92 @@ impl VariantId {
}
pub trait HasModule {
/// Returns the enclosing module this thing is defined within.
fn module(&self, db: &dyn DefDatabase) -> ModuleId;
}
impl HasModule for ItemContainerId {
fn module(&self, db: &dyn DefDatabase) -> ModuleId {
match *self {
ItemContainerId::ModuleId(it) => it,
ItemContainerId::ImplId(it) => it.lookup(db).container,
ItemContainerId::TraitId(it) => it.lookup(db).container,
ItemContainerId::ExternBlockId(it) => it.lookup(db).container,
}
}
}
impl<N: ItemTreeModItemNode> HasModule for AssocItemLoc<N> {
/// Returns the crate this thing is defined within.
#[inline]
fn module(&self, db: &dyn DefDatabase) -> ModuleId {
self.container.module(db)
#[doc(alias = "crate")]
fn krate(&self, db: &dyn DefDatabase) -> CrateId {
self.module(db).krate
}
}
impl HasModule for AdtId {
fn module(&self, db: &dyn DefDatabase) -> ModuleId {
match self {
AdtId::StructId(it) => it.lookup(db).container,
AdtId::UnionId(it) => it.lookup(db).container,
AdtId::EnumId(it) => it.lookup(db).container,
}
}
}
// In theory this impl should work out for us, but rustc thinks it collides with all the other
// manual impls that do not have a ModuleId container...
// impl<N, ItemId, Data> HasModule for ItemId
// where
// N: ItemTreeNode,
// ItemId: for<'db> Lookup<Database<'db> = dyn DefDatabase + 'db, Data = Data> + Copy,
// Data: ItemTreeLoc<Id = N, Container = ModuleId>,
// {
// #[inline]
// fn module(&self, db: &dyn DefDatabase) -> ModuleId {
// self.lookup(db).container()
// }
// }
impl HasModule for EnumId {
impl<N, ItemId> HasModule for ItemId
where
N: ItemTreeNode,
ItemId: for<'db> Lookup<Database<'db> = dyn DefDatabase + 'db, Data = ItemLoc<N>> + Copy,
{
#[inline]
fn module(&self, db: &dyn DefDatabase) -> ModuleId {
self.lookup(db).container
}
}
// Technically this does not overlap with the above, but rustc currently forbids this, hence why we
// need to write the 3 impls manually instead
// impl<N, ItemId> HasModule for ItemId
// where
// N: ItemTreeModItemNode,
// ItemId: for<'db> Lookup<Database<'db> = dyn DefDatabase + 'db, Data = AssocItemLoc<N>> + Copy,
// {
// #[inline]
// fn module(&self, db: &dyn DefDatabase) -> ModuleId {
// self.lookup(db).container.module(db)
// }
// }
// region: manual-assoc-has-module-impls
#[inline]
fn module_for_assoc_item_loc<'db>(
db: &(dyn 'db + DefDatabase),
id: impl Lookup<Database<'db> = dyn DefDatabase + 'db, Data = AssocItemLoc<impl ItemTreeNode>>,
) -> ModuleId {
id.lookup(db).container.module(db)
}
impl HasModule for FunctionId {
#[inline]
fn module(&self, db: &dyn DefDatabase) -> ModuleId {
module_for_assoc_item_loc(db, *self)
}
}
impl HasModule for ConstId {
#[inline]
fn module(&self, db: &dyn DefDatabase) -> ModuleId {
module_for_assoc_item_loc(db, *self)
}
}
impl HasModule for StaticId {
#[inline]
fn module(&self, db: &dyn DefDatabase) -> ModuleId {
module_for_assoc_item_loc(db, *self)
}
}
impl HasModule for TypeAliasId {
#[inline]
fn module(&self, db: &dyn DefDatabase) -> ModuleId {
module_for_assoc_item_loc(db, *self)
}
}
// endregion: manual-assoc-has-module-impls
impl HasModule for EnumVariantId {
#[inline]
fn module(&self, db: &dyn DefDatabase) -> ModuleId {
@ -1028,46 +1158,81 @@ impl HasModule for EnumVariantId {
}
}
impl HasModule for ExternCrateId {
impl HasModule for MacroRulesId {
#[inline]
fn module(&self, db: &dyn DefDatabase) -> ModuleId {
self.lookup(db).container
}
}
impl HasModule for Macro2Id {
#[inline]
fn module(&self, db: &dyn DefDatabase) -> ModuleId {
self.lookup(db).container
}
}
impl HasModule for ProcMacroId {
#[inline]
fn module(&self, db: &dyn DefDatabase) -> ModuleId {
self.lookup(db).container.into()
}
}
impl HasModule for ItemContainerId {
fn module(&self, db: &dyn DefDatabase) -> ModuleId {
match *self {
ItemContainerId::ModuleId(it) => it,
ItemContainerId::ImplId(it) => it.module(db),
ItemContainerId::TraitId(it) => it.module(db),
ItemContainerId::ExternBlockId(it) => it.module(db),
}
}
}
impl HasModule for AdtId {
fn module(&self, db: &dyn DefDatabase) -> ModuleId {
match *self {
AdtId::StructId(it) => it.module(db),
AdtId::UnionId(it) => it.module(db),
AdtId::EnumId(it) => it.module(db),
}
}
}
impl HasModule for VariantId {
fn module(&self, db: &dyn DefDatabase) -> ModuleId {
match self {
VariantId::EnumVariantId(it) => it.lookup(db).parent.module(db),
VariantId::StructId(it) => it.lookup(db).container,
VariantId::UnionId(it) => it.lookup(db).container,
match *self {
VariantId::EnumVariantId(it) => it.module(db),
VariantId::StructId(it) => it.module(db),
VariantId::UnionId(it) => it.module(db),
}
}
}
impl HasModule for MacroId {
fn module(&self, db: &dyn DefDatabase) -> ModuleId {
match self {
MacroId::MacroRulesId(it) => it.lookup(db).container,
MacroId::Macro2Id(it) => it.lookup(db).container,
MacroId::ProcMacroId(it) => it.lookup(db).container.into(),
match *self {
MacroId::MacroRulesId(it) => it.module(db),
MacroId::Macro2Id(it) => it.module(db),
MacroId::ProcMacroId(it) => it.module(db),
}
}
}
impl HasModule for TypeOwnerId {
fn module(&self, db: &dyn DefDatabase) -> ModuleId {
match self {
TypeOwnerId::FunctionId(it) => it.lookup(db).module(db),
TypeOwnerId::StaticId(it) => it.lookup(db).module(db),
TypeOwnerId::ConstId(it) => it.lookup(db).module(db),
TypeOwnerId::InTypeConstId(it) => it.lookup(db).owner.module(db),
match *self {
TypeOwnerId::FunctionId(it) => it.module(db),
TypeOwnerId::StaticId(it) => it.module(db),
TypeOwnerId::ConstId(it) => it.module(db),
TypeOwnerId::AdtId(it) => it.module(db),
TypeOwnerId::TraitId(it) => it.lookup(db).container,
TypeOwnerId::TraitAliasId(it) => it.lookup(db).container,
TypeOwnerId::TypeAliasId(it) => it.lookup(db).module(db),
TypeOwnerId::ImplId(it) => it.lookup(db).container,
TypeOwnerId::EnumVariantId(it) => it.lookup(db).parent.module(db),
TypeOwnerId::TraitId(it) => it.module(db),
TypeOwnerId::TraitAliasId(it) => it.module(db),
TypeOwnerId::TypeAliasId(it) => it.module(db),
TypeOwnerId::ImplId(it) => it.module(db),
TypeOwnerId::EnumVariantId(it) => it.module(db),
TypeOwnerId::InTypeConstId(it) => it.lookup(db).owner.module(db),
}
}
}
@ -1075,10 +1240,10 @@ impl HasModule for TypeOwnerId {
impl HasModule for DefWithBodyId {
fn module(&self, db: &dyn DefDatabase) -> ModuleId {
match self {
DefWithBodyId::FunctionId(it) => it.lookup(db).module(db),
DefWithBodyId::StaticId(it) => it.lookup(db).module(db),
DefWithBodyId::ConstId(it) => it.lookup(db).module(db),
DefWithBodyId::VariantId(it) => it.lookup(db).parent.module(db),
DefWithBodyId::FunctionId(it) => it.module(db),
DefWithBodyId::StaticId(it) => it.module(db),
DefWithBodyId::ConstId(it) => it.module(db),
DefWithBodyId::VariantId(it) => it.module(db),
DefWithBodyId::InTypeConstId(it) => it.lookup(db).owner.module(db),
}
}
@ -1087,29 +1252,43 @@ impl HasModule for DefWithBodyId {
impl HasModule for GenericDefId {
fn module(&self, db: &dyn DefDatabase) -> ModuleId {
match self {
GenericDefId::FunctionId(it) => it.lookup(db).module(db),
GenericDefId::FunctionId(it) => it.module(db),
GenericDefId::AdtId(it) => it.module(db),
GenericDefId::TraitId(it) => it.lookup(db).container,
GenericDefId::TraitAliasId(it) => it.lookup(db).container,
GenericDefId::TypeAliasId(it) => it.lookup(db).module(db),
GenericDefId::ImplId(it) => it.lookup(db).container,
GenericDefId::EnumVariantId(it) => it.lookup(db).parent.lookup(db).container,
GenericDefId::ConstId(it) => it.lookup(db).module(db),
GenericDefId::TraitId(it) => it.module(db),
GenericDefId::TraitAliasId(it) => it.module(db),
GenericDefId::TypeAliasId(it) => it.module(db),
GenericDefId::ImplId(it) => it.module(db),
GenericDefId::EnumVariantId(it) => it.module(db),
GenericDefId::ConstId(it) => it.module(db),
}
}
}
impl HasModule for TypeAliasId {
#[inline]
impl HasModule for AttrDefId {
fn module(&self, db: &dyn DefDatabase) -> ModuleId {
self.lookup(db).module(db)
}
}
impl HasModule for TraitId {
#[inline]
fn module(&self, db: &dyn DefDatabase) -> ModuleId {
self.lookup(db).container
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),
}
}
}
@ -1120,51 +1299,20 @@ impl ModuleDefId {
pub fn module(&self, db: &dyn DefDatabase) -> Option<ModuleId> {
Some(match self {
ModuleDefId::ModuleId(id) => *id,
ModuleDefId::FunctionId(id) => id.lookup(db).module(db),
ModuleDefId::FunctionId(id) => id.module(db),
ModuleDefId::AdtId(id) => id.module(db),
ModuleDefId::EnumVariantId(id) => id.lookup(db).parent.module(db),
ModuleDefId::ConstId(id) => id.lookup(db).container.module(db),
ModuleDefId::StaticId(id) => id.lookup(db).module(db),
ModuleDefId::TraitId(id) => id.lookup(db).container,
ModuleDefId::TraitAliasId(id) => id.lookup(db).container,
ModuleDefId::TypeAliasId(id) => id.lookup(db).module(db),
ModuleDefId::EnumVariantId(id) => id.module(db),
ModuleDefId::ConstId(id) => id.module(db),
ModuleDefId::StaticId(id) => id.module(db),
ModuleDefId::TraitId(id) => id.module(db),
ModuleDefId::TraitAliasId(id) => id.module(db),
ModuleDefId::TypeAliasId(id) => id.module(db),
ModuleDefId::MacroId(id) => id.module(db),
ModuleDefId::BuiltinType(_) => return None,
})
}
}
impl AttrDefId {
pub fn krate(&self, db: &dyn DefDatabase) -> CrateId {
match self {
AttrDefId::ModuleId(it) => it.krate,
AttrDefId::FieldId(it) => it.parent.module(db).krate,
AttrDefId::AdtId(it) => it.module(db).krate,
AttrDefId::FunctionId(it) => it.lookup(db).module(db).krate,
AttrDefId::EnumVariantId(it) => it.lookup(db).parent.module(db).krate,
AttrDefId::StaticId(it) => it.lookup(db).module(db).krate,
AttrDefId::ConstId(it) => it.lookup(db).module(db).krate,
AttrDefId::TraitId(it) => it.lookup(db).container.krate,
AttrDefId::TraitAliasId(it) => it.lookup(db).container.krate,
AttrDefId::TypeAliasId(it) => it.lookup(db).module(db).krate,
AttrDefId::ImplId(it) => it.lookup(db).container.krate,
AttrDefId::ExternBlockId(it) => it.lookup(db).container.krate,
AttrDefId::GenericParamId(it) => {
match it {
GenericParamId::TypeParamId(it) => it.parent(),
GenericParamId::ConstParamId(it) => it.parent(),
GenericParamId::LifetimeParamId(it) => it.parent,
}
.module(db)
.krate
}
AttrDefId::MacroId(it) => it.module(db).krate,
AttrDefId::ExternCrateId(it) => it.lookup(db).container.krate,
AttrDefId::UseId(it) => it.lookup(db).container.krate,
}
}
}
/// A helper trait for converting to MacroCallId
pub trait AsMacroCall {
fn as_call_id(

View file

@ -157,7 +157,7 @@ where
generic: Vec<T::InGenericArg>,
}
impl <T: $crate::clone::Clone, > $crate::clone::Clone for Foo<T, > where T: Trait, T::InFieldShorthand: $crate::clone::Clone, T::InGenericArg: $crate::clone::Clone, {
impl <T: $crate::clone::Clone, > $crate::clone::Clone for Foo<T, > where <T as Trait>::InWc: Marker, T: Trait, T::InFieldShorthand: $crate::clone::Clone, T::InGenericArg: $crate::clone::Clone, {
fn clone(&self ) -> Self {
match self {
Foo {

View file

@ -35,9 +35,9 @@ macro_rules! f {
};
}
struct#0:1@58..64#2# MyTraitMap2#0:2@31..42#0# {#0:1@72..73#2#
map#0:1@86..89#2#:#0:1@89..90#2# #0:1@89..90#2#::#0:1@91..92#2#std#0:1@93..96#2#::#0:1@96..97#2#collections#0:1@98..109#2#::#0:1@109..110#2#HashSet#0:1@111..118#2#<#0:1@118..119#2#(#0:1@119..120#2#)#0:1@120..121#2#>#0:1@121..122#2#,#0:1@122..123#2#
}#0:1@132..133#2#
struct#0:1@58..64#1# MyTraitMap2#0:2@31..42#0# {#0:1@72..73#1#
map#0:1@86..89#1#:#0:1@89..90#1# #0:1@89..90#1#::#0:1@91..92#1#std#0:1@93..96#1#::#0:1@96..97#1#collections#0:1@98..109#1#::#0:1@109..110#1#HashSet#0:1@111..118#1#<#0:1@118..119#1#(#0:1@119..120#1#)#0:1@120..121#1#>#0:1@121..122#1#,#0:1@122..123#1#
}#0:1@132..133#1#
"#]],
);
}
@ -171,7 +171,7 @@ fn main(foo: ()) {
}
fn main(foo: ()) {
/* error: unresolved macro unresolved */"helloworld!"#0:3@207..323#6#;
/* error: unresolved macro unresolved */"helloworld!"#0:3@207..323#2#;
}
}
@ -197,7 +197,7 @@ macro_rules! mk_struct {
#[macro_use]
mod foo;
struct#1:1@59..65#2# Foo#0:2@32..35#0#(#1:1@70..71#2#u32#0:2@41..44#0#)#1:1@74..75#2#;#1:1@75..76#2#
struct#1:1@59..65#1# Foo#0:2@32..35#0#(#1:1@70..71#1#u32#0:2@41..44#0#)#1:1@74..75#1#;#1:1@75..76#1#
"#]],
);
}

View file

@ -224,7 +224,7 @@ fn reindent(indent: IndentLevel, pp: String) -> String {
return pp;
}
let mut lines = pp.split_inclusive('\n');
let mut res = lines.next().unwrap().to_string();
let mut res = lines.next().unwrap().to_owned();
for line in lines {
if line.trim().is_empty() {
res.push_str(line)

View file

@ -33,8 +33,8 @@ use crate::{
db::DefDatabase,
item_scope::{ImportId, ImportOrExternCrate, ImportType, PerNsGlobImports},
item_tree::{
self, ExternCrate, Fields, FileItemTreeId, ImportKind, ItemTree, ItemTreeId,
ItemTreeModItemNode, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId,
self, ExternCrate, Fields, FileItemTreeId, ImportKind, ItemTree, ItemTreeId, ItemTreeNode,
Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId,
},
macro_call_as_call_id, macro_call_as_call_id_with_eager,
nameres::{
@ -2125,7 +2125,7 @@ impl ModCollector<'_, '_> {
let is_export = export_attr.exists();
let local_inner = if is_export {
export_attr.tt_values().flat_map(|it| &it.token_trees).any(|it| match it {
export_attr.tt_values().flat_map(|it| it.token_trees.iter()).any(|it| match it {
tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => {
ident.text.contains("local_inner_macros")
}

View file

@ -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)
}

View file

@ -1,12 +1,14 @@
//! 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::ItemTreeModItemNode, AssocItemLoc, EnumVariantLoc, ItemLoc, Lookup,
Macro2Loc, MacroRulesLoc, ProcMacroLoc, UseId,
data::adt::lower_struct, db::DefDatabase, item_tree::ItemTreeNode, trace::Trace, GenericDefId,
ItemTreeLoc, LocalFieldId, LocalLifetimeParamId, LocalTypeOrConstParamId, Lookup, UseId,
VariantId,
};
pub trait HasSource {
@ -14,81 +16,22 @@ pub trait HasSource {
fn source(&self, db: &dyn DefDatabase) -> InFile<Self::Value>;
}
impl<N: ItemTreeModItemNode> HasSource for AssocItemLoc<N> {
type Value = N::Source;
fn source(&self, db: &dyn DefDatabase) -> InFile<N::Source> {
let tree = self.id.item_tree(db);
let ast_id_map = db.ast_id_map(self.id.file_id());
let root = db.parse_or_expand(self.id.file_id());
let node = &tree[self.id.value];
InFile::new(self.id.file_id(), ast_id_map.get(node.ast_id()).to_node(&root))
}
}
impl<N: ItemTreeModItemNode> HasSource for ItemLoc<N> {
type Value = N::Source;
fn source(&self, db: &dyn DefDatabase) -> InFile<N::Source> {
let tree = self.id.item_tree(db);
let ast_id_map = db.ast_id_map(self.id.file_id());
let root = db.parse_or_expand(self.id.file_id());
let node = &tree[self.id.value];
InFile::new(self.id.file_id(), ast_id_map.get(node.ast_id()).to_node(&root))
}
}
impl HasSource for EnumVariantLoc {
type Value = ast::Variant;
fn source(&self, db: &dyn DefDatabase) -> InFile<ast::Variant> {
let tree = self.id.item_tree(db);
let ast_id_map = db.ast_id_map(self.id.file_id());
let root = db.parse_or_expand(self.id.file_id());
let node = &tree[self.id.value];
InFile::new(self.id.file_id(), ast_id_map.get(node.ast_id).to_node(&root))
}
}
impl HasSource for Macro2Loc {
type Value = ast::MacroDef;
impl<T> HasSource for T
where
T: ItemTreeLoc,
T::Id: ItemTreeNode,
{
type Value = <T::Id as ItemTreeNode>::Source;
fn source(&self, db: &dyn DefDatabase) -> InFile<Self::Value> {
let tree = self.id.item_tree(db);
let ast_id_map = db.ast_id_map(self.id.file_id());
let root = db.parse_or_expand(self.id.file_id());
let node = &tree[self.id.value];
let id = self.item_tree_id();
let file_id = id.file_id();
let tree = id.item_tree(db);
let ast_id_map = db.ast_id_map(file_id);
let root = db.parse_or_expand(file_id);
let node = &tree[id.value];
InFile::new(self.id.file_id(), ast_id_map.get(node.ast_id()).to_node(&root))
}
}
impl HasSource for MacroRulesLoc {
type Value = ast::MacroRules;
fn source(&self, db: &dyn DefDatabase) -> InFile<Self::Value> {
let tree = self.id.item_tree(db);
let ast_id_map = db.ast_id_map(self.id.file_id());
let root = db.parse_or_expand(self.id.file_id());
let node = &tree[self.id.value];
InFile::new(self.id.file_id(), ast_id_map.get(node.ast_id()).to_node(&root))
}
}
impl HasSource for ProcMacroLoc {
type Value = ast::Fn;
fn source(&self, db: &dyn DefDatabase) -> InFile<Self::Value> {
let tree = self.id.item_tree(db);
let ast_id_map = db.ast_id_map(self.id.file_id());
let root = db.parse_or_expand(self.id.file_id());
let node = &tree[self.id.value];
InFile::new(self.id.file_id(), ast_id_map.get(node.ast_id()).to_node(&root))
InFile::new(file_id, ast_id_map.get(node.ast_id()).to_node(&root))
}
}
@ -111,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())
}
}

View file

@ -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>>,

View file

@ -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,11 @@ 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 {
Visibility::Module(m, _) => m,
@ -104,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).
@ -129,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
@ -175,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
@ -207,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,