diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_arena/src/lib.rs | 13 | ||||
-rw-r--r-- | crates/ra_hir/src/adt.rs | 95 | ||||
-rw-r--r-- | crates/ra_hir/src/code_model_api.rs | 65 | ||||
-rw-r--r-- | crates/ra_hir/src/db.rs | 8 | ||||
-rw-r--r-- | crates/ra_hir/src/ty.rs | 90 | ||||
-rw-r--r-- | crates/ra_ide_api/src/completion/complete_dot.rs | 4 |
6 files changed, 144 insertions, 131 deletions
diff --git a/crates/ra_arena/src/lib.rs b/crates/ra_arena/src/lib.rs index d7d5d5265..97f554838 100644 --- a/crates/ra_arena/src/lib.rs +++ b/crates/ra_arena/src/lib.rs | |||
@@ -4,6 +4,7 @@ use std::{ | |||
4 | fmt, | 4 | fmt, |
5 | marker::PhantomData, | 5 | marker::PhantomData, |
6 | ops::{Index, IndexMut}, | 6 | ops::{Index, IndexMut}, |
7 | iter::FromIterator, | ||
7 | }; | 8 | }; |
8 | 9 | ||
9 | pub mod map; | 10 | pub mod map; |
@@ -109,3 +110,15 @@ impl<ID: ArenaId, T> IndexMut<ID> for Arena<ID, T> { | |||
109 | &mut self.data[idx] | 110 | &mut self.data[idx] |
110 | } | 111 | } |
111 | } | 112 | } |
113 | |||
114 | impl<ID: ArenaId, T> FromIterator<T> for Arena<ID, T> { | ||
115 | fn from_iter<I>(iter: I) -> Self | ||
116 | where | ||
117 | I: IntoIterator<Item = T>, | ||
118 | { | ||
119 | Arena { | ||
120 | data: Vec::from_iter(iter), | ||
121 | _ty: PhantomData, | ||
122 | } | ||
123 | } | ||
124 | } | ||
diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs index 2579ece19..df609b8d7 100644 --- a/crates/ra_hir/src/adt.rs +++ b/crates/ra_hir/src/adt.rs | |||
@@ -79,12 +79,13 @@ impl EnumVariant { | |||
79 | .to_owned(); | 79 | .to_owned(); |
80 | (file_id, var) | 80 | (file_id, var) |
81 | } | 81 | } |
82 | pub(crate) fn variant_data(&self, db: &impl HirDatabase) -> Arc<VariantData> { | ||
83 | db.enum_data(self.parent).variants[self.id] | ||
84 | .variant_data | ||
85 | .clone() | ||
86 | } | ||
82 | } | 87 | } |
83 | 88 | ||
84 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
85 | pub(crate) struct EnumVariantId(RawId); | ||
86 | impl_arena_id!(EnumVariantId); | ||
87 | |||
88 | #[derive(Debug, Clone, PartialEq, Eq)] | 89 | #[derive(Debug, Clone, PartialEq, Eq)] |
89 | pub struct EnumData { | 90 | pub struct EnumData { |
90 | pub(crate) name: Option<Name>, | 91 | pub(crate) name: Option<Name>, |
@@ -94,28 +95,31 @@ pub struct EnumData { | |||
94 | impl EnumData { | 95 | impl EnumData { |
95 | pub(crate) fn enum_data_query(db: &impl HirDatabase, e: Enum) -> Arc<EnumData> { | 96 | pub(crate) fn enum_data_query(db: &impl HirDatabase, e: Enum) -> Arc<EnumData> { |
96 | let (_file_id, enum_def) = e.source(db); | 97 | let (_file_id, enum_def) = e.source(db); |
97 | let mut res = EnumData { | 98 | let name = enum_def.name().map(|n| n.as_name()); |
98 | name: enum_def.name().map(|n| n.as_name()), | 99 | let variants = variants(&*enum_def) |
99 | variants: Arena::default(), | 100 | .map(|var| EnumVariantData { |
100 | }; | ||
101 | for var in variants(&*enum_def) { | ||
102 | let data = EnumVariantData { | ||
103 | name: var.name().map(|it| it.as_name()), | 101 | name: var.name().map(|it| it.as_name()), |
104 | variant_data: Arc::new(VariantData::new(var.flavor())), | 102 | variant_data: Arc::new(VariantData::new(var.flavor())), |
105 | }; | 103 | }) |
106 | res.variants.alloc(data); | 104 | .collect(); |
107 | } | 105 | Arc::new(EnumData { name, variants }) |
108 | |||
109 | Arc::new(res) | ||
110 | } | 106 | } |
111 | } | 107 | } |
112 | 108 | ||
109 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
110 | pub(crate) struct EnumVariantId(RawId); | ||
111 | impl_arena_id!(EnumVariantId); | ||
112 | |||
113 | #[derive(Debug, Clone, PartialEq, Eq)] | 113 | #[derive(Debug, Clone, PartialEq, Eq)] |
114 | pub struct EnumVariantData { | 114 | pub struct EnumVariantData { |
115 | pub(crate) name: Option<Name>, | 115 | pub(crate) name: Option<Name>, |
116 | pub(crate) variant_data: Arc<VariantData>, | 116 | pub(crate) variant_data: Arc<VariantData>, |
117 | } | 117 | } |
118 | 118 | ||
119 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
120 | pub(crate) struct StructFieldId(RawId); | ||
121 | impl_arena_id!(StructFieldId); | ||
122 | |||
119 | /// A single field of an enum variant or struct | 123 | /// A single field of an enum variant or struct |
120 | #[derive(Debug, Clone, PartialEq, Eq)] | 124 | #[derive(Debug, Clone, PartialEq, Eq)] |
121 | pub struct StructFieldData { | 125 | pub struct StructFieldData { |
@@ -125,45 +129,27 @@ pub struct StructFieldData { | |||
125 | 129 | ||
126 | /// Fields of an enum variant or struct | 130 | /// Fields of an enum variant or struct |
127 | #[derive(Debug, Clone, PartialEq, Eq)] | 131 | #[derive(Debug, Clone, PartialEq, Eq)] |
128 | pub enum VariantData { | 132 | pub struct VariantData(VariantDataInner); |
129 | Struct(Vec<StructFieldData>), | 133 | |
130 | Tuple(Vec<StructFieldData>), | 134 | #[derive(Debug, Clone, PartialEq, Eq)] |
135 | enum VariantDataInner { | ||
136 | Struct(Arena<StructFieldId, StructFieldData>), | ||
137 | Tuple(Arena<StructFieldId, StructFieldData>), | ||
131 | Unit, | 138 | Unit, |
132 | } | 139 | } |
133 | 140 | ||
134 | impl VariantData { | 141 | impl VariantData { |
135 | pub fn fields(&self) -> &[StructFieldData] { | 142 | pub(crate) fn fields(&self) -> Option<&Arena<StructFieldId, StructFieldData>> { |
136 | match self { | 143 | match &self.0 { |
137 | VariantData::Struct(fields) | VariantData::Tuple(fields) => fields, | 144 | VariantDataInner::Struct(fields) | VariantDataInner::Tuple(fields) => Some(fields), |
138 | _ => &[], | 145 | _ => None, |
139 | } | ||
140 | } | ||
141 | |||
142 | pub fn is_struct(&self) -> bool { | ||
143 | match self { | ||
144 | VariantData::Struct(..) => true, | ||
145 | _ => false, | ||
146 | } | ||
147 | } | ||
148 | |||
149 | pub fn is_tuple(&self) -> bool { | ||
150 | match self { | ||
151 | VariantData::Tuple(..) => true, | ||
152 | _ => false, | ||
153 | } | ||
154 | } | ||
155 | |||
156 | pub fn is_unit(&self) -> bool { | ||
157 | match self { | ||
158 | VariantData::Unit => true, | ||
159 | _ => false, | ||
160 | } | 146 | } |
161 | } | 147 | } |
162 | } | 148 | } |
163 | 149 | ||
164 | impl VariantData { | 150 | impl VariantData { |
165 | fn new(flavor: StructFlavor) -> Self { | 151 | fn new(flavor: StructFlavor) -> Self { |
166 | match flavor { | 152 | let inner = match flavor { |
167 | StructFlavor::Tuple(fl) => { | 153 | StructFlavor::Tuple(fl) => { |
168 | let fields = fl | 154 | let fields = fl |
169 | .fields() | 155 | .fields() |
@@ -173,7 +159,7 @@ impl VariantData { | |||
173 | type_ref: TypeRef::from_ast_opt(fd.type_ref()), | 159 | type_ref: TypeRef::from_ast_opt(fd.type_ref()), |
174 | }) | 160 | }) |
175 | .collect(); | 161 | .collect(); |
176 | VariantData::Tuple(fields) | 162 | VariantDataInner::Tuple(fields) |
177 | } | 163 | } |
178 | StructFlavor::Named(fl) => { | 164 | StructFlavor::Named(fl) => { |
179 | let fields = fl | 165 | let fields = fl |
@@ -183,16 +169,17 @@ impl VariantData { | |||
183 | type_ref: TypeRef::from_ast_opt(fd.type_ref()), | 169 | type_ref: TypeRef::from_ast_opt(fd.type_ref()), |
184 | }) | 170 | }) |
185 | .collect(); | 171 | .collect(); |
186 | VariantData::Struct(fields) | 172 | VariantDataInner::Struct(fields) |
187 | } | 173 | } |
188 | StructFlavor::Unit => VariantData::Unit, | 174 | StructFlavor::Unit => VariantDataInner::Unit, |
189 | } | 175 | }; |
176 | VariantData(inner) | ||
190 | } | 177 | } |
191 | 178 | ||
192 | pub(crate) fn get_field_type_ref(&self, field_name: &Name) -> Option<&TypeRef> { | 179 | // pub(crate) fn get_field_type_ref(&self, field_name: &Name) -> Option<&TypeRef> { |
193 | self.fields() | 180 | // self.fields() |
194 | .iter() | 181 | // .iter() |
195 | .find(|f| f.name == *field_name) | 182 | // .find(|f| f.name == *field_name) |
196 | .map(|f| &f.type_ref) | 183 | // .map(|f| &f.type_ref) |
197 | } | 184 | // } |
198 | } | 185 | } |
diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index 249a4aba9..118562984 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs | |||
@@ -11,7 +11,7 @@ use crate::{ | |||
11 | db::HirDatabase, | 11 | db::HirDatabase, |
12 | expr::BodySyntaxMapping, | 12 | expr::BodySyntaxMapping, |
13 | ty::{InferenceResult, VariantDef}, | 13 | ty::{InferenceResult, VariantDef}, |
14 | adt::{VariantData, EnumVariantId}, | 14 | adt::{EnumVariantId, StructFieldId}, |
15 | generics::GenericParams, | 15 | generics::GenericParams, |
16 | docs::{Documentation, Docs, docs_from_ast}, | 16 | docs::{Documentation, Docs, docs_from_ast}, |
17 | module_tree::ModuleId, | 17 | module_tree::ModuleId, |
@@ -177,19 +177,25 @@ impl Module { | |||
177 | } | 177 | } |
178 | } | 178 | } |
179 | 179 | ||
180 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 180 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
181 | pub struct StructField { | 181 | pub struct StructField { |
182 | parent: VariantDef, | 182 | parent: VariantDef, |
183 | name: Name, | 183 | pub(crate) id: StructFieldId, |
184 | } | 184 | } |
185 | 185 | ||
186 | impl StructField { | 186 | impl StructField { |
187 | pub fn name(&self) -> &Name { | 187 | pub fn name(&self, db: &impl HirDatabase) -> Name { |
188 | &self.name | 188 | self.parent.variant_data(db).fields().unwrap()[self.id] |
189 | .name | ||
190 | .clone() | ||
189 | } | 191 | } |
190 | 192 | ||
191 | pub fn ty(&self, db: &impl HirDatabase) -> Option<Ty> { | 193 | pub fn ty(&self, db: &impl HirDatabase) -> Ty { |
192 | db.type_for_field(self.parent, self.name.clone()) | 194 | db.type_for_field(*self) |
195 | } | ||
196 | |||
197 | pub fn parent_def(&self, _db: &impl HirDatabase) -> VariantDef { | ||
198 | self.parent | ||
193 | } | 199 | } |
194 | } | 200 | } |
195 | 201 | ||
@@ -215,14 +221,28 @@ impl Struct { | |||
215 | db.struct_data(*self) | 221 | db.struct_data(*self) |
216 | .variant_data | 222 | .variant_data |
217 | .fields() | 223 | .fields() |
218 | .iter() | 224 | .into_iter() |
219 | .map(|it| StructField { | 225 | .flat_map(|it| it.iter()) |
226 | .map(|(id, _)| StructField { | ||
220 | parent: (*self).into(), | 227 | parent: (*self).into(), |
221 | name: it.name.clone(), | 228 | id, |
222 | }) | 229 | }) |
223 | .collect() | 230 | .collect() |
224 | } | 231 | } |
225 | 232 | ||
233 | pub fn field(&self, db: &impl HirDatabase, name: &Name) -> Option<StructField> { | ||
234 | db.struct_data(*self) | ||
235 | .variant_data | ||
236 | .fields() | ||
237 | .into_iter() | ||
238 | .flat_map(|it| it.iter()) | ||
239 | .find(|(_id, data)| data.name == *name) | ||
240 | .map(|(id, _)| StructField { | ||
241 | parent: (*self).into(), | ||
242 | id, | ||
243 | }) | ||
244 | } | ||
245 | |||
226 | pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> { | 246 | pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> { |
227 | db.generic_params((*self).into()) | 247 | db.generic_params((*self).into()) |
228 | } | 248 | } |
@@ -300,22 +320,29 @@ impl EnumVariant { | |||
300 | db.enum_data(self.parent).variants[self.id].name.clone() | 320 | db.enum_data(self.parent).variants[self.id].name.clone() |
301 | } | 321 | } |
302 | 322 | ||
303 | pub fn variant_data(&self, db: &impl HirDatabase) -> Arc<VariantData> { | ||
304 | db.enum_data(self.parent).variants[self.id] | ||
305 | .variant_data | ||
306 | .clone() | ||
307 | } | ||
308 | |||
309 | pub fn fields(&self, db: &impl HirDatabase) -> Vec<StructField> { | 323 | pub fn fields(&self, db: &impl HirDatabase) -> Vec<StructField> { |
310 | self.variant_data(db) | 324 | self.variant_data(db) |
311 | .fields() | 325 | .fields() |
312 | .iter() | 326 | .into_iter() |
313 | .map(|it| StructField { | 327 | .flat_map(|it| it.iter()) |
328 | .map(|(id, _)| StructField { | ||
314 | parent: (*self).into(), | 329 | parent: (*self).into(), |
315 | name: it.name.clone(), | 330 | id, |
316 | }) | 331 | }) |
317 | .collect() | 332 | .collect() |
318 | } | 333 | } |
334 | |||
335 | pub fn field(&self, db: &impl HirDatabase, name: &Name) -> Option<StructField> { | ||
336 | self.variant_data(db) | ||
337 | .fields() | ||
338 | .into_iter() | ||
339 | .flat_map(|it| it.iter()) | ||
340 | .find(|(_id, data)| data.name == *name) | ||
341 | .map(|(id, _)| StructField { | ||
342 | parent: (*self).into(), | ||
343 | id, | ||
344 | }) | ||
345 | } | ||
319 | } | 346 | } |
320 | 347 | ||
321 | impl Docs for EnumVariant { | 348 | impl Docs for EnumVariant { |
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index 5a29e54d6..3c82262a2 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs | |||
@@ -4,15 +4,15 @@ use ra_syntax::{SyntaxNode, TreeArc, SourceFile}; | |||
4 | use ra_db::{SyntaxDatabase, CrateId, salsa}; | 4 | use ra_db::{SyntaxDatabase, CrateId, salsa}; |
5 | 5 | ||
6 | use crate::{ | 6 | use crate::{ |
7 | MacroCallId, Name, HirFileId, | 7 | MacroCallId, HirFileId, |
8 | SourceFileItems, SourceItemId, Crate, Module, HirInterner, | 8 | SourceFileItems, SourceItemId, Crate, Module, HirInterner, |
9 | query_definitions, | 9 | query_definitions, |
10 | Function, FnSignature, FnScopes, | 10 | Function, FnSignature, FnScopes, |
11 | Struct, Enum, | 11 | Struct, Enum, StructField, |
12 | macros::MacroExpansion, | 12 | macros::MacroExpansion, |
13 | module_tree::ModuleTree, | 13 | module_tree::ModuleTree, |
14 | nameres::{ItemMap, lower::{LoweredModule, ImportSourceMap}}, | 14 | nameres::{ItemMap, lower::{LoweredModule, ImportSourceMap}}, |
15 | ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks, TypableDef, VariantDef}, | 15 | ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks, TypableDef}, |
16 | adt::{StructData, EnumData}, | 16 | adt::{StructData, EnumData}, |
17 | impl_block::ModuleImplBlocks, | 17 | impl_block::ModuleImplBlocks, |
18 | generics::{GenericParams, GenericDef}, | 18 | generics::{GenericParams, GenericDef}, |
@@ -42,7 +42,7 @@ pub trait HirDatabase: SyntaxDatabase + AsRef<HirInterner> { | |||
42 | fn type_for_def(&self, def: TypableDef) -> Ty; | 42 | fn type_for_def(&self, def: TypableDef) -> Ty; |
43 | 43 | ||
44 | #[salsa::invoke(crate::ty::type_for_field)] | 44 | #[salsa::invoke(crate::ty::type_for_field)] |
45 | fn type_for_field(&self, def: VariantDef, field: Name) -> Option<Ty>; | 45 | fn type_for_field(&self, field: StructField) -> Ty; |
46 | 46 | ||
47 | #[salsa::invoke(query_definitions::file_items)] | 47 | #[salsa::invoke(query_definitions::file_items)] |
48 | fn file_items(&self, file_id: HirFileId) -> Arc<SourceFileItems>; | 48 | fn file_items(&self, file_id: HirFileId) -> Arc<SourceFileItems>; |
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index c7f77e7a3..c57e222dd 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -38,6 +38,7 @@ use crate::{ | |||
38 | expr::{Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat}, | 38 | expr::{Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat}, |
39 | generics::GenericParams, | 39 | generics::GenericParams, |
40 | path::GenericArg, | 40 | path::GenericArg, |
41 | adt::VariantData, | ||
41 | }; | 42 | }; |
42 | 43 | ||
43 | /// The ID of a type variable. | 44 | /// The ID of a type variable. |
@@ -702,19 +703,30 @@ pub enum VariantDef { | |||
702 | } | 703 | } |
703 | impl_froms!(VariantDef: Struct, EnumVariant); | 704 | impl_froms!(VariantDef: Struct, EnumVariant); |
704 | 705 | ||
705 | pub(super) fn type_for_field(db: &impl HirDatabase, def: VariantDef, field: Name) -> Option<Ty> { | 706 | impl VariantDef { |
706 | let (variant_data, generics, module) = match def { | 707 | pub(crate) fn field(self, db: &impl HirDatabase, name: &Name) -> Option<StructField> { |
707 | VariantDef::Struct(s) => (s.variant_data(db), s.generic_params(db), s.module(db)), | 708 | match self { |
708 | VariantDef::EnumVariant(var) => ( | 709 | VariantDef::Struct(it) => it.field(db, name), |
709 | var.variant_data(db), | 710 | VariantDef::EnumVariant(it) => it.field(db, name), |
710 | var.parent_enum(db).generic_params(db), | 711 | } |
711 | var.module(db), | 712 | } |
712 | ), | 713 | pub(crate) fn variant_data(self, db: &impl HirDatabase) -> Arc<VariantData> { |
714 | match self { | ||
715 | VariantDef::Struct(it) => it.variant_data(db), | ||
716 | VariantDef::EnumVariant(it) => it.variant_data(db), | ||
717 | } | ||
718 | } | ||
719 | } | ||
720 | |||
721 | pub(super) fn type_for_field(db: &impl HirDatabase, field: StructField) -> Ty { | ||
722 | let parent_def = field.parent_def(db); | ||
723 | let (generics, module) = match parent_def { | ||
724 | VariantDef::Struct(it) => (it.generic_params(db), it.module(db)), | ||
725 | VariantDef::EnumVariant(it) => (it.parent_enum(db).generic_params(db), it.module(db)), | ||
713 | }; | 726 | }; |
714 | // We can't have an impl block ere, right? | 727 | let var_data = parent_def.variant_data(db); |
715 | // let impl_block = def_id.impl_block(db); | 728 | let type_ref = &var_data.fields().unwrap()[field.id].type_ref; |
716 | let type_ref = variant_data.get_field_type_ref(&field)?; | 729 | Ty::from_hir(db, &module, None, &generics, type_ref) |
717 | Some(Ty::from_hir(db, &module, None, &generics, &type_ref)) | ||
718 | } | 730 | } |
719 | 731 | ||
720 | /// The result of type inference: A mapping from expressions and patterns to types. | 732 | /// The result of type inference: A mapping from expressions and patterns to types. |
@@ -1122,39 +1134,22 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1122 | } | 1134 | } |
1123 | } | 1135 | } |
1124 | 1136 | ||
1125 | fn resolve_fields(&mut self, path: Option<&Path>) -> Option<(Ty, Vec<StructField>)> { | ||
1126 | let (ty, def) = self.resolve_variant(path); | ||
1127 | match def? { | ||
1128 | VariantDef::Struct(s) => { | ||
1129 | let fields = s.fields(self.db); | ||
1130 | Some((ty, fields)) | ||
1131 | } | ||
1132 | VariantDef::EnumVariant(var) => { | ||
1133 | let fields = var.fields(self.db); | ||
1134 | Some((ty, fields)) | ||
1135 | } | ||
1136 | } | ||
1137 | } | ||
1138 | |||
1139 | fn infer_tuple_struct_pat( | 1137 | fn infer_tuple_struct_pat( |
1140 | &mut self, | 1138 | &mut self, |
1141 | path: Option<&Path>, | 1139 | path: Option<&Path>, |
1142 | subpats: &[PatId], | 1140 | subpats: &[PatId], |
1143 | expected: &Ty, | 1141 | expected: &Ty, |
1144 | ) -> Ty { | 1142 | ) -> Ty { |
1145 | let (ty, fields) = self | 1143 | let (ty, def) = self.resolve_variant(path); |
1146 | .resolve_fields(path) | ||
1147 | .unwrap_or((Ty::Unknown, Vec::new())); | ||
1148 | 1144 | ||
1149 | self.unify(&ty, expected); | 1145 | self.unify(&ty, expected); |
1150 | 1146 | ||
1151 | let substs = ty.substs().unwrap_or_else(Substs::empty); | 1147 | let substs = ty.substs().unwrap_or_else(Substs::empty); |
1152 | 1148 | ||
1153 | for (i, &subpat) in subpats.iter().enumerate() { | 1149 | for (i, &subpat) in subpats.iter().enumerate() { |
1154 | let expected_ty = fields | 1150 | let expected_ty = def |
1155 | .get(i) | 1151 | .and_then(|d| d.field(self.db, &Name::tuple_field_name(i))) |
1156 | .and_then(|field| field.ty(self.db)) | 1152 | .map_or(Ty::Unknown, |field| field.ty(self.db)) |
1157 | .unwrap_or(Ty::Unknown) | ||
1158 | .subst(&substs); | 1153 | .subst(&substs); |
1159 | self.infer_pat(subpat, &expected_ty); | 1154 | self.infer_pat(subpat, &expected_ty); |
1160 | } | 1155 | } |
@@ -1163,19 +1158,16 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1163 | } | 1158 | } |
1164 | 1159 | ||
1165 | fn infer_struct_pat(&mut self, path: Option<&Path>, subpats: &[FieldPat], expected: &Ty) -> Ty { | 1160 | fn infer_struct_pat(&mut self, path: Option<&Path>, subpats: &[FieldPat], expected: &Ty) -> Ty { |
1166 | let (ty, fields) = self | 1161 | let (ty, def) = self.resolve_variant(path); |
1167 | .resolve_fields(path) | ||
1168 | .unwrap_or((Ty::Unknown, Vec::new())); | ||
1169 | 1162 | ||
1170 | self.unify(&ty, expected); | 1163 | self.unify(&ty, expected); |
1171 | 1164 | ||
1172 | let substs = ty.substs().unwrap_or_else(Substs::empty); | 1165 | let substs = ty.substs().unwrap_or_else(Substs::empty); |
1173 | 1166 | ||
1174 | for subpat in subpats { | 1167 | for subpat in subpats { |
1175 | let matching_field = fields.iter().find(|field| field.name() == &subpat.name); | 1168 | let matching_field = def.and_then(|it| it.field(self.db, &subpat.name)); |
1176 | let expected_ty = matching_field | 1169 | let expected_ty = matching_field |
1177 | .and_then(|field| field.ty(self.db)) | 1170 | .map_or(Ty::Unknown, |field| field.ty(self.db)) |
1178 | .unwrap_or(Ty::Unknown) | ||
1179 | .subst(&substs); | 1171 | .subst(&substs); |
1180 | self.infer_pat(subpat.pat, &expected_ty); | 1172 | self.infer_pat(subpat.pat, &expected_ty); |
1181 | } | 1173 | } |
@@ -1420,14 +1412,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1420 | let (ty, def_id) = self.resolve_variant(path.as_ref()); | 1412 | let (ty, def_id) = self.resolve_variant(path.as_ref()); |
1421 | let substs = ty.substs().unwrap_or_else(Substs::empty); | 1413 | let substs = ty.substs().unwrap_or_else(Substs::empty); |
1422 | for field in fields { | 1414 | for field in fields { |
1423 | let field_ty = if let Some(def_id) = def_id { | 1415 | let field_ty = def_id |
1424 | self.db | 1416 | .and_then(|it| it.field(self.db, &field.name)) |
1425 | .type_for_field(def_id.into(), field.name.clone()) | 1417 | .map_or(Ty::Unknown, |field| field.ty(self.db)) |
1426 | .unwrap_or(Ty::Unknown) | 1418 | .subst(&substs); |
1427 | .subst(&substs) | ||
1428 | } else { | ||
1429 | Ty::Unknown | ||
1430 | }; | ||
1431 | self.infer_expr(field.expr, &Expectation::has_type(field_ty)); | 1419 | self.infer_expr(field.expr, &Expectation::has_type(field_ty)); |
1432 | } | 1420 | } |
1433 | if let Some(expr) = spread { | 1421 | if let Some(expr) = spread { |
@@ -1440,7 +1428,6 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1440 | let ty = receiver_ty | 1428 | let ty = receiver_ty |
1441 | .autoderef(self.db) | 1429 | .autoderef(self.db) |
1442 | .find_map(|derefed_ty| match derefed_ty { | 1430 | .find_map(|derefed_ty| match derefed_ty { |
1443 | // this is more complicated than necessary because type_for_field is cancelable | ||
1444 | Ty::Tuple(fields) => { | 1431 | Ty::Tuple(fields) => { |
1445 | let i = name.to_string().parse::<usize>().ok(); | 1432 | let i = name.to_string().parse::<usize>().ok(); |
1446 | i.and_then(|i| fields.get(i).cloned()) | 1433 | i.and_then(|i| fields.get(i).cloned()) |
@@ -1449,10 +1436,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1449 | def_id: AdtDef::Struct(s), | 1436 | def_id: AdtDef::Struct(s), |
1450 | ref substs, | 1437 | ref substs, |
1451 | .. | 1438 | .. |
1452 | } => self | 1439 | } => s |
1453 | .db | 1440 | .field(self.db, name) |
1454 | .type_for_field(s.into(), name.clone()) | 1441 | .map(|field| field.ty(self.db).subst(substs)), |
1455 | .map(|ty| ty.subst(substs)), | ||
1456 | _ => None, | 1442 | _ => None, |
1457 | }) | 1443 | }) |
1458 | .unwrap_or(Ty::Unknown); | 1444 | .unwrap_or(Ty::Unknown); |
diff --git a/crates/ra_ide_api/src/completion/complete_dot.rs b/crates/ra_ide_api/src/completion/complete_dot.rs index 6a9358d33..060a46c5e 100644 --- a/crates/ra_ide_api/src/completion/complete_dot.rs +++ b/crates/ra_ide_api/src/completion/complete_dot.rs | |||
@@ -34,10 +34,10 @@ fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) | |||
34 | CompletionItem::new( | 34 | CompletionItem::new( |
35 | CompletionKind::Reference, | 35 | CompletionKind::Reference, |
36 | ctx.source_range(), | 36 | ctx.source_range(), |
37 | field.name().to_string(), | 37 | field.name(ctx.db).to_string(), |
38 | ) | 38 | ) |
39 | .kind(CompletionItemKind::Field) | 39 | .kind(CompletionItemKind::Field) |
40 | .set_detail(field.ty(ctx.db).map(|ty| ty.subst(substs).to_string())) | 40 | .detail(field.ty(ctx.db).subst(substs).to_string()) |
41 | .add_to(acc); | 41 | .add_to(acc); |
42 | } | 42 | } |
43 | } | 43 | } |