mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-13 21:54:42 +00:00
Switch type aliases to new sources
This commit is contained in:
parent
b7a36b5443
commit
64c21ed195
9 changed files with 162 additions and 73 deletions
|
@ -13,7 +13,7 @@ use hir_def::{
|
|||
traits::TraitData,
|
||||
type_ref::{Mutability, TypeRef},
|
||||
AssocItemId, CrateModuleId, FunctionContainerId, HasModule, ImplId, LocalEnumVariantId,
|
||||
LocalStructFieldId, Lookup, ModuleId, UnionId,
|
||||
LocalStructFieldId, Lookup, ModuleId, TypeAliasContainerId, UnionId,
|
||||
};
|
||||
use hir_expand::{
|
||||
diagnostics::DiagnosticSink,
|
||||
|
@ -954,30 +954,34 @@ pub struct TypeAlias {
|
|||
|
||||
impl TypeAlias {
|
||||
pub fn module(self, db: &impl DefDatabase) -> Module {
|
||||
Module { id: self.id.module(db) }
|
||||
Module { id: self.id.lookup(db).module(db) }
|
||||
}
|
||||
|
||||
pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> {
|
||||
Some(self.module(db).krate())
|
||||
}
|
||||
|
||||
/// The containing impl block, if this is a method.
|
||||
/// The containing impl block, if this is a type alias.
|
||||
pub fn impl_block(self, db: &impl DefDatabase) -> Option<ImplBlock> {
|
||||
ImplBlock::containing(db, self.into())
|
||||
match self.container(db) {
|
||||
Some(Container::ImplBlock(it)) => Some(it),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// The containing trait, if this is a trait method definition.
|
||||
/// The containing trait, if this is a trait type alias definition.
|
||||
pub fn parent_trait(self, db: &impl DefDatabase) -> Option<Trait> {
|
||||
db.trait_items_index(self.module(db).id).get_parent_trait(self.id.into()).map(Trait::from)
|
||||
match self.container(db) {
|
||||
Some(Container::Trait(it)) => Some(it),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn container(self, db: &impl DefDatabase) -> Option<Container> {
|
||||
if let Some(impl_block) = self.impl_block(db) {
|
||||
Some(impl_block.into())
|
||||
} else if let Some(trait_) = self.parent_trait(db) {
|
||||
Some(trait_.into())
|
||||
} else {
|
||||
None
|
||||
match self.id.lookup(db).container {
|
||||
TypeAliasContainerId::TraitId(it) => Some(Container::Trait(it.into())),
|
||||
TypeAliasContainerId::ImplId(it) => Some(Container::ImplBlock(it.into())),
|
||||
TypeAliasContainerId::ModuleId(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -138,7 +138,7 @@ impl HasSource for Trait {
|
|||
impl HasSource for TypeAlias {
|
||||
type Ast = ast::TypeAliasDef;
|
||||
fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::TypeAliasDef> {
|
||||
self.id.source(db)
|
||||
self.id.lookup(db).source(db)
|
||||
}
|
||||
}
|
||||
impl HasSource for MacroDef {
|
||||
|
|
|
@ -4,7 +4,7 @@ use hir_def::{ModuleId, StructId, StructOrUnionId, UnionId};
|
|||
use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind};
|
||||
use ra_syntax::{
|
||||
ast::{self, AstNode, NameOwner},
|
||||
match_ast, AstPtr,
|
||||
match_ast, AstPtr, SyntaxNode,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
|
@ -52,48 +52,27 @@ impl FromSource for Trait {
|
|||
impl FromSource for Function {
|
||||
type Ast = ast::FnDef;
|
||||
fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> {
|
||||
// FIXME: this doesn't try to handle nested declarations
|
||||
for container in src.value.syntax().ancestors() {
|
||||
let res = match_ast! {
|
||||
match container {
|
||||
ast::TraitDef(it) => {
|
||||
let c = Trait::from_source(db, src.with_value(it))?;
|
||||
c.items(db)
|
||||
.into_iter()
|
||||
.filter_map(|it| match it {
|
||||
AssocItem::Function(it) => Some(it),
|
||||
_ => None
|
||||
})
|
||||
.find(|it| same_source(&it.source(db), &src))?
|
||||
},
|
||||
ast::ImplBlock(it) => {
|
||||
let c = ImplBlock::from_source(db, src.with_value(it))?;
|
||||
c.items(db)
|
||||
.into_iter()
|
||||
.filter_map(|it| match it {
|
||||
AssocItem::Function(it) => Some(it),
|
||||
_ => None
|
||||
})
|
||||
.find(|it| same_source(&it.source(db), &src))?
|
||||
|
||||
},
|
||||
_ => { continue },
|
||||
}
|
||||
};
|
||||
return Some(res);
|
||||
}
|
||||
|
||||
let module_source = ModuleSource::from_child_node(db, src.as_ref().map(|it| it.syntax()));
|
||||
let c = Module::from_definition(db, src.with_value(module_source))?;
|
||||
let res = c
|
||||
.declarations(db)
|
||||
let items = match Container::find(db, src.as_ref().map(|it| it.syntax()))? {
|
||||
Container::Trait(it) => it.items(db),
|
||||
Container::ImplBlock(it) => it.items(db),
|
||||
Container::Module(m) => {
|
||||
return m
|
||||
.declarations(db)
|
||||
.into_iter()
|
||||
.filter_map(|it| match it {
|
||||
ModuleDef::Function(it) => Some(it),
|
||||
_ => None,
|
||||
})
|
||||
.find(|it| same_source(&it.source(db), &src))
|
||||
}
|
||||
};
|
||||
items
|
||||
.into_iter()
|
||||
.filter_map(|it| match it {
|
||||
ModuleDef::Function(it) => Some(it),
|
||||
AssocItem::Function(it) => Some(it),
|
||||
_ => None,
|
||||
})
|
||||
.find(|it| same_source(&it.source(db), &src));
|
||||
res
|
||||
.find(|it| same_source(&it.source(db), &src))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -114,8 +93,27 @@ impl FromSource for Static {
|
|||
impl FromSource for TypeAlias {
|
||||
type Ast = ast::TypeAliasDef;
|
||||
fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> {
|
||||
let id = from_source(db, src)?;
|
||||
Some(TypeAlias { id })
|
||||
let items = match Container::find(db, src.as_ref().map(|it| it.syntax()))? {
|
||||
Container::Trait(it) => it.items(db),
|
||||
Container::ImplBlock(it) => it.items(db),
|
||||
Container::Module(m) => {
|
||||
return m
|
||||
.declarations(db)
|
||||
.into_iter()
|
||||
.filter_map(|it| match it {
|
||||
ModuleDef::TypeAlias(it) => Some(it),
|
||||
_ => None,
|
||||
})
|
||||
.find(|it| same_source(&it.source(db), &src))
|
||||
}
|
||||
};
|
||||
items
|
||||
.into_iter()
|
||||
.filter_map(|it| match it {
|
||||
AssocItem::TypeAlias(it) => Some(it),
|
||||
_ => None,
|
||||
})
|
||||
.find(|it| same_source(&it.source(db), &src))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -258,6 +256,38 @@ where
|
|||
Some(DEF::from_ast(ctx, &src.value))
|
||||
}
|
||||
|
||||
enum Container {
|
||||
Trait(Trait),
|
||||
ImplBlock(ImplBlock),
|
||||
Module(Module),
|
||||
}
|
||||
|
||||
impl Container {
|
||||
fn find(db: &impl DefDatabase, src: Source<&SyntaxNode>) -> Option<Container> {
|
||||
// FIXME: this doesn't try to handle nested declarations
|
||||
for container in src.value.ancestors() {
|
||||
let res = match_ast! {
|
||||
match container {
|
||||
ast::TraitDef(it) => {
|
||||
let c = Trait::from_source(db, src.with_value(it))?;
|
||||
Container::Trait(c)
|
||||
},
|
||||
ast::ImplBlock(it) => {
|
||||
let c = ImplBlock::from_source(db, src.with_value(it))?;
|
||||
Container::ImplBlock(c)
|
||||
},
|
||||
_ => { continue },
|
||||
}
|
||||
};
|
||||
return Some(res);
|
||||
}
|
||||
|
||||
let module_source = ModuleSource::from_child_node(db, src);
|
||||
let c = Module::from_definition(db, src.with_value(module_source))?;
|
||||
Some(Container::Module(c))
|
||||
}
|
||||
}
|
||||
|
||||
/// XXX: AST Nodes and SyntaxNodes have identity equality semantics: nodes are
|
||||
/// equal if they point to exactly the same object.
|
||||
///
|
||||
|
|
|
@ -14,13 +14,13 @@ use crate::{
|
|||
CrateDefMap,
|
||||
},
|
||||
traits::{TraitData, TraitItemsIndex},
|
||||
DefWithBodyId, EnumId, FunctionLoc, ImplId, ItemLoc, ModuleId, StructOrUnionId, TraitId,
|
||||
DefWithBodyId, EnumId, ImplId, ItemLoc, ModuleId, StructOrUnionId, TraitId,
|
||||
};
|
||||
|
||||
#[salsa::query_group(InternDatabaseStorage)]
|
||||
pub trait InternDatabase: SourceDatabase {
|
||||
#[salsa::interned]
|
||||
fn intern_function(&self, loc: FunctionLoc) -> crate::FunctionId;
|
||||
fn intern_function(&self, loc: crate::FunctionLoc) -> crate::FunctionId;
|
||||
#[salsa::interned]
|
||||
fn intern_struct_or_union(&self, loc: ItemLoc<ast::StructDef>) -> crate::StructOrUnionId;
|
||||
#[salsa::interned]
|
||||
|
@ -32,7 +32,7 @@ pub trait InternDatabase: SourceDatabase {
|
|||
#[salsa::interned]
|
||||
fn intern_trait(&self, loc: ItemLoc<ast::TraitDef>) -> crate::TraitId;
|
||||
#[salsa::interned]
|
||||
fn intern_type_alias(&self, loc: ItemLoc<ast::TypeAliasDef>) -> crate::TypeAliasId;
|
||||
fn intern_type_alias(&self, loc: crate::TypeAliasLoc) -> crate::TypeAliasId;
|
||||
#[salsa::interned]
|
||||
fn intern_impl(&self, loc: ItemLoc<ast::ImplBlock>) -> crate::ImplId;
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@ impl GenericParams {
|
|||
let self_param = TypeRef::Path(name::SELF_TYPE.into());
|
||||
generics.fill_bounds(&it.source(db).value, self_param);
|
||||
}
|
||||
GenericDefId::TypeAliasId(it) => generics.fill(&it.source(db).value, start),
|
||||
GenericDefId::TypeAliasId(it) => generics.fill(&it.lookup(db).source(db).value, start),
|
||||
// Note that we don't add `Self` here: in `impl`s, `Self` is not a
|
||||
// type-parameter, but rather is a type-alias for impl's target
|
||||
// type, so this is handled by the resolver.
|
||||
|
|
|
@ -10,7 +10,7 @@ use ra_syntax::ast;
|
|||
|
||||
use crate::{
|
||||
db::DefDatabase2, type_ref::TypeRef, AssocItemId, AstItemDef, ConstId, FunctionContainerId,
|
||||
FunctionLoc, ImplId, Intern, LocationCtx, TypeAliasId,
|
||||
FunctionLoc, ImplId, Intern, LocationCtx, TypeAliasContainerId, TypeAliasLoc,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
|
@ -36,18 +36,23 @@ impl ImplData {
|
|||
.impl_items()
|
||||
.map(|item_node| match item_node {
|
||||
ast::ImplItem::FnDef(it) => {
|
||||
let func_id = FunctionLoc {
|
||||
let def = FunctionLoc {
|
||||
container: FunctionContainerId::ImplId(id),
|
||||
ast_id: AstId::new(src.file_id, items.ast_id(&it)),
|
||||
}
|
||||
.intern(db);
|
||||
func_id.into()
|
||||
def.into()
|
||||
}
|
||||
ast::ImplItem::ConstDef(it) => {
|
||||
ConstId::from_ast_id(ctx, items.ast_id(&it)).into()
|
||||
}
|
||||
ast::ImplItem::TypeAliasDef(it) => {
|
||||
TypeAliasId::from_ast_id(ctx, items.ast_id(&it)).into()
|
||||
let def = TypeAliasLoc {
|
||||
container: TypeAliasContainerId::ImplId(id),
|
||||
ast_id: AstId::new(src.file_id, items.ast_id(&it)),
|
||||
}
|
||||
.intern(db);
|
||||
def.into()
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
|
|
|
@ -332,15 +332,34 @@ impl AstItemDef<ast::TraitDef> for TraitId {
|
|||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct TypeAliasId(salsa::InternId);
|
||||
impl_intern_key!(TypeAliasId);
|
||||
impl AstItemDef<ast::TypeAliasDef> for TypeAliasId {
|
||||
fn intern(db: &impl InternDatabase, loc: ItemLoc<ast::TypeAliasDef>) -> Self {
|
||||
db.intern_type_alias(loc)
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct TypeAliasLoc {
|
||||
pub container: TypeAliasContainerId,
|
||||
pub ast_id: AstId<ast::TypeAliasDef>,
|
||||
}
|
||||
|
||||
impl Intern for TypeAliasLoc {
|
||||
type ID = TypeAliasId;
|
||||
fn intern(self, db: &impl db::DefDatabase2) -> TypeAliasId {
|
||||
db.intern_type_alias(self)
|
||||
}
|
||||
fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc<ast::TypeAliasDef> {
|
||||
db.lookup_intern_type_alias(self)
|
||||
}
|
||||
|
||||
impl Lookup for TypeAliasId {
|
||||
type Data = TypeAliasLoc;
|
||||
fn lookup(&self, db: &impl db::DefDatabase2) -> TypeAliasLoc {
|
||||
db.lookup_intern_type_alias(*self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum TypeAliasContainerId {
|
||||
ModuleId(ModuleId),
|
||||
ImplId(ImplId),
|
||||
TraitId(TraitId),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct ImplId(salsa::InternId);
|
||||
impl_intern_key!(ImplId);
|
||||
|
@ -476,6 +495,16 @@ impl HasModule for FunctionLoc {
|
|||
}
|
||||
}
|
||||
|
||||
impl HasModule for TypeAliasLoc {
|
||||
fn module(&self, db: &impl db::DefDatabase2) -> ModuleId {
|
||||
match self.container {
|
||||
TypeAliasContainerId::ModuleId(it) => it,
|
||||
TypeAliasContainerId::ImplId(it) => it.module(db),
|
||||
TypeAliasContainerId::TraitId(it) => it.module(db),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait HasSource {
|
||||
type Value;
|
||||
fn source(&self, db: &impl db::DefDatabase2) -> Source<Self::Value>;
|
||||
|
@ -489,3 +518,12 @@ impl HasSource for FunctionLoc {
|
|||
Source::new(self.ast_id.file_id(), node)
|
||||
}
|
||||
}
|
||||
|
||||
impl HasSource for TypeAliasLoc {
|
||||
type Value = ast::TypeAliasDef;
|
||||
|
||||
fn source(&self, db: &impl db::DefDatabase2) -> Source<ast::TypeAliasDef> {
|
||||
let node = self.ast_id.to_node(db);
|
||||
Source::new(self.ast_id.file_id(), node)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ use crate::{
|
|||
path::{Path, PathKind},
|
||||
AdtId, AstId, AstItemDef, ConstId, CrateModuleId, EnumId, EnumVariantId, FunctionContainerId,
|
||||
FunctionLoc, ImplId, Intern, LocationCtx, ModuleDefId, ModuleId, StaticId, StructId,
|
||||
StructOrUnionId, TraitId, TypeAliasId, UnionId,
|
||||
StructOrUnionId, TraitId, TypeAliasContainerId, TypeAliasLoc, UnionId,
|
||||
};
|
||||
|
||||
pub(super) fn collect_defs(db: &impl DefDatabase2, mut def_map: CrateDefMap) -> CrateDefMap {
|
||||
|
@ -673,13 +673,13 @@ where
|
|||
let name = def.name.clone();
|
||||
let def: PerNs = match def.kind {
|
||||
raw::DefKind::Function(ast_id) => {
|
||||
let f = FunctionLoc {
|
||||
let def = FunctionLoc {
|
||||
container: FunctionContainerId::ModuleId(module),
|
||||
ast_id: AstId::new(self.file_id, ast_id),
|
||||
}
|
||||
.intern(self.def_collector.db);
|
||||
|
||||
PerNs::values(f.into())
|
||||
PerNs::values(def.into())
|
||||
}
|
||||
raw::DefKind::Struct(ast_id) => {
|
||||
let id = StructOrUnionId::from_ast_id(ctx, ast_id).into();
|
||||
|
@ -698,7 +698,13 @@ where
|
|||
}
|
||||
raw::DefKind::Trait(ast_id) => PerNs::types(TraitId::from_ast_id(ctx, ast_id).into()),
|
||||
raw::DefKind::TypeAlias(ast_id) => {
|
||||
PerNs::types(TypeAliasId::from_ast_id(ctx, ast_id).into())
|
||||
let def = TypeAliasLoc {
|
||||
container: TypeAliasContainerId::ModuleId(module),
|
||||
ast_id: AstId::new(self.file_id, ast_id),
|
||||
}
|
||||
.intern(self.def_collector.db);
|
||||
|
||||
PerNs::types(def.into())
|
||||
}
|
||||
};
|
||||
let resolution = Resolution { def, import: None };
|
||||
|
|
|
@ -12,7 +12,7 @@ use rustc_hash::FxHashMap;
|
|||
|
||||
use crate::{
|
||||
db::DefDatabase2, AssocItemId, AstItemDef, ConstId, FunctionContainerId, FunctionLoc, Intern,
|
||||
LocationCtx, ModuleDefId, ModuleId, TraitId, TypeAliasId,
|
||||
LocationCtx, ModuleDefId, ModuleId, TraitId, TypeAliasContainerId, TypeAliasLoc,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
|
@ -41,7 +41,12 @@ impl TraitData {
|
|||
.intern(db)
|
||||
.into(),
|
||||
ast::ImplItem::ConstDef(it) => ConstId::from_ast(ctx, &it).into(),
|
||||
ast::ImplItem::TypeAliasDef(it) => TypeAliasId::from_ast(ctx, &it).into(),
|
||||
ast::ImplItem::TypeAliasDef(it) => TypeAliasLoc {
|
||||
container: TypeAliasContainerId::TraitId(tr),
|
||||
ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
|
||||
}
|
||||
.intern(db)
|
||||
.into(),
|
||||
})
|
||||
.collect()
|
||||
} else {
|
||||
|
@ -65,6 +70,7 @@ impl TraitItemsIndex {
|
|||
for item in db.trait_data(tr).items.iter() {
|
||||
match item {
|
||||
AssocItemId::FunctionId(_) => (),
|
||||
AssocItemId::TypeAliasId(_) => (),
|
||||
_ => {
|
||||
let prev = index.traits_by_def.insert(*item, tr);
|
||||
assert!(prev.is_none());
|
||||
|
|
Loading…
Reference in a new issue