diff options
author | Florian Diebold <[email protected]> | 2018-12-25 20:40:33 +0000 |
---|---|---|
committer | Florian Diebold <[email protected]> | 2018-12-25 20:40:33 +0000 |
commit | bc745a139674f289386f3081458793f756cab5b9 (patch) | |
tree | 518c38ce87807c76644b512ce0213dd01e43614a /crates | |
parent | cdca39706121b2d1734a94938a2372da881e10c6 (diff) |
Resolve field types lazily
I.e. not already when getting the HIR for the struct.
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_analysis/src/db.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir/src/adt.rs | 71 | ||||
-rw-r--r-- | crates/ra_hir/src/db.rs | 6 | ||||
-rw-r--r-- | crates/ra_hir/src/mock.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir/src/query_definitions.rs | 18 | ||||
-rw-r--r-- | crates/ra_hir/src/ty.rs | 36 | ||||
-rw-r--r-- | crates/ra_hir/src/type_ref.rs | 2 |
7 files changed, 76 insertions, 59 deletions
diff --git a/crates/ra_analysis/src/db.rs b/crates/ra_analysis/src/db.rs index 677745d57..036e284bf 100644 --- a/crates/ra_analysis/src/db.rs +++ b/crates/ra_analysis/src/db.rs | |||
@@ -95,6 +95,7 @@ salsa::database_storage! { | |||
95 | fn submodules() for hir::db::SubmodulesQuery; | 95 | fn submodules() for hir::db::SubmodulesQuery; |
96 | fn infer() for hir::db::InferQuery; | 96 | fn infer() for hir::db::InferQuery; |
97 | fn type_for_def() for hir::db::TypeForDefQuery; | 97 | fn type_for_def() for hir::db::TypeForDefQuery; |
98 | fn type_for_field() for hir::db::TypeForFieldQuery; | ||
98 | fn struct_data() for hir::db::StructDataQuery; | 99 | fn struct_data() for hir::db::StructDataQuery; |
99 | fn enum_data() for hir::db::EnumDataQuery; | 100 | fn enum_data() for hir::db::EnumDataQuery; |
100 | } | 101 | } |
diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs index dae04d258..65c461148 100644 --- a/crates/ra_hir/src/adt.rs +++ b/crates/ra_hir/src/adt.rs | |||
@@ -5,8 +5,7 @@ use ra_syntax::{SmolStr, ast::{self, NameOwner, StructFlavor}}; | |||
5 | use crate::{ | 5 | use crate::{ |
6 | DefId, Cancelable, | 6 | DefId, Cancelable, |
7 | db::{HirDatabase}, | 7 | db::{HirDatabase}, |
8 | module::Module, | 8 | type_ref::TypeRef, |
9 | ty::{Ty}, | ||
10 | }; | 9 | }; |
11 | 10 | ||
12 | pub struct Struct { | 11 | pub struct Struct { |
@@ -42,15 +41,11 @@ pub struct StructData { | |||
42 | } | 41 | } |
43 | 42 | ||
44 | impl StructData { | 43 | impl StructData { |
45 | pub(crate) fn new( | 44 | pub(crate) fn new(struct_def: ast::StructDef) -> StructData { |
46 | db: &impl HirDatabase, | ||
47 | module: &Module, | ||
48 | struct_def: ast::StructDef, | ||
49 | ) -> Cancelable<StructData> { | ||
50 | let name = struct_def.name().map(|n| n.text()); | 45 | let name = struct_def.name().map(|n| n.text()); |
51 | let variant_data = VariantData::new(db, module, struct_def.flavor())?; | 46 | let variant_data = VariantData::new(struct_def.flavor()); |
52 | let variant_data = Arc::new(variant_data); | 47 | let variant_data = Arc::new(variant_data); |
53 | Ok(StructData { name, variant_data }) | 48 | StructData { name, variant_data } |
54 | } | 49 | } |
55 | 50 | ||
56 | pub fn name(&self) -> Option<&SmolStr> { | 51 | pub fn name(&self) -> Option<&SmolStr> { |
@@ -87,27 +82,23 @@ pub struct EnumData { | |||
87 | } | 82 | } |
88 | 83 | ||
89 | impl EnumData { | 84 | impl EnumData { |
90 | pub(crate) fn new( | 85 | pub(crate) fn new(enum_def: ast::EnumDef) -> Self { |
91 | db: &impl HirDatabase, | ||
92 | module: &Module, | ||
93 | enum_def: ast::EnumDef, | ||
94 | ) -> Cancelable<Self> { | ||
95 | let name = enum_def.name().map(|n| n.text()); | 86 | let name = enum_def.name().map(|n| n.text()); |
96 | let variants = if let Some(evl) = enum_def.variant_list() { | 87 | let variants = if let Some(evl) = enum_def.variant_list() { |
97 | evl.variants() | 88 | evl.variants() |
98 | .map(|v| { | 89 | .map(|v| { |
99 | Ok(( | 90 | ( |
100 | v.name() | 91 | v.name() |
101 | .map(|n| n.text()) | 92 | .map(|n| n.text()) |
102 | .unwrap_or_else(|| SmolStr::new("[error]")), | 93 | .unwrap_or_else(|| SmolStr::new("[error]")), |
103 | Arc::new(VariantData::new(db, module, v.flavor())?), | 94 | Arc::new(VariantData::new(v.flavor())), |
104 | )) | 95 | ) |
105 | }) | 96 | }) |
106 | .collect::<Cancelable<_>>()? | 97 | .collect() |
107 | } else { | 98 | } else { |
108 | Vec::new() | 99 | Vec::new() |
109 | }; | 100 | }; |
110 | Ok(EnumData { name, variants }) | 101 | EnumData { name, variants } |
111 | } | 102 | } |
112 | } | 103 | } |
113 | 104 | ||
@@ -115,15 +106,15 @@ impl EnumData { | |||
115 | #[derive(Debug, Clone, PartialEq, Eq)] | 106 | #[derive(Debug, Clone, PartialEq, Eq)] |
116 | pub struct StructField { | 107 | pub struct StructField { |
117 | name: SmolStr, | 108 | name: SmolStr, |
118 | ty: Ty, | 109 | type_ref: TypeRef, |
119 | } | 110 | } |
120 | 111 | ||
121 | impl StructField { | 112 | impl StructField { |
122 | pub fn name(&self) -> SmolStr { | 113 | pub fn name(&self) -> SmolStr { |
123 | self.name.clone() | 114 | self.name.clone() |
124 | } | 115 | } |
125 | pub fn ty(&self) -> Ty { | 116 | pub fn type_ref(&self) -> &TypeRef { |
126 | self.ty.clone() | 117 | &self.type_ref |
127 | } | 118 | } |
128 | } | 119 | } |
129 | 120 | ||
@@ -136,45 +127,41 @@ pub enum VariantData { | |||
136 | } | 127 | } |
137 | 128 | ||
138 | impl VariantData { | 129 | impl VariantData { |
139 | pub fn new(db: &impl HirDatabase, module: &Module, flavor: StructFlavor) -> Cancelable<Self> { | 130 | pub fn new(flavor: StructFlavor) -> Self { |
140 | Ok(match flavor { | 131 | match flavor { |
141 | StructFlavor::Tuple(fl) => { | 132 | StructFlavor::Tuple(fl) => { |
142 | let fields = fl | 133 | let fields = fl |
143 | .fields() | 134 | .fields() |
144 | .enumerate() | 135 | .enumerate() |
145 | .map(|(i, fd)| { | 136 | .map(|(i, fd)| StructField { |
146 | Ok(StructField { | 137 | name: SmolStr::new(i.to_string()), |
147 | name: SmolStr::new(i.to_string()), | 138 | type_ref: TypeRef::from_ast_opt(fd.type_ref()), |
148 | ty: Ty::from_ast_opt(db, &module, fd.type_ref())?, | ||
149 | }) | ||
150 | }) | 139 | }) |
151 | .collect::<Cancelable<_>>()?; | 140 | .collect(); |
152 | VariantData::Tuple(fields) | 141 | VariantData::Tuple(fields) |
153 | } | 142 | } |
154 | StructFlavor::Named(fl) => { | 143 | StructFlavor::Named(fl) => { |
155 | let fields = fl | 144 | let fields = fl |
156 | .fields() | 145 | .fields() |
157 | .map(|fd| { | 146 | .map(|fd| StructField { |
158 | Ok(StructField { | 147 | name: fd |
159 | name: fd | 148 | .name() |
160 | .name() | 149 | .map(|n| n.text()) |
161 | .map(|n| n.text()) | 150 | .unwrap_or_else(|| SmolStr::new("[error]")), |
162 | .unwrap_or_else(|| SmolStr::new("[error]")), | 151 | type_ref: TypeRef::from_ast_opt(fd.type_ref()), |
163 | ty: Ty::from_ast_opt(db, &module, fd.type_ref())?, | ||
164 | }) | ||
165 | }) | 152 | }) |
166 | .collect::<Cancelable<_>>()?; | 153 | .collect(); |
167 | VariantData::Struct(fields) | 154 | VariantData::Struct(fields) |
168 | } | 155 | } |
169 | StructFlavor::Unit => VariantData::Unit, | 156 | StructFlavor::Unit => VariantData::Unit, |
170 | }) | 157 | } |
171 | } | 158 | } |
172 | 159 | ||
173 | pub(crate) fn get_field_ty(&self, field_name: &str) -> Option<Ty> { | 160 | pub(crate) fn get_field_type_ref(&self, field_name: &str) -> Option<&TypeRef> { |
174 | self.fields() | 161 | self.fields() |
175 | .iter() | 162 | .iter() |
176 | .find(|f| f.name == field_name) | 163 | .find(|f| f.name == field_name) |
177 | .map(|f| f.ty.clone()) | 164 | .map(|f| &f.type_ref) |
178 | } | 165 | } |
179 | 166 | ||
180 | pub fn fields(&self) -> &[StructField] { | 167 | pub fn fields(&self) -> &[StructField] { |
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index 113790ee9..e7f9afa77 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs | |||
@@ -1,6 +1,7 @@ | |||
1 | use std::sync::Arc; | 1 | use std::sync::Arc; |
2 | 2 | ||
3 | use ra_syntax::{ | 3 | use ra_syntax::{ |
4 | SmolStr, | ||
4 | SyntaxNode, | 5 | SyntaxNode, |
5 | ast::FnDefNode, | 6 | ast::FnDefNode, |
6 | }; | 7 | }; |
@@ -52,6 +53,11 @@ pub trait HirDatabase: SyntaxDatabase | |||
52 | use fn query_definitions::type_for_def; | 53 | use fn query_definitions::type_for_def; |
53 | } | 54 | } |
54 | 55 | ||
56 | fn type_for_field(def_id: DefId, field: SmolStr) -> Cancelable<Ty> { | ||
57 | type TypeForFieldQuery; | ||
58 | use fn query_definitions::type_for_field; | ||
59 | } | ||
60 | |||
55 | fn file_items(file_id: FileId) -> Arc<SourceFileItems> { | 61 | fn file_items(file_id: FileId) -> Arc<SourceFileItems> { |
56 | type SourceFileItemsQuery; | 62 | type SourceFileItemsQuery; |
57 | use fn query_definitions::file_items; | 63 | use fn query_definitions::file_items; |
diff --git a/crates/ra_hir/src/mock.rs b/crates/ra_hir/src/mock.rs index ead2b8414..f6882cb77 100644 --- a/crates/ra_hir/src/mock.rs +++ b/crates/ra_hir/src/mock.rs | |||
@@ -193,6 +193,7 @@ salsa::database_storage! { | |||
193 | fn submodules() for db::SubmodulesQuery; | 193 | fn submodules() for db::SubmodulesQuery; |
194 | fn infer() for db::InferQuery; | 194 | fn infer() for db::InferQuery; |
195 | fn type_for_def() for db::TypeForDefQuery; | 195 | fn type_for_def() for db::TypeForDefQuery; |
196 | fn type_for_field() for db::TypeForFieldQuery; | ||
196 | fn struct_data() for db::StructDataQuery; | 197 | fn struct_data() for db::StructDataQuery; |
197 | fn enum_data() for db::EnumDataQuery; | 198 | fn enum_data() for db::EnumDataQuery; |
198 | } | 199 | } |
diff --git a/crates/ra_hir/src/query_definitions.rs b/crates/ra_hir/src/query_definitions.rs index 405e359f1..4a7958a12 100644 --- a/crates/ra_hir/src/query_definitions.rs +++ b/crates/ra_hir/src/query_definitions.rs | |||
@@ -46,18 +46,21 @@ pub(super) fn type_for_def(db: &impl HirDatabase, def_id: DefId) -> Cancelable<T | |||
46 | ty::type_for_def(db, def_id) | 46 | ty::type_for_def(db, def_id) |
47 | } | 47 | } |
48 | 48 | ||
49 | pub(super) fn type_for_field( | ||
50 | db: &impl HirDatabase, | ||
51 | def_id: DefId, | ||
52 | field: SmolStr, | ||
53 | ) -> Cancelable<Ty> { | ||
54 | ty::type_for_field(db, def_id, field) | ||
55 | } | ||
56 | |||
49 | pub(super) fn struct_data(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Arc<StructData>> { | 57 | pub(super) fn struct_data(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Arc<StructData>> { |
50 | let def_loc = def_id.loc(db); | 58 | let def_loc = def_id.loc(db); |
51 | assert!(def_loc.kind == DefKind::Struct); | 59 | assert!(def_loc.kind == DefKind::Struct); |
52 | let syntax = db.file_item(def_loc.source_item_id); | 60 | let syntax = db.file_item(def_loc.source_item_id); |
53 | let struct_def = | 61 | let struct_def = |
54 | ast::StructDef::cast(syntax.borrowed()).expect("struct def should point to StructDef node"); | 62 | ast::StructDef::cast(syntax.borrowed()).expect("struct def should point to StructDef node"); |
55 | let module = def_id.module(db)?; | 63 | Ok(Arc::new(StructData::new(struct_def.borrowed()))) |
56 | Ok(Arc::new(StructData::new( | ||
57 | db, | ||
58 | &module, | ||
59 | struct_def.borrowed(), | ||
60 | )?)) | ||
61 | } | 64 | } |
62 | 65 | ||
63 | pub(super) fn enum_data(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Arc<EnumData>> { | 66 | pub(super) fn enum_data(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Arc<EnumData>> { |
@@ -66,8 +69,7 @@ pub(super) fn enum_data(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Arc< | |||
66 | let syntax = db.file_item(def_loc.source_item_id); | 69 | let syntax = db.file_item(def_loc.source_item_id); |
67 | let enum_def = | 70 | let enum_def = |
68 | ast::EnumDef::cast(syntax.borrowed()).expect("enum def should point to EnumDef node"); | 71 | ast::EnumDef::cast(syntax.borrowed()).expect("enum def should point to EnumDef node"); |
69 | let module = def_id.module(db)?; | 72 | Ok(Arc::new(EnumData::new(enum_def.borrowed()))) |
70 | Ok(Arc::new(EnumData::new(db, &module, enum_def.borrowed())?)) | ||
71 | } | 73 | } |
72 | 74 | ||
73 | pub(super) fn file_items(db: &impl HirDatabase, file_id: FileId) -> Arc<SourceFileItems> { | 75 | pub(super) fn file_items(db: &impl HirDatabase, file_id: FileId) -> Arc<SourceFileItems> { |
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 11b4caa23..67b523c2c 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -309,6 +309,33 @@ pub fn type_for_def(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Ty> { | |||
309 | } | 309 | } |
310 | } | 310 | } |
311 | 311 | ||
312 | pub(super) fn type_for_field( | ||
313 | db: &impl HirDatabase, | ||
314 | def_id: DefId, | ||
315 | field: SmolStr, | ||
316 | ) -> Cancelable<Ty> { | ||
317 | let def = def_id.resolve(db)?; | ||
318 | let variant_data = match def { | ||
319 | Def::Struct(s) => { | ||
320 | let variant_data = s.variant_data(db)?; | ||
321 | variant_data | ||
322 | } | ||
323 | // TODO: unions | ||
324 | // TODO: enum variants | ||
325 | _ => panic!( | ||
326 | "trying to get type for field in non-struct/variant {:?}", | ||
327 | def_id | ||
328 | ), | ||
329 | }; | ||
330 | let module = def_id.module(db)?; | ||
331 | let type_ref = if let Some(tr) = variant_data.get_field_type_ref(&field) { | ||
332 | tr | ||
333 | } else { | ||
334 | return Ok(Ty::Unknown); | ||
335 | }; | ||
336 | Ty::from_hir(db, &module, &type_ref) | ||
337 | } | ||
338 | |||
312 | #[derive(Clone, PartialEq, Eq, Debug)] | 339 | #[derive(Clone, PartialEq, Eq, Debug)] |
313 | pub struct InferenceResult { | 340 | pub struct InferenceResult { |
314 | type_of: FxHashMap<LocalSyntaxPtr, Ty>, | 341 | type_of: FxHashMap<LocalSyntaxPtr, Ty>, |
@@ -540,14 +567,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
540 | i.and_then(|i| fields.get(i).cloned()) | 567 | i.and_then(|i| fields.get(i).cloned()) |
541 | .unwrap_or(Ty::Unknown) | 568 | .unwrap_or(Ty::Unknown) |
542 | } | 569 | } |
543 | Ty::Adt { def_id, .. } => { | 570 | Ty::Adt { def_id, .. } => self.db.type_for_field(def_id, text)?, |
544 | let field_ty = match def_id.resolve(self.db)? { | ||
545 | Def::Struct(s) => s.variant_data(self.db)?.get_field_ty(&text), | ||
546 | // TODO unions | ||
547 | _ => None, | ||
548 | }; | ||
549 | field_ty.unwrap_or(Ty::Unknown) | ||
550 | } | ||
551 | _ => Ty::Unknown, | 571 | _ => Ty::Unknown, |
552 | } | 572 | } |
553 | } else { | 573 | } else { |
diff --git a/crates/ra_hir/src/type_ref.rs b/crates/ra_hir/src/type_ref.rs index ae163313f..b36bb35d8 100644 --- a/crates/ra_hir/src/type_ref.rs +++ b/crates/ra_hir/src/type_ref.rs | |||
@@ -100,7 +100,7 @@ impl TypeRef { | |||
100 | } | 100 | } |
101 | } | 101 | } |
102 | 102 | ||
103 | fn from_ast_opt(node: Option<ast::TypeRef>) -> Self { | 103 | pub(crate) fn from_ast_opt(node: Option<ast::TypeRef>) -> Self { |
104 | if let Some(node) = node { | 104 | if let Some(node) = node { |
105 | TypeRef::from_ast(node) | 105 | TypeRef::from_ast(node) |
106 | } else { | 106 | } else { |