diff options
-rw-r--r-- | crates/ra_hir/src/adt.rs | 176 | ||||
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 31 | ||||
-rw-r--r-- | crates/ra_hir/src/code_model/src.rs | 42 | ||||
-rw-r--r-- | crates/ra_hir/src/db.rs | 15 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/lower.rs | 8 | ||||
-rw-r--r-- | crates/ra_hir_def/src/adt.rs | 114 | ||||
-rw-r--r-- | crates/ra_hir_def/src/db.rs | 12 | ||||
-rw-r--r-- | crates/ra_hir_def/src/lib.rs | 17 |
8 files changed, 214 insertions, 201 deletions
diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs index 4fa2062bd..0436d20b7 100644 --- a/crates/ra_hir/src/adt.rs +++ b/crates/ra_hir/src/adt.rs | |||
@@ -3,152 +3,16 @@ | |||
3 | 3 | ||
4 | use std::sync::Arc; | 4 | use std::sync::Arc; |
5 | 5 | ||
6 | use hir_def::{type_ref::TypeRef, LocalEnumVariantId}; | 6 | use hir_def::adt::VariantData; |
7 | use hir_expand::name::AsName; | ||
8 | use ra_arena::{impl_arena_id, Arena, RawId}; | ||
9 | use ra_syntax::ast::{self, NameOwner, StructKind, TypeAscriptionOwner}; | ||
10 | 7 | ||
11 | use crate::{ | 8 | use crate::{ |
12 | db::{AstDatabase, DefDatabase, HirDatabase}, | 9 | db::{DefDatabase, HirDatabase}, |
13 | Enum, EnumVariant, FieldSource, HasSource, Module, Name, Source, Struct, StructField, | 10 | EnumVariant, Module, Name, Struct, StructField, |
14 | }; | 11 | }; |
15 | 12 | ||
16 | impl Struct { | 13 | impl Struct { |
17 | pub(crate) fn variant_data(self, db: &impl DefDatabase) -> Arc<VariantData> { | 14 | pub(crate) fn variant_data(self, db: &impl DefDatabase) -> Arc<VariantData> { |
18 | db.struct_data(self).variant_data.clone() | 15 | db.struct_data(self.id).variant_data.clone() |
19 | } | ||
20 | } | ||
21 | |||
22 | /// Note that we use `StructData` for unions as well! | ||
23 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
24 | pub struct StructData { | ||
25 | pub(crate) name: Option<Name>, | ||
26 | pub(crate) variant_data: Arc<VariantData>, | ||
27 | } | ||
28 | |||
29 | impl StructData { | ||
30 | fn new(struct_def: &ast::StructDef) -> StructData { | ||
31 | let name = struct_def.name().map(|n| n.as_name()); | ||
32 | let variant_data = VariantData::new(struct_def.kind()); | ||
33 | let variant_data = Arc::new(variant_data); | ||
34 | StructData { name, variant_data } | ||
35 | } | ||
36 | |||
37 | pub(crate) fn struct_data_query( | ||
38 | db: &(impl DefDatabase + AstDatabase), | ||
39 | struct_: Struct, | ||
40 | ) -> Arc<StructData> { | ||
41 | let src = struct_.source(db); | ||
42 | Arc::new(StructData::new(&src.ast)) | ||
43 | } | ||
44 | } | ||
45 | |||
46 | fn variants(enum_def: &ast::EnumDef) -> impl Iterator<Item = ast::EnumVariant> { | ||
47 | enum_def.variant_list().into_iter().flat_map(|it| it.variants()) | ||
48 | } | ||
49 | |||
50 | impl EnumVariant { | ||
51 | pub(crate) fn source_impl( | ||
52 | self, | ||
53 | db: &(impl DefDatabase + AstDatabase), | ||
54 | ) -> Source<ast::EnumVariant> { | ||
55 | let src = self.parent.source(db); | ||
56 | let ast = variants(&src.ast) | ||
57 | .zip(db.enum_data(self.parent).variants.iter()) | ||
58 | .find(|(_syntax, (id, _))| *id == self.id) | ||
59 | .unwrap() | ||
60 | .0; | ||
61 | Source { file_id: src.file_id, ast } | ||
62 | } | ||
63 | pub(crate) fn variant_data(self, db: &impl DefDatabase) -> Arc<VariantData> { | ||
64 | db.enum_data(self.parent).variants[self.id].variant_data.clone() | ||
65 | } | ||
66 | } | ||
67 | |||
68 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
69 | pub struct EnumData { | ||
70 | pub(crate) name: Option<Name>, | ||
71 | pub(crate) variants: Arena<LocalEnumVariantId, EnumVariantData>, | ||
72 | } | ||
73 | |||
74 | impl EnumData { | ||
75 | pub(crate) fn enum_data_query(db: &(impl DefDatabase + AstDatabase), e: Enum) -> Arc<EnumData> { | ||
76 | let src = e.source(db); | ||
77 | let name = src.ast.name().map(|n| n.as_name()); | ||
78 | let variants = variants(&src.ast) | ||
79 | .map(|var| EnumVariantData { | ||
80 | name: var.name().map(|it| it.as_name()), | ||
81 | variant_data: Arc::new(VariantData::new(var.kind())), | ||
82 | }) | ||
83 | .collect(); | ||
84 | Arc::new(EnumData { name, variants }) | ||
85 | } | ||
86 | } | ||
87 | |||
88 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
89 | pub(crate) struct EnumVariantData { | ||
90 | pub(crate) name: Option<Name>, | ||
91 | variant_data: Arc<VariantData>, | ||
92 | } | ||
93 | |||
94 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
95 | pub(crate) struct StructFieldId(RawId); | ||
96 | impl_arena_id!(StructFieldId); | ||
97 | |||
98 | /// A single field of an enum variant or struct | ||
99 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
100 | pub struct StructFieldData { | ||
101 | pub(crate) name: Name, | ||
102 | pub(crate) type_ref: TypeRef, | ||
103 | } | ||
104 | |||
105 | /// Fields of an enum variant or struct | ||
106 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
107 | pub(crate) struct VariantData(VariantDataInner); | ||
108 | |||
109 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
110 | enum VariantDataInner { | ||
111 | Struct(Arena<StructFieldId, StructFieldData>), | ||
112 | Tuple(Arena<StructFieldId, StructFieldData>), | ||
113 | Unit, | ||
114 | } | ||
115 | |||
116 | impl VariantData { | ||
117 | pub(crate) fn fields(&self) -> Option<&Arena<StructFieldId, StructFieldData>> { | ||
118 | match &self.0 { | ||
119 | VariantDataInner::Struct(fields) | VariantDataInner::Tuple(fields) => Some(fields), | ||
120 | _ => None, | ||
121 | } | ||
122 | } | ||
123 | } | ||
124 | |||
125 | impl VariantData { | ||
126 | fn new(flavor: StructKind) -> Self { | ||
127 | let inner = match flavor { | ||
128 | ast::StructKind::Tuple(fl) => { | ||
129 | let fields = fl | ||
130 | .fields() | ||
131 | .enumerate() | ||
132 | .map(|(i, fd)| StructFieldData { | ||
133 | name: Name::new_tuple_field(i), | ||
134 | type_ref: TypeRef::from_ast_opt(fd.type_ref()), | ||
135 | }) | ||
136 | .collect(); | ||
137 | VariantDataInner::Tuple(fields) | ||
138 | } | ||
139 | ast::StructKind::Named(fl) => { | ||
140 | let fields = fl | ||
141 | .fields() | ||
142 | .map(|fd| StructFieldData { | ||
143 | name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing), | ||
144 | type_ref: TypeRef::from_ast_opt(fd.ascribed_type()), | ||
145 | }) | ||
146 | .collect(); | ||
147 | VariantDataInner::Struct(fields) | ||
148 | } | ||
149 | ast::StructKind::Unit => VariantDataInner::Unit, | ||
150 | }; | ||
151 | VariantData(inner) | ||
152 | } | 16 | } |
153 | } | 17 | } |
154 | 18 | ||
@@ -188,35 +52,3 @@ impl VariantDef { | |||
188 | } | 52 | } |
189 | } | 53 | } |
190 | } | 54 | } |
191 | |||
192 | impl StructField { | ||
193 | pub(crate) fn source_impl(&self, db: &(impl DefDatabase + AstDatabase)) -> Source<FieldSource> { | ||
194 | let var_data = self.parent.variant_data(db); | ||
195 | let fields = var_data.fields().unwrap(); | ||
196 | let ss; | ||
197 | let es; | ||
198 | let (file_id, struct_kind) = match self.parent { | ||
199 | VariantDef::Struct(s) => { | ||
200 | ss = s.source(db); | ||
201 | (ss.file_id, ss.ast.kind()) | ||
202 | } | ||
203 | VariantDef::EnumVariant(e) => { | ||
204 | es = e.source(db); | ||
205 | (es.file_id, es.ast.kind()) | ||
206 | } | ||
207 | }; | ||
208 | |||
209 | let field_sources = match struct_kind { | ||
210 | ast::StructKind::Tuple(fl) => fl.fields().map(|it| FieldSource::Pos(it)).collect(), | ||
211 | ast::StructKind::Named(fl) => fl.fields().map(|it| FieldSource::Named(it)).collect(), | ||
212 | ast::StructKind::Unit => Vec::new(), | ||
213 | }; | ||
214 | let ast = field_sources | ||
215 | .into_iter() | ||
216 | .zip(fields.iter()) | ||
217 | .find(|(_syntax, (id, _))| *id == self.id) | ||
218 | .unwrap() | ||
219 | .0; | ||
220 | Source { file_id, ast } | ||
221 | } | ||
222 | } | ||
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index b32aa145e..ae6ef7606 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs | |||
@@ -6,16 +6,17 @@ pub(crate) mod docs; | |||
6 | use std::sync::Arc; | 6 | use std::sync::Arc; |
7 | 7 | ||
8 | use hir_def::{ | 8 | use hir_def::{ |
9 | adt::VariantData, | ||
9 | builtin_type::BuiltinType, | 10 | builtin_type::BuiltinType, |
10 | type_ref::{Mutability, TypeRef}, | 11 | type_ref::{Mutability, TypeRef}, |
11 | CrateModuleId, LocalEnumVariantId, ModuleId, | 12 | CrateModuleId, LocalEnumVariantId, LocalStructFieldId, ModuleId, |
12 | }; | 13 | }; |
13 | use hir_expand::name::{self, AsName}; | 14 | use hir_expand::name::{self, AsName}; |
14 | use ra_db::{CrateId, Edition}; | 15 | use ra_db::{CrateId, Edition}; |
15 | use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner}; | 16 | use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner}; |
16 | 17 | ||
17 | use crate::{ | 18 | use crate::{ |
18 | adt::{StructFieldId, VariantDef}, | 19 | adt::VariantDef, |
19 | db::{AstDatabase, DefDatabase, HirDatabase}, | 20 | db::{AstDatabase, DefDatabase, HirDatabase}, |
20 | diagnostics::DiagnosticSink, | 21 | diagnostics::DiagnosticSink, |
21 | expr::{validation::ExprValidator, Body, BodySourceMap}, | 22 | expr::{validation::ExprValidator, Body, BodySourceMap}, |
@@ -250,7 +251,7 @@ impl Module { | |||
250 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 251 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
251 | pub struct StructField { | 252 | pub struct StructField { |
252 | pub(crate) parent: VariantDef, | 253 | pub(crate) parent: VariantDef, |
253 | pub(crate) id: StructFieldId, | 254 | pub(crate) id: LocalStructFieldId, |
254 | } | 255 | } |
255 | 256 | ||
256 | #[derive(Debug, PartialEq, Eq)] | 257 | #[derive(Debug, PartialEq, Eq)] |
@@ -288,11 +289,11 @@ impl Struct { | |||
288 | } | 289 | } |
289 | 290 | ||
290 | pub fn name(self, db: &impl DefDatabase) -> Option<Name> { | 291 | pub fn name(self, db: &impl DefDatabase) -> Option<Name> { |
291 | db.struct_data(self).name.clone() | 292 | db.struct_data(self.id).name.clone() |
292 | } | 293 | } |
293 | 294 | ||
294 | pub fn fields(self, db: &impl HirDatabase) -> Vec<StructField> { | 295 | pub fn fields(self, db: &impl HirDatabase) -> Vec<StructField> { |
295 | db.struct_data(self) | 296 | db.struct_data(self.id) |
296 | .variant_data | 297 | .variant_data |
297 | .fields() | 298 | .fields() |
298 | .into_iter() | 299 | .into_iter() |
@@ -302,7 +303,7 @@ impl Struct { | |||
302 | } | 303 | } |
303 | 304 | ||
304 | pub fn field(self, db: &impl HirDatabase, name: &Name) -> Option<StructField> { | 305 | pub fn field(self, db: &impl HirDatabase, name: &Name) -> Option<StructField> { |
305 | db.struct_data(self) | 306 | db.struct_data(self.id) |
306 | .variant_data | 307 | .variant_data |
307 | .fields() | 308 | .fields() |
308 | .into_iter() | 309 | .into_iter() |
@@ -338,7 +339,7 @@ pub struct Union { | |||
338 | 339 | ||
339 | impl Union { | 340 | impl Union { |
340 | pub fn name(self, db: &impl DefDatabase) -> Option<Name> { | 341 | pub fn name(self, db: &impl DefDatabase) -> Option<Name> { |
341 | db.struct_data(Struct { id: self.id }).name.clone() | 342 | db.struct_data(self.id).name.clone() |
342 | } | 343 | } |
343 | 344 | ||
344 | pub fn module(self, db: &impl HirDatabase) -> Module { | 345 | pub fn module(self, db: &impl HirDatabase) -> Module { |
@@ -376,15 +377,19 @@ impl Enum { | |||
376 | } | 377 | } |
377 | 378 | ||
378 | pub fn name(self, db: &impl DefDatabase) -> Option<Name> { | 379 | pub fn name(self, db: &impl DefDatabase) -> Option<Name> { |
379 | db.enum_data(self).name.clone() | 380 | db.enum_data(self.id).name.clone() |
380 | } | 381 | } |
381 | 382 | ||
382 | pub fn variants(self, db: &impl DefDatabase) -> Vec<EnumVariant> { | 383 | pub fn variants(self, db: &impl DefDatabase) -> Vec<EnumVariant> { |
383 | db.enum_data(self).variants.iter().map(|(id, _)| EnumVariant { parent: self, id }).collect() | 384 | db.enum_data(self.id) |
385 | .variants | ||
386 | .iter() | ||
387 | .map(|(id, _)| EnumVariant { parent: self, id }) | ||
388 | .collect() | ||
384 | } | 389 | } |
385 | 390 | ||
386 | pub fn variant(self, db: &impl DefDatabase, name: &Name) -> Option<EnumVariant> { | 391 | pub fn variant(self, db: &impl DefDatabase, name: &Name) -> Option<EnumVariant> { |
387 | db.enum_data(self) | 392 | db.enum_data(self.id) |
388 | .variants | 393 | .variants |
389 | .iter() | 394 | .iter() |
390 | .find(|(_id, data)| data.name.as_ref() == Some(name)) | 395 | .find(|(_id, data)| data.name.as_ref() == Some(name)) |
@@ -422,7 +427,7 @@ impl EnumVariant { | |||
422 | } | 427 | } |
423 | 428 | ||
424 | pub fn name(self, db: &impl DefDatabase) -> Option<Name> { | 429 | pub fn name(self, db: &impl DefDatabase) -> Option<Name> { |
425 | db.enum_data(self.parent).variants[self.id].name.clone() | 430 | db.enum_data(self.parent.id).variants[self.id].name.clone() |
426 | } | 431 | } |
427 | 432 | ||
428 | pub fn fields(self, db: &impl HirDatabase) -> Vec<StructField> { | 433 | pub fn fields(self, db: &impl HirDatabase) -> Vec<StructField> { |
@@ -442,6 +447,10 @@ impl EnumVariant { | |||
442 | .find(|(_id, data)| data.name == *name) | 447 | .find(|(_id, data)| data.name == *name) |
443 | .map(|(id, _)| StructField { parent: self.into(), id }) | 448 | .map(|(id, _)| StructField { parent: self.into(), id }) |
444 | } | 449 | } |
450 | |||
451 | pub(crate) fn variant_data(self, db: &impl DefDatabase) -> Arc<VariantData> { | ||
452 | db.enum_data(self.parent.id).variants[self.id].variant_data.clone() | ||
453 | } | ||
445 | } | 454 | } |
446 | 455 | ||
447 | /// A Data Type | 456 | /// A Data Type |
diff --git a/crates/ra_hir/src/code_model/src.rs b/crates/ra_hir/src/code_model/src.rs index 5c7f61eef..0f4c78df7 100644 --- a/crates/ra_hir/src/code_model/src.rs +++ b/crates/ra_hir/src/code_model/src.rs | |||
@@ -3,6 +3,7 @@ | |||
3 | use ra_syntax::ast::{self, AstNode}; | 3 | use ra_syntax::ast::{self, AstNode}; |
4 | 4 | ||
5 | use crate::{ | 5 | use crate::{ |
6 | adt::VariantDef, | ||
6 | db::{AstDatabase, DefDatabase, HirDatabase}, | 7 | db::{AstDatabase, DefDatabase, HirDatabase}, |
7 | ids::AstItemDef, | 8 | ids::AstItemDef, |
8 | Const, Either, Enum, EnumVariant, FieldSource, Function, HasBody, HirFileId, MacroDef, Module, | 9 | Const, Either, Enum, EnumVariant, FieldSource, Function, HasBody, HirFileId, MacroDef, Module, |
@@ -45,7 +46,33 @@ impl Module { | |||
45 | impl HasSource for StructField { | 46 | impl HasSource for StructField { |
46 | type Ast = FieldSource; | 47 | type Ast = FieldSource; |
47 | fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<FieldSource> { | 48 | fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<FieldSource> { |
48 | self.source_impl(db) | 49 | let var_data = self.parent.variant_data(db); |
50 | let fields = var_data.fields().unwrap(); | ||
51 | let ss; | ||
52 | let es; | ||
53 | let (file_id, struct_kind) = match self.parent { | ||
54 | VariantDef::Struct(s) => { | ||
55 | ss = s.source(db); | ||
56 | (ss.file_id, ss.ast.kind()) | ||
57 | } | ||
58 | VariantDef::EnumVariant(e) => { | ||
59 | es = e.source(db); | ||
60 | (es.file_id, es.ast.kind()) | ||
61 | } | ||
62 | }; | ||
63 | |||
64 | let field_sources = match struct_kind { | ||
65 | ast::StructKind::Tuple(fl) => fl.fields().map(|it| FieldSource::Pos(it)).collect(), | ||
66 | ast::StructKind::Named(fl) => fl.fields().map(|it| FieldSource::Named(it)).collect(), | ||
67 | ast::StructKind::Unit => Vec::new(), | ||
68 | }; | ||
69 | let ast = field_sources | ||
70 | .into_iter() | ||
71 | .zip(fields.iter()) | ||
72 | .find(|(_syntax, (id, _))| *id == self.id) | ||
73 | .unwrap() | ||
74 | .0; | ||
75 | Source { file_id, ast } | ||
49 | } | 76 | } |
50 | } | 77 | } |
51 | impl HasSource for Struct { | 78 | impl HasSource for Struct { |
@@ -69,7 +96,18 @@ impl HasSource for Enum { | |||
69 | impl HasSource for EnumVariant { | 96 | impl HasSource for EnumVariant { |
70 | type Ast = ast::EnumVariant; | 97 | type Ast = ast::EnumVariant; |
71 | fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::EnumVariant> { | 98 | fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::EnumVariant> { |
72 | self.source_impl(db) | 99 | let enum_data = db.enum_data(self.parent.id); |
100 | let src = self.parent.id.source(db); | ||
101 | let ast = src | ||
102 | .ast | ||
103 | .variant_list() | ||
104 | .into_iter() | ||
105 | .flat_map(|it| it.variants()) | ||
106 | .zip(enum_data.variants.iter()) | ||
107 | .find(|(_syntax, (id, _))| *id == self.id) | ||
108 | .unwrap() | ||
109 | .0; | ||
110 | Source { file_id: src.file_id, ast } | ||
73 | } | 111 | } |
74 | } | 112 | } |
75 | impl HasSource for Function { | 113 | impl HasSource for Function { |
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index ebfd970eb..89ca4e39f 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs | |||
@@ -6,7 +6,6 @@ use ra_db::salsa; | |||
6 | use ra_syntax::SmolStr; | 6 | use ra_syntax::SmolStr; |
7 | 7 | ||
8 | use crate::{ | 8 | use crate::{ |
9 | adt::{EnumData, StructData}, | ||
10 | debug::HirDebugDatabase, | 9 | debug::HirDebugDatabase, |
11 | generics::{GenericDef, GenericParams}, | 10 | generics::{GenericDef, GenericParams}, |
12 | ids, | 11 | ids, |
@@ -19,13 +18,13 @@ use crate::{ | |||
19 | InferenceResult, Substs, Ty, TypableDef, TypeCtor, | 18 | InferenceResult, Substs, Ty, TypableDef, TypeCtor, |
20 | }, | 19 | }, |
21 | type_alias::TypeAliasData, | 20 | type_alias::TypeAliasData, |
22 | Const, ConstData, Crate, DefWithBody, Enum, ExprScopes, FnData, Function, Module, Static, | 21 | Const, ConstData, Crate, DefWithBody, ExprScopes, FnData, Function, Module, Static, |
23 | Struct, StructField, Trait, TypeAlias, | 22 | StructField, Trait, TypeAlias, |
24 | }; | 23 | }; |
25 | 24 | ||
26 | pub use hir_def::db::{ | 25 | pub use hir_def::db::{ |
27 | DefDatabase2, DefDatabase2Storage, InternDatabase, InternDatabaseStorage, RawItemsQuery, | 26 | DefDatabase2, DefDatabase2Storage, EnumDataQuery, InternDatabase, InternDatabaseStorage, |
28 | RawItemsWithSourceMapQuery, | 27 | RawItemsQuery, RawItemsWithSourceMapQuery, StructDataQuery, |
29 | }; | 28 | }; |
30 | pub use hir_expand::db::{ | 29 | pub use hir_expand::db::{ |
31 | AstDatabase, AstDatabaseStorage, AstIdMapQuery, MacroArgQuery, MacroDefQuery, MacroExpandQuery, | 30 | AstDatabase, AstDatabaseStorage, AstIdMapQuery, MacroArgQuery, MacroDefQuery, MacroExpandQuery, |
@@ -36,12 +35,6 @@ pub use hir_expand::db::{ | |||
36 | #[salsa::query_group(DefDatabaseStorage)] | 35 | #[salsa::query_group(DefDatabaseStorage)] |
37 | #[salsa::requires(AstDatabase)] | 36 | #[salsa::requires(AstDatabase)] |
38 | pub trait DefDatabase: HirDebugDatabase + DefDatabase2 { | 37 | pub trait DefDatabase: HirDebugDatabase + DefDatabase2 { |
39 | #[salsa::invoke(crate::adt::StructData::struct_data_query)] | ||
40 | fn struct_data(&self, s: Struct) -> Arc<StructData>; | ||
41 | |||
42 | #[salsa::invoke(crate::adt::EnumData::enum_data_query)] | ||
43 | fn enum_data(&self, e: Enum) -> Arc<EnumData>; | ||
44 | |||
45 | #[salsa::invoke(crate::traits::TraitData::trait_data_query)] | 38 | #[salsa::invoke(crate::traits::TraitData::trait_data_query)] |
46 | fn trait_data(&self, t: Trait) -> Arc<TraitData>; | 39 | fn trait_data(&self, t: Trait) -> Arc<TraitData>; |
47 | 40 | ||
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs index dd7cd979f..8e2834307 100644 --- a/crates/ra_hir/src/ty/lower.rs +++ b/crates/ra_hir/src/ty/lower.rs | |||
@@ -655,8 +655,8 @@ fn type_for_builtin(def: BuiltinType) -> Ty { | |||
655 | } | 655 | } |
656 | 656 | ||
657 | fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> FnSig { | 657 | fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> FnSig { |
658 | let var_data = def.variant_data(db); | 658 | let struct_data = db.struct_data(def.id); |
659 | let fields = match var_data.fields() { | 659 | let fields = match struct_data.variant_data.fields() { |
660 | Some(fields) => fields, | 660 | Some(fields) => fields, |
661 | None => panic!("fn_sig_for_struct_constructor called on unit struct"), | 661 | None => panic!("fn_sig_for_struct_constructor called on unit struct"), |
662 | }; | 662 | }; |
@@ -671,8 +671,8 @@ fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> FnSig { | |||
671 | 671 | ||
672 | /// Build the type of a tuple struct constructor. | 672 | /// Build the type of a tuple struct constructor. |
673 | fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty { | 673 | fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty { |
674 | let var_data = def.variant_data(db); | 674 | let struct_data = db.struct_data(def.id); |
675 | if var_data.fields().is_none() { | 675 | if struct_data.variant_data.fields().is_none() { |
676 | return type_for_adt(db, def); // Unit struct | 676 | return type_for_adt(db, def); // Unit struct |
677 | } | 677 | } |
678 | let generics = def.generic_params(db); | 678 | let generics = def.generic_params(db); |
diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs new file mode 100644 index 000000000..22bd469f0 --- /dev/null +++ b/crates/ra_hir_def/src/adt.rs | |||
@@ -0,0 +1,114 @@ | |||
1 | //! Defines hir-level representation of structs, enums and unions | ||
2 | |||
3 | use std::sync::Arc; | ||
4 | |||
5 | use hir_expand::name::{AsName, Name}; | ||
6 | use ra_arena::Arena; | ||
7 | use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner}; | ||
8 | |||
9 | use crate::{ | ||
10 | db::DefDatabase2, type_ref::TypeRef, AstItemDef, EnumId, LocalEnumVariantId, | ||
11 | LocalStructFieldId, StructId, | ||
12 | }; | ||
13 | |||
14 | /// Note that we use `StructData` for unions as well! | ||
15 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
16 | pub struct StructData { | ||
17 | pub name: Option<Name>, | ||
18 | pub variant_data: Arc<VariantData>, | ||
19 | } | ||
20 | |||
21 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
22 | pub struct EnumData { | ||
23 | pub name: Option<Name>, | ||
24 | pub variants: Arena<LocalEnumVariantId, EnumVariantData>, | ||
25 | } | ||
26 | |||
27 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
28 | pub struct EnumVariantData { | ||
29 | pub name: Option<Name>, | ||
30 | pub variant_data: Arc<VariantData>, | ||
31 | } | ||
32 | |||
33 | /// Fields of an enum variant or struct | ||
34 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
35 | pub struct VariantData(VariantDataInner); | ||
36 | |||
37 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
38 | enum VariantDataInner { | ||
39 | Struct(Arena<LocalStructFieldId, StructFieldData>), | ||
40 | Tuple(Arena<LocalStructFieldId, StructFieldData>), | ||
41 | Unit, | ||
42 | } | ||
43 | |||
44 | /// A single field of an enum variant or struct | ||
45 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
46 | pub struct StructFieldData { | ||
47 | pub name: Name, | ||
48 | pub type_ref: TypeRef, | ||
49 | } | ||
50 | |||
51 | impl StructData { | ||
52 | pub(crate) fn struct_data_query(db: &impl DefDatabase2, struct_: StructId) -> Arc<StructData> { | ||
53 | let src = struct_.source(db); | ||
54 | let name = src.ast.name().map(|n| n.as_name()); | ||
55 | let variant_data = VariantData::new(src.ast.kind()); | ||
56 | let variant_data = Arc::new(variant_data); | ||
57 | Arc::new(StructData { name, variant_data }) | ||
58 | } | ||
59 | } | ||
60 | |||
61 | impl EnumData { | ||
62 | pub(crate) fn enum_data_query(db: &impl DefDatabase2, e: EnumId) -> Arc<EnumData> { | ||
63 | let src = e.source(db); | ||
64 | let name = src.ast.name().map(|n| n.as_name()); | ||
65 | let variants = src | ||
66 | .ast | ||
67 | .variant_list() | ||
68 | .into_iter() | ||
69 | .flat_map(|it| it.variants()) | ||
70 | .map(|var| EnumVariantData { | ||
71 | name: var.name().map(|it| it.as_name()), | ||
72 | variant_data: Arc::new(VariantData::new(var.kind())), | ||
73 | }) | ||
74 | .collect(); | ||
75 | Arc::new(EnumData { name, variants }) | ||
76 | } | ||
77 | } | ||
78 | |||
79 | impl VariantData { | ||
80 | fn new(flavor: ast::StructKind) -> Self { | ||
81 | let inner = match flavor { | ||
82 | ast::StructKind::Tuple(fl) => { | ||
83 | let fields = fl | ||
84 | .fields() | ||
85 | .enumerate() | ||
86 | .map(|(i, fd)| StructFieldData { | ||
87 | name: Name::new_tuple_field(i), | ||
88 | type_ref: TypeRef::from_ast_opt(fd.type_ref()), | ||
89 | }) | ||
90 | .collect(); | ||
91 | VariantDataInner::Tuple(fields) | ||
92 | } | ||
93 | ast::StructKind::Named(fl) => { | ||
94 | let fields = fl | ||
95 | .fields() | ||
96 | .map(|fd| StructFieldData { | ||
97 | name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing), | ||
98 | type_ref: TypeRef::from_ast_opt(fd.ascribed_type()), | ||
99 | }) | ||
100 | .collect(); | ||
101 | VariantDataInner::Struct(fields) | ||
102 | } | ||
103 | ast::StructKind::Unit => VariantDataInner::Unit, | ||
104 | }; | ||
105 | VariantData(inner) | ||
106 | } | ||
107 | |||
108 | pub fn fields(&self) -> Option<&Arena<LocalStructFieldId, StructFieldData>> { | ||
109 | match &self.0 { | ||
110 | VariantDataInner::Struct(fields) | VariantDataInner::Tuple(fields) => Some(fields), | ||
111 | _ => None, | ||
112 | } | ||
113 | } | ||
114 | } | ||
diff --git a/crates/ra_hir_def/src/db.rs b/crates/ra_hir_def/src/db.rs index b271636b0..f6027013f 100644 --- a/crates/ra_hir_def/src/db.rs +++ b/crates/ra_hir_def/src/db.rs | |||
@@ -5,7 +5,11 @@ use hir_expand::{db::AstDatabase, HirFileId}; | |||
5 | use ra_db::{salsa, SourceDatabase}; | 5 | use ra_db::{salsa, SourceDatabase}; |
6 | use ra_syntax::ast; | 6 | use ra_syntax::ast; |
7 | 7 | ||
8 | use crate::nameres::raw::{ImportSourceMap, RawItems}; | 8 | use crate::{ |
9 | adt::{EnumData, StructData}, | ||
10 | nameres::raw::{ImportSourceMap, RawItems}, | ||
11 | EnumId, StructId, | ||
12 | }; | ||
9 | 13 | ||
10 | #[salsa::query_group(InternDatabaseStorage)] | 14 | #[salsa::query_group(InternDatabaseStorage)] |
11 | pub trait InternDatabase: SourceDatabase { | 15 | pub trait InternDatabase: SourceDatabase { |
@@ -37,4 +41,10 @@ pub trait DefDatabase2: InternDatabase + AstDatabase { | |||
37 | 41 | ||
38 | #[salsa::invoke(RawItems::raw_items_query)] | 42 | #[salsa::invoke(RawItems::raw_items_query)] |
39 | fn raw_items(&self, file_id: HirFileId) -> Arc<RawItems>; | 43 | fn raw_items(&self, file_id: HirFileId) -> Arc<RawItems>; |
44 | |||
45 | #[salsa::invoke(StructData::struct_data_query)] | ||
46 | fn struct_data(&self, s: StructId) -> Arc<StructData>; | ||
47 | |||
48 | #[salsa::invoke(EnumData::enum_data_query)] | ||
49 | fn enum_data(&self, e: EnumId) -> Arc<EnumData>; | ||
40 | } | 50 | } |
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index 93ad40005..76d5f1852 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs | |||
@@ -12,6 +12,7 @@ pub mod attr; | |||
12 | pub mod path; | 12 | pub mod path; |
13 | pub mod type_ref; | 13 | pub mod type_ref; |
14 | pub mod builtin_type; | 14 | pub mod builtin_type; |
15 | pub mod adt; | ||
15 | 16 | ||
16 | // FIXME: this should be private | 17 | // FIXME: this should be private |
17 | pub mod nameres; | 18 | pub mod nameres; |
@@ -260,6 +261,22 @@ pub struct LocalEnumVariantId(RawId); | |||
260 | impl_arena_id!(LocalEnumVariantId); | 261 | impl_arena_id!(LocalEnumVariantId); |
261 | 262 | ||
262 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 263 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
264 | pub enum VariantId { | ||
265 | EnumVariantId(EnumVariantId), | ||
266 | StructId(StructId), | ||
267 | } | ||
268 | |||
269 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
270 | pub struct StructFieldId { | ||
271 | parent: VariantId, | ||
272 | local_id: LocalStructFieldId, | ||
273 | } | ||
274 | |||
275 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
276 | pub struct LocalStructFieldId(RawId); | ||
277 | impl_arena_id!(LocalStructFieldId); | ||
278 | |||
279 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
263 | pub struct ConstId(salsa::InternId); | 280 | pub struct ConstId(salsa::InternId); |
264 | impl_intern_key!(ConstId); | 281 | impl_intern_key!(ConstId); |
265 | impl AstItemDef<ast::ConstDef> for ConstId { | 282 | impl AstItemDef<ast::ConstDef> for ConstId { |