aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2018-12-25 20:40:33 +0000
committerFlorian Diebold <[email protected]>2018-12-25 20:40:33 +0000
commitbc745a139674f289386f3081458793f756cab5b9 (patch)
tree518c38ce87807c76644b512ce0213dd01e43614a /crates
parentcdca39706121b2d1734a94938a2372da881e10c6 (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.rs1
-rw-r--r--crates/ra_hir/src/adt.rs71
-rw-r--r--crates/ra_hir/src/db.rs6
-rw-r--r--crates/ra_hir/src/mock.rs1
-rw-r--r--crates/ra_hir/src/query_definitions.rs18
-rw-r--r--crates/ra_hir/src/ty.rs36
-rw-r--r--crates/ra_hir/src/type_ref.rs2
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}};
5use crate::{ 5use 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
12pub struct Struct { 11pub struct Struct {
@@ -42,15 +41,11 @@ pub struct StructData {
42} 41}
43 42
44impl StructData { 43impl 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
89impl EnumData { 84impl 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)]
116pub struct StructField { 107pub struct StructField {
117 name: SmolStr, 108 name: SmolStr,
118 ty: Ty, 109 type_ref: TypeRef,
119} 110}
120 111
121impl StructField { 112impl 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
138impl VariantData { 129impl 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 @@
1use std::sync::Arc; 1use std::sync::Arc;
2 2
3use ra_syntax::{ 3use 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
49pub(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
49pub(super) fn struct_data(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Arc<StructData>> { 57pub(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
63pub(super) fn enum_data(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Arc<EnumData>> { 66pub(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
73pub(super) fn file_items(db: &impl HirDatabase, file_id: FileId) -> Arc<SourceFileItems> { 75pub(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
312pub(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)]
313pub struct InferenceResult { 340pub 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 {