mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-26 13:03:31 +00:00
Merge #2144
2144: move struct & enum data to hir_def r=matklad a=matklad Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
commit
9421e5be35
8 changed files with 214 additions and 201 deletions
|
@ -3,152 +3,16 @@
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use hir_def::{type_ref::TypeRef, LocalEnumVariantId};
|
use hir_def::adt::VariantData;
|
||||||
use hir_expand::name::AsName;
|
|
||||||
use ra_arena::{impl_arena_id, Arena, RawId};
|
|
||||||
use ra_syntax::ast::{self, NameOwner, StructKind, TypeAscriptionOwner};
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
db::{AstDatabase, DefDatabase, HirDatabase},
|
db::{DefDatabase, HirDatabase},
|
||||||
Enum, EnumVariant, FieldSource, HasSource, Module, Name, Source, Struct, StructField,
|
EnumVariant, Module, Name, Struct, StructField,
|
||||||
};
|
};
|
||||||
|
|
||||||
impl Struct {
|
impl Struct {
|
||||||
pub(crate) fn variant_data(self, db: &impl DefDatabase) -> Arc<VariantData> {
|
pub(crate) fn variant_data(self, db: &impl DefDatabase) -> Arc<VariantData> {
|
||||||
db.struct_data(self).variant_data.clone()
|
db.struct_data(self.id).variant_data.clone()
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Note that we use `StructData` for unions as well!
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
||||||
pub struct StructData {
|
|
||||||
pub(crate) name: Option<Name>,
|
|
||||||
pub(crate) variant_data: Arc<VariantData>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl StructData {
|
|
||||||
fn new(struct_def: &ast::StructDef) -> StructData {
|
|
||||||
let name = struct_def.name().map(|n| n.as_name());
|
|
||||||
let variant_data = VariantData::new(struct_def.kind());
|
|
||||||
let variant_data = Arc::new(variant_data);
|
|
||||||
StructData { name, variant_data }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn struct_data_query(
|
|
||||||
db: &(impl DefDatabase + AstDatabase),
|
|
||||||
struct_: Struct,
|
|
||||||
) -> Arc<StructData> {
|
|
||||||
let src = struct_.source(db);
|
|
||||||
Arc::new(StructData::new(&src.ast))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn variants(enum_def: &ast::EnumDef) -> impl Iterator<Item = ast::EnumVariant> {
|
|
||||||
enum_def.variant_list().into_iter().flat_map(|it| it.variants())
|
|
||||||
}
|
|
||||||
|
|
||||||
impl EnumVariant {
|
|
||||||
pub(crate) fn source_impl(
|
|
||||||
self,
|
|
||||||
db: &(impl DefDatabase + AstDatabase),
|
|
||||||
) -> Source<ast::EnumVariant> {
|
|
||||||
let src = self.parent.source(db);
|
|
||||||
let ast = variants(&src.ast)
|
|
||||||
.zip(db.enum_data(self.parent).variants.iter())
|
|
||||||
.find(|(_syntax, (id, _))| *id == self.id)
|
|
||||||
.unwrap()
|
|
||||||
.0;
|
|
||||||
Source { file_id: src.file_id, ast }
|
|
||||||
}
|
|
||||||
pub(crate) fn variant_data(self, db: &impl DefDatabase) -> Arc<VariantData> {
|
|
||||||
db.enum_data(self.parent).variants[self.id].variant_data.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
||||||
pub struct EnumData {
|
|
||||||
pub(crate) name: Option<Name>,
|
|
||||||
pub(crate) variants: Arena<LocalEnumVariantId, EnumVariantData>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl EnumData {
|
|
||||||
pub(crate) fn enum_data_query(db: &(impl DefDatabase + AstDatabase), e: Enum) -> Arc<EnumData> {
|
|
||||||
let src = e.source(db);
|
|
||||||
let name = src.ast.name().map(|n| n.as_name());
|
|
||||||
let variants = variants(&src.ast)
|
|
||||||
.map(|var| EnumVariantData {
|
|
||||||
name: var.name().map(|it| it.as_name()),
|
|
||||||
variant_data: Arc::new(VariantData::new(var.kind())),
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
Arc::new(EnumData { name, variants })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
||||||
pub(crate) struct EnumVariantData {
|
|
||||||
pub(crate) name: Option<Name>,
|
|
||||||
variant_data: Arc<VariantData>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
||||||
pub(crate) struct StructFieldId(RawId);
|
|
||||||
impl_arena_id!(StructFieldId);
|
|
||||||
|
|
||||||
/// A single field of an enum variant or struct
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
||||||
pub struct StructFieldData {
|
|
||||||
pub(crate) name: Name,
|
|
||||||
pub(crate) type_ref: TypeRef,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Fields of an enum variant or struct
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
||||||
pub(crate) struct VariantData(VariantDataInner);
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
||||||
enum VariantDataInner {
|
|
||||||
Struct(Arena<StructFieldId, StructFieldData>),
|
|
||||||
Tuple(Arena<StructFieldId, StructFieldData>),
|
|
||||||
Unit,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl VariantData {
|
|
||||||
pub(crate) fn fields(&self) -> Option<&Arena<StructFieldId, StructFieldData>> {
|
|
||||||
match &self.0 {
|
|
||||||
VariantDataInner::Struct(fields) | VariantDataInner::Tuple(fields) => Some(fields),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl VariantData {
|
|
||||||
fn new(flavor: StructKind) -> Self {
|
|
||||||
let inner = match flavor {
|
|
||||||
ast::StructKind::Tuple(fl) => {
|
|
||||||
let fields = fl
|
|
||||||
.fields()
|
|
||||||
.enumerate()
|
|
||||||
.map(|(i, fd)| StructFieldData {
|
|
||||||
name: Name::new_tuple_field(i),
|
|
||||||
type_ref: TypeRef::from_ast_opt(fd.type_ref()),
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
VariantDataInner::Tuple(fields)
|
|
||||||
}
|
|
||||||
ast::StructKind::Named(fl) => {
|
|
||||||
let fields = fl
|
|
||||||
.fields()
|
|
||||||
.map(|fd| StructFieldData {
|
|
||||||
name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing),
|
|
||||||
type_ref: TypeRef::from_ast_opt(fd.ascribed_type()),
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
VariantDataInner::Struct(fields)
|
|
||||||
}
|
|
||||||
ast::StructKind::Unit => VariantDataInner::Unit,
|
|
||||||
};
|
|
||||||
VariantData(inner)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,35 +52,3 @@ impl VariantDef {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StructField {
|
|
||||||
pub(crate) fn source_impl(&self, db: &(impl DefDatabase + AstDatabase)) -> Source<FieldSource> {
|
|
||||||
let var_data = self.parent.variant_data(db);
|
|
||||||
let fields = var_data.fields().unwrap();
|
|
||||||
let ss;
|
|
||||||
let es;
|
|
||||||
let (file_id, struct_kind) = match self.parent {
|
|
||||||
VariantDef::Struct(s) => {
|
|
||||||
ss = s.source(db);
|
|
||||||
(ss.file_id, ss.ast.kind())
|
|
||||||
}
|
|
||||||
VariantDef::EnumVariant(e) => {
|
|
||||||
es = e.source(db);
|
|
||||||
(es.file_id, es.ast.kind())
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let field_sources = match struct_kind {
|
|
||||||
ast::StructKind::Tuple(fl) => fl.fields().map(|it| FieldSource::Pos(it)).collect(),
|
|
||||||
ast::StructKind::Named(fl) => fl.fields().map(|it| FieldSource::Named(it)).collect(),
|
|
||||||
ast::StructKind::Unit => Vec::new(),
|
|
||||||
};
|
|
||||||
let ast = field_sources
|
|
||||||
.into_iter()
|
|
||||||
.zip(fields.iter())
|
|
||||||
.find(|(_syntax, (id, _))| *id == self.id)
|
|
||||||
.unwrap()
|
|
||||||
.0;
|
|
||||||
Source { file_id, ast }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -6,16 +6,17 @@ pub(crate) mod docs;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
|
adt::VariantData,
|
||||||
builtin_type::BuiltinType,
|
builtin_type::BuiltinType,
|
||||||
type_ref::{Mutability, TypeRef},
|
type_ref::{Mutability, TypeRef},
|
||||||
CrateModuleId, LocalEnumVariantId, ModuleId,
|
CrateModuleId, LocalEnumVariantId, LocalStructFieldId, ModuleId,
|
||||||
};
|
};
|
||||||
use hir_expand::name::{self, AsName};
|
use hir_expand::name::{self, AsName};
|
||||||
use ra_db::{CrateId, Edition};
|
use ra_db::{CrateId, Edition};
|
||||||
use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner};
|
use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
adt::{StructFieldId, VariantDef},
|
adt::VariantDef,
|
||||||
db::{AstDatabase, DefDatabase, HirDatabase},
|
db::{AstDatabase, DefDatabase, HirDatabase},
|
||||||
diagnostics::DiagnosticSink,
|
diagnostics::DiagnosticSink,
|
||||||
expr::{validation::ExprValidator, Body, BodySourceMap},
|
expr::{validation::ExprValidator, Body, BodySourceMap},
|
||||||
|
@ -250,7 +251,7 @@ impl Module {
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub struct StructField {
|
pub struct StructField {
|
||||||
pub(crate) parent: VariantDef,
|
pub(crate) parent: VariantDef,
|
||||||
pub(crate) id: StructFieldId,
|
pub(crate) id: LocalStructFieldId,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
@ -288,11 +289,11 @@ impl Struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn name(self, db: &impl DefDatabase) -> Option<Name> {
|
pub fn name(self, db: &impl DefDatabase) -> Option<Name> {
|
||||||
db.struct_data(self).name.clone()
|
db.struct_data(self.id).name.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fields(self, db: &impl HirDatabase) -> Vec<StructField> {
|
pub fn fields(self, db: &impl HirDatabase) -> Vec<StructField> {
|
||||||
db.struct_data(self)
|
db.struct_data(self.id)
|
||||||
.variant_data
|
.variant_data
|
||||||
.fields()
|
.fields()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
@ -302,7 +303,7 @@ impl Struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn field(self, db: &impl HirDatabase, name: &Name) -> Option<StructField> {
|
pub fn field(self, db: &impl HirDatabase, name: &Name) -> Option<StructField> {
|
||||||
db.struct_data(self)
|
db.struct_data(self.id)
|
||||||
.variant_data
|
.variant_data
|
||||||
.fields()
|
.fields()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
@ -338,7 +339,7 @@ pub struct Union {
|
||||||
|
|
||||||
impl Union {
|
impl Union {
|
||||||
pub fn name(self, db: &impl DefDatabase) -> Option<Name> {
|
pub fn name(self, db: &impl DefDatabase) -> Option<Name> {
|
||||||
db.struct_data(Struct { id: self.id }).name.clone()
|
db.struct_data(self.id).name.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn module(self, db: &impl HirDatabase) -> Module {
|
pub fn module(self, db: &impl HirDatabase) -> Module {
|
||||||
|
@ -376,15 +377,19 @@ impl Enum {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn name(self, db: &impl DefDatabase) -> Option<Name> {
|
pub fn name(self, db: &impl DefDatabase) -> Option<Name> {
|
||||||
db.enum_data(self).name.clone()
|
db.enum_data(self.id).name.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn variants(self, db: &impl DefDatabase) -> Vec<EnumVariant> {
|
pub fn variants(self, db: &impl DefDatabase) -> Vec<EnumVariant> {
|
||||||
db.enum_data(self).variants.iter().map(|(id, _)| EnumVariant { parent: self, id }).collect()
|
db.enum_data(self.id)
|
||||||
|
.variants
|
||||||
|
.iter()
|
||||||
|
.map(|(id, _)| EnumVariant { parent: self, id })
|
||||||
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn variant(self, db: &impl DefDatabase, name: &Name) -> Option<EnumVariant> {
|
pub fn variant(self, db: &impl DefDatabase, name: &Name) -> Option<EnumVariant> {
|
||||||
db.enum_data(self)
|
db.enum_data(self.id)
|
||||||
.variants
|
.variants
|
||||||
.iter()
|
.iter()
|
||||||
.find(|(_id, data)| data.name.as_ref() == Some(name))
|
.find(|(_id, data)| data.name.as_ref() == Some(name))
|
||||||
|
@ -422,7 +427,7 @@ impl EnumVariant {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn name(self, db: &impl DefDatabase) -> Option<Name> {
|
pub fn name(self, db: &impl DefDatabase) -> Option<Name> {
|
||||||
db.enum_data(self.parent).variants[self.id].name.clone()
|
db.enum_data(self.parent.id).variants[self.id].name.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fields(self, db: &impl HirDatabase) -> Vec<StructField> {
|
pub fn fields(self, db: &impl HirDatabase) -> Vec<StructField> {
|
||||||
|
@ -442,6 +447,10 @@ impl EnumVariant {
|
||||||
.find(|(_id, data)| data.name == *name)
|
.find(|(_id, data)| data.name == *name)
|
||||||
.map(|(id, _)| StructField { parent: self.into(), id })
|
.map(|(id, _)| StructField { parent: self.into(), id })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn variant_data(self, db: &impl DefDatabase) -> Arc<VariantData> {
|
||||||
|
db.enum_data(self.parent.id).variants[self.id].variant_data.clone()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A Data Type
|
/// A Data Type
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
use ra_syntax::ast::{self, AstNode};
|
use ra_syntax::ast::{self, AstNode};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
adt::VariantDef,
|
||||||
db::{AstDatabase, DefDatabase, HirDatabase},
|
db::{AstDatabase, DefDatabase, HirDatabase},
|
||||||
ids::AstItemDef,
|
ids::AstItemDef,
|
||||||
Const, Either, Enum, EnumVariant, FieldSource, Function, HasBody, HirFileId, MacroDef, Module,
|
Const, Either, Enum, EnumVariant, FieldSource, Function, HasBody, HirFileId, MacroDef, Module,
|
||||||
|
@ -45,7 +46,33 @@ impl Module {
|
||||||
impl HasSource for StructField {
|
impl HasSource for StructField {
|
||||||
type Ast = FieldSource;
|
type Ast = FieldSource;
|
||||||
fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<FieldSource> {
|
fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<FieldSource> {
|
||||||
self.source_impl(db)
|
let var_data = self.parent.variant_data(db);
|
||||||
|
let fields = var_data.fields().unwrap();
|
||||||
|
let ss;
|
||||||
|
let es;
|
||||||
|
let (file_id, struct_kind) = match self.parent {
|
||||||
|
VariantDef::Struct(s) => {
|
||||||
|
ss = s.source(db);
|
||||||
|
(ss.file_id, ss.ast.kind())
|
||||||
|
}
|
||||||
|
VariantDef::EnumVariant(e) => {
|
||||||
|
es = e.source(db);
|
||||||
|
(es.file_id, es.ast.kind())
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let field_sources = match struct_kind {
|
||||||
|
ast::StructKind::Tuple(fl) => fl.fields().map(|it| FieldSource::Pos(it)).collect(),
|
||||||
|
ast::StructKind::Named(fl) => fl.fields().map(|it| FieldSource::Named(it)).collect(),
|
||||||
|
ast::StructKind::Unit => Vec::new(),
|
||||||
|
};
|
||||||
|
let ast = field_sources
|
||||||
|
.into_iter()
|
||||||
|
.zip(fields.iter())
|
||||||
|
.find(|(_syntax, (id, _))| *id == self.id)
|
||||||
|
.unwrap()
|
||||||
|
.0;
|
||||||
|
Source { file_id, ast }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl HasSource for Struct {
|
impl HasSource for Struct {
|
||||||
|
@ -69,7 +96,18 @@ impl HasSource for Enum {
|
||||||
impl HasSource for EnumVariant {
|
impl HasSource for EnumVariant {
|
||||||
type Ast = ast::EnumVariant;
|
type Ast = ast::EnumVariant;
|
||||||
fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::EnumVariant> {
|
fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::EnumVariant> {
|
||||||
self.source_impl(db)
|
let enum_data = db.enum_data(self.parent.id);
|
||||||
|
let src = self.parent.id.source(db);
|
||||||
|
let ast = src
|
||||||
|
.ast
|
||||||
|
.variant_list()
|
||||||
|
.into_iter()
|
||||||
|
.flat_map(|it| it.variants())
|
||||||
|
.zip(enum_data.variants.iter())
|
||||||
|
.find(|(_syntax, (id, _))| *id == self.id)
|
||||||
|
.unwrap()
|
||||||
|
.0;
|
||||||
|
Source { file_id: src.file_id, ast }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl HasSource for Function {
|
impl HasSource for Function {
|
||||||
|
|
|
@ -6,7 +6,6 @@ use ra_db::salsa;
|
||||||
use ra_syntax::SmolStr;
|
use ra_syntax::SmolStr;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
adt::{EnumData, StructData},
|
|
||||||
debug::HirDebugDatabase,
|
debug::HirDebugDatabase,
|
||||||
generics::{GenericDef, GenericParams},
|
generics::{GenericDef, GenericParams},
|
||||||
ids,
|
ids,
|
||||||
|
@ -19,13 +18,13 @@ use crate::{
|
||||||
InferenceResult, Substs, Ty, TypableDef, TypeCtor,
|
InferenceResult, Substs, Ty, TypableDef, TypeCtor,
|
||||||
},
|
},
|
||||||
type_alias::TypeAliasData,
|
type_alias::TypeAliasData,
|
||||||
Const, ConstData, Crate, DefWithBody, Enum, ExprScopes, FnData, Function, Module, Static,
|
Const, ConstData, Crate, DefWithBody, ExprScopes, FnData, Function, Module, Static,
|
||||||
Struct, StructField, Trait, TypeAlias,
|
StructField, Trait, TypeAlias,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use hir_def::db::{
|
pub use hir_def::db::{
|
||||||
DefDatabase2, DefDatabase2Storage, InternDatabase, InternDatabaseStorage, RawItemsQuery,
|
DefDatabase2, DefDatabase2Storage, EnumDataQuery, InternDatabase, InternDatabaseStorage,
|
||||||
RawItemsWithSourceMapQuery,
|
RawItemsQuery, RawItemsWithSourceMapQuery, StructDataQuery,
|
||||||
};
|
};
|
||||||
pub use hir_expand::db::{
|
pub use hir_expand::db::{
|
||||||
AstDatabase, AstDatabaseStorage, AstIdMapQuery, MacroArgQuery, MacroDefQuery, MacroExpandQuery,
|
AstDatabase, AstDatabaseStorage, AstIdMapQuery, MacroArgQuery, MacroDefQuery, MacroExpandQuery,
|
||||||
|
@ -36,12 +35,6 @@ pub use hir_expand::db::{
|
||||||
#[salsa::query_group(DefDatabaseStorage)]
|
#[salsa::query_group(DefDatabaseStorage)]
|
||||||
#[salsa::requires(AstDatabase)]
|
#[salsa::requires(AstDatabase)]
|
||||||
pub trait DefDatabase: HirDebugDatabase + DefDatabase2 {
|
pub trait DefDatabase: HirDebugDatabase + DefDatabase2 {
|
||||||
#[salsa::invoke(crate::adt::StructData::struct_data_query)]
|
|
||||||
fn struct_data(&self, s: Struct) -> Arc<StructData>;
|
|
||||||
|
|
||||||
#[salsa::invoke(crate::adt::EnumData::enum_data_query)]
|
|
||||||
fn enum_data(&self, e: Enum) -> Arc<EnumData>;
|
|
||||||
|
|
||||||
#[salsa::invoke(crate::traits::TraitData::trait_data_query)]
|
#[salsa::invoke(crate::traits::TraitData::trait_data_query)]
|
||||||
fn trait_data(&self, t: Trait) -> Arc<TraitData>;
|
fn trait_data(&self, t: Trait) -> Arc<TraitData>;
|
||||||
|
|
||||||
|
|
|
@ -655,8 +655,8 @@ fn type_for_builtin(def: BuiltinType) -> Ty {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> FnSig {
|
fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> FnSig {
|
||||||
let var_data = def.variant_data(db);
|
let struct_data = db.struct_data(def.id);
|
||||||
let fields = match var_data.fields() {
|
let fields = match struct_data.variant_data.fields() {
|
||||||
Some(fields) => fields,
|
Some(fields) => fields,
|
||||||
None => panic!("fn_sig_for_struct_constructor called on unit struct"),
|
None => panic!("fn_sig_for_struct_constructor called on unit struct"),
|
||||||
};
|
};
|
||||||
|
@ -671,8 +671,8 @@ fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> FnSig {
|
||||||
|
|
||||||
/// Build the type of a tuple struct constructor.
|
/// Build the type of a tuple struct constructor.
|
||||||
fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty {
|
fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty {
|
||||||
let var_data = def.variant_data(db);
|
let struct_data = db.struct_data(def.id);
|
||||||
if var_data.fields().is_none() {
|
if struct_data.variant_data.fields().is_none() {
|
||||||
return type_for_adt(db, def); // Unit struct
|
return type_for_adt(db, def); // Unit struct
|
||||||
}
|
}
|
||||||
let generics = def.generic_params(db);
|
let generics = def.generic_params(db);
|
||||||
|
|
114
crates/ra_hir_def/src/adt.rs
Normal file
114
crates/ra_hir_def/src/adt.rs
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
//! Defines hir-level representation of structs, enums and unions
|
||||||
|
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use hir_expand::name::{AsName, Name};
|
||||||
|
use ra_arena::Arena;
|
||||||
|
use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
db::DefDatabase2, type_ref::TypeRef, AstItemDef, EnumId, LocalEnumVariantId,
|
||||||
|
LocalStructFieldId, StructId,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Note that we use `StructData` for unions as well!
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub struct StructData {
|
||||||
|
pub name: Option<Name>,
|
||||||
|
pub variant_data: Arc<VariantData>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub struct EnumData {
|
||||||
|
pub name: Option<Name>,
|
||||||
|
pub variants: Arena<LocalEnumVariantId, EnumVariantData>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub struct EnumVariantData {
|
||||||
|
pub name: Option<Name>,
|
||||||
|
pub variant_data: Arc<VariantData>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fields of an enum variant or struct
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub struct VariantData(VariantDataInner);
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
enum VariantDataInner {
|
||||||
|
Struct(Arena<LocalStructFieldId, StructFieldData>),
|
||||||
|
Tuple(Arena<LocalStructFieldId, StructFieldData>),
|
||||||
|
Unit,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A single field of an enum variant or struct
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub struct StructFieldData {
|
||||||
|
pub name: Name,
|
||||||
|
pub type_ref: TypeRef,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StructData {
|
||||||
|
pub(crate) fn struct_data_query(db: &impl DefDatabase2, struct_: StructId) -> Arc<StructData> {
|
||||||
|
let src = struct_.source(db);
|
||||||
|
let name = src.ast.name().map(|n| n.as_name());
|
||||||
|
let variant_data = VariantData::new(src.ast.kind());
|
||||||
|
let variant_data = Arc::new(variant_data);
|
||||||
|
Arc::new(StructData { name, variant_data })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EnumData {
|
||||||
|
pub(crate) fn enum_data_query(db: &impl DefDatabase2, e: EnumId) -> Arc<EnumData> {
|
||||||
|
let src = e.source(db);
|
||||||
|
let name = src.ast.name().map(|n| n.as_name());
|
||||||
|
let variants = src
|
||||||
|
.ast
|
||||||
|
.variant_list()
|
||||||
|
.into_iter()
|
||||||
|
.flat_map(|it| it.variants())
|
||||||
|
.map(|var| EnumVariantData {
|
||||||
|
name: var.name().map(|it| it.as_name()),
|
||||||
|
variant_data: Arc::new(VariantData::new(var.kind())),
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
Arc::new(EnumData { name, variants })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VariantData {
|
||||||
|
fn new(flavor: ast::StructKind) -> Self {
|
||||||
|
let inner = match flavor {
|
||||||
|
ast::StructKind::Tuple(fl) => {
|
||||||
|
let fields = fl
|
||||||
|
.fields()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(i, fd)| StructFieldData {
|
||||||
|
name: Name::new_tuple_field(i),
|
||||||
|
type_ref: TypeRef::from_ast_opt(fd.type_ref()),
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
VariantDataInner::Tuple(fields)
|
||||||
|
}
|
||||||
|
ast::StructKind::Named(fl) => {
|
||||||
|
let fields = fl
|
||||||
|
.fields()
|
||||||
|
.map(|fd| StructFieldData {
|
||||||
|
name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing),
|
||||||
|
type_ref: TypeRef::from_ast_opt(fd.ascribed_type()),
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
VariantDataInner::Struct(fields)
|
||||||
|
}
|
||||||
|
ast::StructKind::Unit => VariantDataInner::Unit,
|
||||||
|
};
|
||||||
|
VariantData(inner)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fields(&self) -> Option<&Arena<LocalStructFieldId, StructFieldData>> {
|
||||||
|
match &self.0 {
|
||||||
|
VariantDataInner::Struct(fields) | VariantDataInner::Tuple(fields) => Some(fields),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,7 +5,11 @@ use hir_expand::{db::AstDatabase, HirFileId};
|
||||||
use ra_db::{salsa, SourceDatabase};
|
use ra_db::{salsa, SourceDatabase};
|
||||||
use ra_syntax::ast;
|
use ra_syntax::ast;
|
||||||
|
|
||||||
use crate::nameres::raw::{ImportSourceMap, RawItems};
|
use crate::{
|
||||||
|
adt::{EnumData, StructData},
|
||||||
|
nameres::raw::{ImportSourceMap, RawItems},
|
||||||
|
EnumId, StructId,
|
||||||
|
};
|
||||||
|
|
||||||
#[salsa::query_group(InternDatabaseStorage)]
|
#[salsa::query_group(InternDatabaseStorage)]
|
||||||
pub trait InternDatabase: SourceDatabase {
|
pub trait InternDatabase: SourceDatabase {
|
||||||
|
@ -37,4 +41,10 @@ pub trait DefDatabase2: InternDatabase + AstDatabase {
|
||||||
|
|
||||||
#[salsa::invoke(RawItems::raw_items_query)]
|
#[salsa::invoke(RawItems::raw_items_query)]
|
||||||
fn raw_items(&self, file_id: HirFileId) -> Arc<RawItems>;
|
fn raw_items(&self, file_id: HirFileId) -> Arc<RawItems>;
|
||||||
|
|
||||||
|
#[salsa::invoke(StructData::struct_data_query)]
|
||||||
|
fn struct_data(&self, s: StructId) -> Arc<StructData>;
|
||||||
|
|
||||||
|
#[salsa::invoke(EnumData::enum_data_query)]
|
||||||
|
fn enum_data(&self, e: EnumId) -> Arc<EnumData>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ pub mod attr;
|
||||||
pub mod path;
|
pub mod path;
|
||||||
pub mod type_ref;
|
pub mod type_ref;
|
||||||
pub mod builtin_type;
|
pub mod builtin_type;
|
||||||
|
pub mod adt;
|
||||||
|
|
||||||
// FIXME: this should be private
|
// FIXME: this should be private
|
||||||
pub mod nameres;
|
pub mod nameres;
|
||||||
|
@ -259,6 +260,22 @@ pub struct EnumVariantId {
|
||||||
pub struct LocalEnumVariantId(RawId);
|
pub struct LocalEnumVariantId(RawId);
|
||||||
impl_arena_id!(LocalEnumVariantId);
|
impl_arena_id!(LocalEnumVariantId);
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
pub enum VariantId {
|
||||||
|
EnumVariantId(EnumVariantId),
|
||||||
|
StructId(StructId),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
pub struct StructFieldId {
|
||||||
|
parent: VariantId,
|
||||||
|
local_id: LocalStructFieldId,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
pub struct LocalStructFieldId(RawId);
|
||||||
|
impl_arena_id!(LocalStructFieldId);
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub struct ConstId(salsa::InternId);
|
pub struct ConstId(salsa::InternId);
|
||||||
impl_intern_key!(ConstId);
|
impl_intern_key!(ConstId);
|
||||||
|
|
Loading…
Reference in a new issue