diff options
author | Florian Diebold <[email protected]> | 2019-01-12 20:27:35 +0000 |
---|---|---|
committer | Florian Diebold <[email protected]> | 2019-01-19 15:02:06 +0000 |
commit | 688a45e00b53412a7a16360c6d678a5d91a95789 (patch) | |
tree | d3f3481bbad9889d22867729e9efcde184e45671 | |
parent | 415cdc52108807126f0339fbf812856582f01c18 (diff) |
Implement beginnings of generics
- add HIR for generic params
- resolve generic params in type paths
- add substitions for ADTs
- insert type variables for substitutions
-rw-r--r-- | crates/ra_hir/src/adt.rs | 5 | ||||
-rw-r--r-- | crates/ra_hir/src/code_model_api.rs | 21 | ||||
-rw-r--r-- | crates/ra_hir/src/db.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir/src/generics.rs | 48 | ||||
-rw-r--r-- | crates/ra_hir/src/lib.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir/src/mock.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir/src/ty.rs | 180 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/method_resolution.rs | 17 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests/data/function_generics.txt | 20 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests/data/generic_chain.txt | 44 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests/data/struct_generics.txt | 22 | ||||
-rw-r--r-- | crates/ra_ide_api/src/completion/complete_dot.rs | 6 | ||||
-rw-r--r-- | crates/ra_ide_api/src/db.rs | 1 |
13 files changed, 288 insertions, 82 deletions
diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs index d87fe7049..ab1c428db 100644 --- a/crates/ra_hir/src/adt.rs +++ b/crates/ra_hir/src/adt.rs | |||
@@ -1,3 +1,6 @@ | |||
1 | //! This module contains the implementation details of the HIR for ADTs, i.e. | ||
2 | //! structs and enums (and unions). | ||
3 | |||
1 | use std::sync::Arc; | 4 | use std::sync::Arc; |
2 | 5 | ||
3 | use ra_syntax::{ | 6 | use ra_syntax::{ |
@@ -62,7 +65,7 @@ fn get_def_id( | |||
62 | }; | 65 | }; |
63 | let loc = DefLoc { | 66 | let loc = DefLoc { |
64 | kind: expected_kind, | 67 | kind: expected_kind, |
65 | source_item_id: source_item_id, | 68 | source_item_id, |
66 | ..*same_file_loc | 69 | ..*same_file_loc |
67 | }; | 70 | }; |
68 | loc.id(db) | 71 | loc.id(db) |
diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index 11e919c1a..6c85e5939 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs | |||
@@ -12,6 +12,7 @@ use crate::{ | |||
12 | expr::BodySyntaxMapping, | 12 | expr::BodySyntaxMapping, |
13 | ty::InferenceResult, | 13 | ty::InferenceResult, |
14 | adt::VariantData, | 14 | adt::VariantData, |
15 | generics::Generics, | ||
15 | code_model_impl::def_id_to_ast, | 16 | code_model_impl::def_id_to_ast, |
16 | }; | 17 | }; |
17 | 18 | ||
@@ -201,6 +202,10 @@ impl Struct { | |||
201 | pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::StructDef>) { | 202 | pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::StructDef>) { |
202 | def_id_to_ast(db, self.def_id) | 203 | def_id_to_ast(db, self.def_id) |
203 | } | 204 | } |
205 | |||
206 | pub fn generics(&self, db: &impl HirDatabase) -> Arc<Generics> { | ||
207 | db.generics(self.def_id) | ||
208 | } | ||
204 | } | 209 | } |
205 | 210 | ||
206 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 211 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
@@ -228,6 +233,10 @@ impl Enum { | |||
228 | pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::EnumDef>) { | 233 | pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::EnumDef>) { |
229 | def_id_to_ast(db, self.def_id) | 234 | def_id_to_ast(db, self.def_id) |
230 | } | 235 | } |
236 | |||
237 | pub fn generics(&self, db: &impl HirDatabase) -> Arc<Generics> { | ||
238 | db.generics(self.def_id) | ||
239 | } | ||
231 | } | 240 | } |
232 | 241 | ||
233 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 242 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
@@ -339,6 +348,10 @@ impl Function { | |||
339 | pub fn infer(&self, db: &impl HirDatabase) -> Arc<InferenceResult> { | 348 | pub fn infer(&self, db: &impl HirDatabase) -> Arc<InferenceResult> { |
340 | db.infer(self.def_id) | 349 | db.infer(self.def_id) |
341 | } | 350 | } |
351 | |||
352 | pub fn generics(&self, db: &impl HirDatabase) -> Arc<Generics> { | ||
353 | db.generics(self.def_id) | ||
354 | } | ||
342 | } | 355 | } |
343 | 356 | ||
344 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 357 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
@@ -384,6 +397,10 @@ impl Trait { | |||
384 | pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::TraitDef>) { | 397 | pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::TraitDef>) { |
385 | def_id_to_ast(db, self.def_id) | 398 | def_id_to_ast(db, self.def_id) |
386 | } | 399 | } |
400 | |||
401 | pub fn generics(&self, db: &impl HirDatabase) -> Arc<Generics> { | ||
402 | db.generics(self.def_id) | ||
403 | } | ||
387 | } | 404 | } |
388 | 405 | ||
389 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 406 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
@@ -399,4 +416,8 @@ impl Type { | |||
399 | pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::TypeDef>) { | 416 | pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::TypeDef>) { |
400 | def_id_to_ast(db, self.def_id) | 417 | def_id_to_ast(db, self.def_id) |
401 | } | 418 | } |
419 | |||
420 | pub fn generics(&self, db: &impl HirDatabase) -> Arc<Generics> { | ||
421 | db.generics(self.def_id) | ||
422 | } | ||
402 | } | 423 | } |
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index 60065cf6a..10e64f880 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs | |||
@@ -14,6 +14,7 @@ use crate::{ | |||
14 | ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks}, | 14 | ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks}, |
15 | adt::{StructData, EnumData, EnumVariantData}, | 15 | adt::{StructData, EnumData, EnumVariantData}, |
16 | impl_block::ModuleImplBlocks, | 16 | impl_block::ModuleImplBlocks, |
17 | generics::Generics, | ||
17 | }; | 18 | }; |
18 | 19 | ||
19 | #[salsa::query_group] | 20 | #[salsa::query_group] |
@@ -101,6 +102,9 @@ pub trait HirDatabase: | |||
101 | #[salsa::invoke(crate::expr::body_syntax_mapping)] | 102 | #[salsa::invoke(crate::expr::body_syntax_mapping)] |
102 | fn body_syntax_mapping(&self, def_id: DefId) -> Arc<crate::expr::BodySyntaxMapping>; | 103 | fn body_syntax_mapping(&self, def_id: DefId) -> Arc<crate::expr::BodySyntaxMapping>; |
103 | 104 | ||
105 | #[salsa::invoke(crate::generics::Generics::generics_query)] | ||
106 | fn generics(&self, def_id: DefId) -> Arc<Generics>; | ||
107 | |||
104 | #[salsa::invoke(crate::FnSignature::fn_signature_query)] | 108 | #[salsa::invoke(crate::FnSignature::fn_signature_query)] |
105 | fn fn_signature(&self, def_id: DefId) -> Arc<FnSignature>; | 109 | fn fn_signature(&self, def_id: DefId) -> Arc<FnSignature>; |
106 | } | 110 | } |
diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs new file mode 100644 index 000000000..cdabc0424 --- /dev/null +++ b/crates/ra_hir/src/generics.rs | |||
@@ -0,0 +1,48 @@ | |||
1 | //! Many kinds of items or constructs can have generic parameters: functions, | ||
2 | //! structs, impls, traits, etc. This module provides a common HIR for these | ||
3 | //! generic parameters. See also the `Generics` type and the `generics_of` query | ||
4 | //! in rustc. | ||
5 | |||
6 | use std::sync::Arc; | ||
7 | |||
8 | use ra_syntax::ast::{TypeParamList, AstNode, NameOwner}; | ||
9 | |||
10 | use crate::{db::HirDatabase, DefId, Name, AsName}; | ||
11 | |||
12 | /// Data about a generic parameter (to a function, struct, impl, ...). | ||
13 | #[derive(Clone, PartialEq, Eq, Debug)] | ||
14 | pub struct GenericParam { | ||
15 | pub(crate) idx: u32, | ||
16 | pub(crate) name: Name, | ||
17 | } | ||
18 | |||
19 | /// Data about the generic parameters of a function, struct, impl, etc. | ||
20 | #[derive(Clone, PartialEq, Eq, Debug, Default)] | ||
21 | pub struct Generics { | ||
22 | pub(crate) params: Vec<GenericParam>, | ||
23 | } | ||
24 | |||
25 | impl Generics { | ||
26 | pub(crate) fn generics_query(db: &impl HirDatabase, def_id: DefId) -> Arc<Generics> { | ||
27 | let (_file_id, node) = def_id.source(db); | ||
28 | let mut generics = Generics::default(); | ||
29 | if let Some(type_param_list) = node.children().find_map(TypeParamList::cast) { | ||
30 | for (idx, type_param) in type_param_list.type_params().enumerate() { | ||
31 | let name = type_param | ||
32 | .name() | ||
33 | .map(AsName::as_name) | ||
34 | .unwrap_or_else(Name::missing); | ||
35 | let param = GenericParam { | ||
36 | idx: idx as u32, | ||
37 | name, | ||
38 | }; | ||
39 | generics.params.push(param); | ||
40 | } | ||
41 | } | ||
42 | Arc::new(generics) | ||
43 | } | ||
44 | |||
45 | pub(crate) fn find_by_name(&self, name: &Name) -> Option<&GenericParam> { | ||
46 | self.params.iter().find(|p| &p.name == name) | ||
47 | } | ||
48 | } | ||
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index f1402a286..361d39f03 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs | |||
@@ -24,6 +24,7 @@ mod type_ref; | |||
24 | mod ty; | 24 | mod ty; |
25 | mod impl_block; | 25 | mod impl_block; |
26 | mod expr; | 26 | mod expr; |
27 | mod generics; | ||
27 | 28 | ||
28 | mod code_model_api; | 29 | mod code_model_api; |
29 | mod code_model_impl; | 30 | mod code_model_impl; |
diff --git a/crates/ra_hir/src/mock.rs b/crates/ra_hir/src/mock.rs index 018e5e0d4..d674db8e6 100644 --- a/crates/ra_hir/src/mock.rs +++ b/crates/ra_hir/src/mock.rs | |||
@@ -243,6 +243,7 @@ salsa::database_storage! { | |||
243 | fn body_hir() for db::BodyHirQuery; | 243 | fn body_hir() for db::BodyHirQuery; |
244 | fn body_syntax_mapping() for db::BodySyntaxMappingQuery; | 244 | fn body_syntax_mapping() for db::BodySyntaxMappingQuery; |
245 | fn fn_signature() for db::FnSignatureQuery; | 245 | fn fn_signature() for db::FnSignatureQuery; |
246 | fn generics() for db::GenericsQuery; | ||
246 | } | 247 | } |
247 | } | 248 | } |
248 | } | 249 | } |
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 8d6493887..b9a48929d 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -37,6 +37,7 @@ use crate::{ | |||
37 | type_ref::{TypeRef, Mutability}, | 37 | type_ref::{TypeRef, Mutability}, |
38 | name::KnownName, | 38 | name::KnownName, |
39 | expr::{Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat}, | 39 | expr::{Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat}, |
40 | generics::Generics, | ||
40 | }; | 41 | }; |
41 | 42 | ||
42 | /// The ID of a type variable. | 43 | /// The ID of a type variable. |
@@ -151,10 +152,14 @@ impl Expectation { | |||
151 | } | 152 | } |
152 | } | 153 | } |
153 | 154 | ||
155 | /// A list of substitutions for generic parameters. | ||
156 | #[derive(Clone, PartialEq, Eq, Debug)] | ||
157 | pub struct Substs(Arc<[Ty]>); | ||
158 | |||
154 | /// A type. This is based on the `TyKind` enum in rustc (librustc/ty/sty.rs). | 159 | /// A type. This is based on the `TyKind` enum in rustc (librustc/ty/sty.rs). |
155 | /// | 160 | /// |
156 | /// This should be cheap to clone. | 161 | /// This should be cheap to clone. |
157 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] | 162 | #[derive(Clone, PartialEq, Eq, Debug)] |
158 | pub enum Ty { | 163 | pub enum Ty { |
159 | /// The primitive boolean type. Written as `bool`. | 164 | /// The primitive boolean type. Written as `bool`. |
160 | Bool, | 165 | Bool, |
@@ -175,7 +180,8 @@ pub enum Ty { | |||
175 | def_id: DefId, | 180 | def_id: DefId, |
176 | /// The name, for displaying. | 181 | /// The name, for displaying. |
177 | name: Name, | 182 | name: Name, |
178 | // later we'll need generic substitutions here | 183 | /// Substitutions for the generic parameters of the type. |
184 | substs: Substs, | ||
179 | }, | 185 | }, |
180 | 186 | ||
181 | /// The pointee of a string slice. Written as `str`. | 187 | /// The pointee of a string slice. Written as `str`. |
@@ -234,9 +240,14 @@ pub enum Ty { | |||
234 | 240 | ||
235 | // Opaque (`impl Trait`) type found in a return type. | 241 | // Opaque (`impl Trait`) type found in a return type. |
236 | // Opaque(DefId, Substs), | 242 | // Opaque(DefId, Substs), |
243 | /// A type parameter; for example, `T` in `fn f<T>(x: T) {} | ||
244 | Param { | ||
245 | /// The index of the parameter. | ||
246 | idx: u32, | ||
247 | /// The name of the parameter, for displaying. | ||
248 | name: Name, | ||
249 | }, | ||
237 | 250 | ||
238 | // A type parameter; for example, `T` in `fn f<T>(x: T) {} | ||
239 | // Param(ParamTy), | ||
240 | /// A type variable used during type checking. Not to be confused with a | 251 | /// A type variable used during type checking. Not to be confused with a |
241 | /// type parameter. | 252 | /// type parameter. |
242 | Infer(InferTy), | 253 | Infer(InferTy), |
@@ -250,7 +261,7 @@ pub enum Ty { | |||
250 | } | 261 | } |
251 | 262 | ||
252 | /// A function signature. | 263 | /// A function signature. |
253 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] | 264 | #[derive(Clone, PartialEq, Eq, Debug)] |
254 | pub struct FnSig { | 265 | pub struct FnSig { |
255 | input: Vec<Ty>, | 266 | input: Vec<Ty>, |
256 | output: Ty, | 267 | output: Ty, |
@@ -261,6 +272,7 @@ impl Ty { | |||
261 | db: &impl HirDatabase, | 272 | db: &impl HirDatabase, |
262 | module: &Module, | 273 | module: &Module, |
263 | impl_block: Option<&ImplBlock>, | 274 | impl_block: Option<&ImplBlock>, |
275 | generics: &Generics, | ||
264 | type_ref: &TypeRef, | 276 | type_ref: &TypeRef, |
265 | ) -> Self { | 277 | ) -> Self { |
266 | match type_ref { | 278 | match type_ref { |
@@ -268,32 +280,32 @@ impl Ty { | |||
268 | TypeRef::Tuple(inner) => { | 280 | TypeRef::Tuple(inner) => { |
269 | let inner_tys = inner | 281 | let inner_tys = inner |
270 | .iter() | 282 | .iter() |
271 | .map(|tr| Ty::from_hir(db, module, impl_block, tr)) | 283 | .map(|tr| Ty::from_hir(db, module, impl_block, generics, tr)) |
272 | .collect::<Vec<_>>(); | 284 | .collect::<Vec<_>>(); |
273 | Ty::Tuple(inner_tys.into()) | 285 | Ty::Tuple(inner_tys.into()) |
274 | } | 286 | } |
275 | TypeRef::Path(path) => Ty::from_hir_path(db, module, impl_block, path), | 287 | TypeRef::Path(path) => Ty::from_hir_path(db, module, impl_block, generics, path), |
276 | TypeRef::RawPtr(inner, mutability) => { | 288 | TypeRef::RawPtr(inner, mutability) => { |
277 | let inner_ty = Ty::from_hir(db, module, impl_block, inner); | 289 | let inner_ty = Ty::from_hir(db, module, impl_block, generics, inner); |
278 | Ty::RawPtr(Arc::new(inner_ty), *mutability) | 290 | Ty::RawPtr(Arc::new(inner_ty), *mutability) |
279 | } | 291 | } |
280 | TypeRef::Array(inner) => { | 292 | TypeRef::Array(inner) => { |
281 | let inner_ty = Ty::from_hir(db, module, impl_block, inner); | 293 | let inner_ty = Ty::from_hir(db, module, impl_block, generics, inner); |
282 | Ty::Array(Arc::new(inner_ty)) | 294 | Ty::Array(Arc::new(inner_ty)) |
283 | } | 295 | } |
284 | TypeRef::Slice(inner) => { | 296 | TypeRef::Slice(inner) => { |
285 | let inner_ty = Ty::from_hir(db, module, impl_block, inner); | 297 | let inner_ty = Ty::from_hir(db, module, impl_block, generics, inner); |
286 | Ty::Slice(Arc::new(inner_ty)) | 298 | Ty::Slice(Arc::new(inner_ty)) |
287 | } | 299 | } |
288 | TypeRef::Reference(inner, mutability) => { | 300 | TypeRef::Reference(inner, mutability) => { |
289 | let inner_ty = Ty::from_hir(db, module, impl_block, inner); | 301 | let inner_ty = Ty::from_hir(db, module, impl_block, generics, inner); |
290 | Ty::Ref(Arc::new(inner_ty), *mutability) | 302 | Ty::Ref(Arc::new(inner_ty), *mutability) |
291 | } | 303 | } |
292 | TypeRef::Placeholder => Ty::Unknown, | 304 | TypeRef::Placeholder => Ty::Unknown, |
293 | TypeRef::Fn(params) => { | 305 | TypeRef::Fn(params) => { |
294 | let mut inner_tys = params | 306 | let mut inner_tys = params |
295 | .iter() | 307 | .iter() |
296 | .map(|tr| Ty::from_hir(db, module, impl_block, tr)) | 308 | .map(|tr| Ty::from_hir(db, module, impl_block, generics, tr)) |
297 | .collect::<Vec<_>>(); | 309 | .collect::<Vec<_>>(); |
298 | let return_ty = inner_tys | 310 | let return_ty = inner_tys |
299 | .pop() | 311 | .pop() |
@@ -312,15 +324,19 @@ impl Ty { | |||
312 | db: &impl HirDatabase, | 324 | db: &impl HirDatabase, |
313 | module: &Module, | 325 | module: &Module, |
314 | impl_block: Option<&ImplBlock>, | 326 | impl_block: Option<&ImplBlock>, |
327 | generics: &Generics, | ||
315 | type_ref: Option<&TypeRef>, | 328 | type_ref: Option<&TypeRef>, |
316 | ) -> Self { | 329 | ) -> Self { |
317 | type_ref.map_or(Ty::Unknown, |t| Ty::from_hir(db, module, impl_block, t)) | 330 | type_ref.map_or(Ty::Unknown, |t| { |
331 | Ty::from_hir(db, module, impl_block, generics, t) | ||
332 | }) | ||
318 | } | 333 | } |
319 | 334 | ||
320 | pub(crate) fn from_hir_path( | 335 | pub(crate) fn from_hir_path( |
321 | db: &impl HirDatabase, | 336 | db: &impl HirDatabase, |
322 | module: &Module, | 337 | module: &Module, |
323 | impl_block: Option<&ImplBlock>, | 338 | impl_block: Option<&ImplBlock>, |
339 | generics: &Generics, | ||
324 | path: &Path, | 340 | path: &Path, |
325 | ) -> Self { | 341 | ) -> Self { |
326 | if let Some(name) = path.as_ident() { | 342 | if let Some(name) = path.as_ident() { |
@@ -329,7 +345,15 @@ impl Ty { | |||
329 | } else if let Some(float_ty) = primitive::UncertainFloatTy::from_name(name) { | 345 | } else if let Some(float_ty) = primitive::UncertainFloatTy::from_name(name) { |
330 | return Ty::Float(float_ty); | 346 | return Ty::Float(float_ty); |
331 | } else if name.as_known_name() == Some(KnownName::SelfType) { | 347 | } else if name.as_known_name() == Some(KnownName::SelfType) { |
332 | return Ty::from_hir_opt(db, module, None, impl_block.map(|i| i.target_type())); | 348 | // TODO pass the impl block's generics? |
349 | let generics = &Generics::default(); | ||
350 | return Ty::from_hir_opt( | ||
351 | db, | ||
352 | module, | ||
353 | None, | ||
354 | generics, | ||
355 | impl_block.map(|i| i.target_type()), | ||
356 | ); | ||
333 | } else if let Some(known) = name.as_known_name() { | 357 | } else if let Some(known) = name.as_known_name() { |
334 | match known { | 358 | match known { |
335 | KnownName::Bool => return Ty::Bool, | 359 | KnownName::Bool => return Ty::Bool, |
@@ -337,6 +361,11 @@ impl Ty { | |||
337 | KnownName::Str => return Ty::Str, | 361 | KnownName::Str => return Ty::Str, |
338 | _ => {} | 362 | _ => {} |
339 | } | 363 | } |
364 | } else if let Some(generic_param) = generics.find_by_name(&name) { | ||
365 | return Ty::Param { | ||
366 | idx: generic_param.idx, | ||
367 | name: generic_param.name.clone(), | ||
368 | }; | ||
340 | } | 369 | } |
341 | } | 370 | } |
342 | 371 | ||
@@ -374,7 +403,14 @@ impl Ty { | |||
374 | } | 403 | } |
375 | sig_mut.output.walk_mut(f); | 404 | sig_mut.output.walk_mut(f); |
376 | } | 405 | } |
377 | Ty::Adt { .. } => {} // need to walk type parameters later | 406 | Ty::Adt { substs, .. } => { |
407 | // Without an Arc::make_mut_slice, we can't avoid the clone here: | ||
408 | let mut v: Vec<_> = substs.0.iter().cloned().collect(); | ||
409 | for t in &mut v { | ||
410 | t.walk_mut(f); | ||
411 | } | ||
412 | substs.0 = v.into(); | ||
413 | } | ||
378 | _ => {} | 414 | _ => {} |
379 | } | 415 | } |
380 | } | 416 | } |
@@ -394,6 +430,32 @@ impl Ty { | |||
394 | _ => None, | 430 | _ => None, |
395 | } | 431 | } |
396 | } | 432 | } |
433 | |||
434 | /// Replaces type parameters in this type using the given `Substs`. (So e.g. | ||
435 | /// if `self` is `&[T]`, where type parameter T has index 0, and the | ||
436 | /// `Substs` contain `u32` at index 0, we'll have `&[u32]` afterwards.) | ||
437 | pub fn subst(self, substs: &Substs) -> Ty { | ||
438 | self.fold(&mut |ty| match ty { | ||
439 | Ty::Param { idx, name } => { | ||
440 | if (idx as usize) < substs.0.len() { | ||
441 | substs.0[idx as usize].clone() | ||
442 | } else { | ||
443 | // TODO it's yet unclear to me whether we need to shift the indices here | ||
444 | Ty::Param { idx, name } | ||
445 | } | ||
446 | } | ||
447 | ty => ty, | ||
448 | }) | ||
449 | } | ||
450 | |||
451 | /// Returns the type parameters of this type if it has some (i.e. is an ADT | ||
452 | /// or function); so if `self` is `Option<u32>`, this returns the `u32`. | ||
453 | fn substs(&self) -> Option<Substs> { | ||
454 | match self { | ||
455 | Ty::Adt { substs, .. } => Some(substs.clone()), | ||
456 | _ => None, | ||
457 | } | ||
458 | } | ||
397 | } | 459 | } |
398 | 460 | ||
399 | impl fmt::Display for Ty { | 461 | impl fmt::Display for Ty { |
@@ -425,7 +487,17 @@ impl fmt::Display for Ty { | |||
425 | .to_fmt(f)?; | 487 | .to_fmt(f)?; |
426 | write!(f, " -> {}", sig.output) | 488 | write!(f, " -> {}", sig.output) |
427 | } | 489 | } |
428 | Ty::Adt { name, .. } => write!(f, "{}", name), | 490 | Ty::Adt { name, substs, .. } => { |
491 | write!(f, "{}", name)?; | ||
492 | if substs.0.len() > 0 { | ||
493 | join(substs.0.iter()) | ||
494 | .surround_with("<", ">") | ||
495 | .separator(", ") | ||
496 | .to_fmt(f)?; | ||
497 | } | ||
498 | Ok(()) | ||
499 | } | ||
500 | Ty::Param { name, .. } => write!(f, "{}", name), | ||
429 | Ty::Unknown => write!(f, "[unknown]"), | 501 | Ty::Unknown => write!(f, "[unknown]"), |
430 | Ty::Infer(..) => write!(f, "_"), | 502 | Ty::Infer(..) => write!(f, "_"), |
431 | } | 503 | } |
@@ -440,28 +512,49 @@ fn type_for_fn(db: &impl HirDatabase, f: Function) -> Ty { | |||
440 | let signature = f.signature(db); | 512 | let signature = f.signature(db); |
441 | let module = f.module(db); | 513 | let module = f.module(db); |
442 | let impl_block = f.impl_block(db); | 514 | let impl_block = f.impl_block(db); |
443 | // TODO we ignore type parameters for now | 515 | let generics = f.generics(db); |
444 | let input = signature | 516 | let input = signature |
445 | .params() | 517 | .params() |
446 | .iter() | 518 | .iter() |
447 | .map(|tr| Ty::from_hir(db, &module, impl_block.as_ref(), tr)) | 519 | .map(|tr| Ty::from_hir(db, &module, impl_block.as_ref(), &generics, tr)) |
448 | .collect::<Vec<_>>(); | 520 | .collect::<Vec<_>>(); |
449 | let output = Ty::from_hir(db, &module, impl_block.as_ref(), signature.ret_type()); | 521 | let output = Ty::from_hir( |
522 | db, | ||
523 | &module, | ||
524 | impl_block.as_ref(), | ||
525 | &generics, | ||
526 | signature.ret_type(), | ||
527 | ); | ||
450 | let sig = FnSig { input, output }; | 528 | let sig = FnSig { input, output }; |
451 | Ty::FnPtr(Arc::new(sig)) | 529 | Ty::FnPtr(Arc::new(sig)) |
452 | } | 530 | } |
453 | 531 | ||
532 | fn make_substs(generics: &Generics) -> Substs { | ||
533 | Substs( | ||
534 | generics | ||
535 | .params | ||
536 | .iter() | ||
537 | .map(|_p| Ty::Unknown) | ||
538 | .collect::<Vec<_>>() | ||
539 | .into(), | ||
540 | ) | ||
541 | } | ||
542 | |||
454 | fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty { | 543 | fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty { |
544 | let generics = s.generics(db); | ||
455 | Ty::Adt { | 545 | Ty::Adt { |
456 | def_id: s.def_id(), | 546 | def_id: s.def_id(), |
457 | name: s.name(db).unwrap_or_else(Name::missing), | 547 | name: s.name(db).unwrap_or_else(Name::missing), |
548 | substs: make_substs(&generics), | ||
458 | } | 549 | } |
459 | } | 550 | } |
460 | 551 | ||
461 | pub(crate) fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty { | 552 | pub(crate) fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty { |
553 | let generics = s.generics(db); | ||
462 | Ty::Adt { | 554 | Ty::Adt { |
463 | def_id: s.def_id(), | 555 | def_id: s.def_id(), |
464 | name: s.name(db).unwrap_or_else(Name::missing), | 556 | name: s.name(db).unwrap_or_else(Name::missing), |
557 | substs: make_substs(&generics), | ||
465 | } | 558 | } |
466 | } | 559 | } |
467 | 560 | ||
@@ -506,8 +599,15 @@ pub(super) fn type_for_field(db: &impl HirDatabase, def_id: DefId, field: Name) | |||
506 | }; | 599 | }; |
507 | let module = def_id.module(db); | 600 | let module = def_id.module(db); |
508 | let impl_block = def_id.impl_block(db); | 601 | let impl_block = def_id.impl_block(db); |
602 | let generics = db.generics(def_id); | ||
509 | let type_ref = variant_data.get_field_type_ref(&field)?; | 603 | let type_ref = variant_data.get_field_type_ref(&field)?; |
510 | Some(Ty::from_hir(db, &module, impl_block.as_ref(), &type_ref)) | 604 | Some(Ty::from_hir( |
605 | db, | ||
606 | &module, | ||
607 | impl_block.as_ref(), | ||
608 | &generics, | ||
609 | &type_ref, | ||
610 | )) | ||
511 | } | 611 | } |
512 | 612 | ||
513 | /// The result of type inference: A mapping from expressions and patterns to types. | 613 | /// The result of type inference: A mapping from expressions and patterns to types. |
@@ -684,8 +784,18 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
684 | self.type_of_pat.insert(pat, ty); | 784 | self.type_of_pat.insert(pat, ty); |
685 | } | 785 | } |
686 | 786 | ||
687 | fn make_ty(&self, type_ref: &TypeRef) -> Ty { | 787 | fn make_ty(&mut self, type_ref: &TypeRef) -> Ty { |
688 | Ty::from_hir(self.db, &self.module, self.impl_block.as_ref(), type_ref) | 788 | // TODO provide generics of function |
789 | let generics = Generics::default(); | ||
790 | let ty = Ty::from_hir( | ||
791 | self.db, | ||
792 | &self.module, | ||
793 | self.impl_block.as_ref(), | ||
794 | &generics, | ||
795 | type_ref, | ||
796 | ); | ||
797 | let ty = self.insert_type_vars(ty); | ||
798 | ty | ||
689 | } | 799 | } |
690 | 800 | ||
691 | fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool { | 801 | fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool { |
@@ -848,7 +958,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
848 | Some(ty) | 958 | Some(ty) |
849 | } | 959 | } |
850 | 960 | ||
851 | fn resolve_variant(&self, path: Option<&Path>) -> (Ty, Option<DefId>) { | 961 | fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<DefId>) { |
852 | let path = if let Some(path) = path { | 962 | let path = if let Some(path) = path { |
853 | path | 963 | path |
854 | } else { | 964 | } else { |
@@ -862,10 +972,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
862 | match def_id.resolve(self.db) { | 972 | match def_id.resolve(self.db) { |
863 | Def::Struct(s) => { | 973 | Def::Struct(s) => { |
864 | let ty = type_for_struct(self.db, s); | 974 | let ty = type_for_struct(self.db, s); |
975 | let ty = self.insert_type_vars(ty); | ||
865 | (ty, Some(def_id)) | 976 | (ty, Some(def_id)) |
866 | } | 977 | } |
867 | Def::EnumVariant(ev) => { | 978 | Def::EnumVariant(ev) => { |
868 | let ty = type_for_enum_variant(self.db, ev); | 979 | let ty = type_for_enum_variant(self.db, ev); |
980 | let ty = self.insert_type_vars(ty); | ||
869 | (ty, Some(def_id)) | 981 | (ty, Some(def_id)) |
870 | } | 982 | } |
871 | _ => (Ty::Unknown, None), | 983 | _ => (Ty::Unknown, None), |
@@ -1155,11 +1267,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1155 | spread, | 1267 | spread, |
1156 | } => { | 1268 | } => { |
1157 | let (ty, def_id) = self.resolve_variant(path.as_ref()); | 1269 | let (ty, def_id) = self.resolve_variant(path.as_ref()); |
1270 | let substs = ty.substs().expect("adt should have substs"); | ||
1158 | for field in fields { | 1271 | for field in fields { |
1159 | let field_ty = if let Some(def_id) = def_id { | 1272 | let field_ty = if let Some(def_id) = def_id { |
1160 | self.db | 1273 | self.db |
1161 | .type_for_field(def_id, field.name.clone()) | 1274 | .type_for_field(def_id, field.name.clone()) |
1162 | .unwrap_or(Ty::Unknown) | 1275 | .unwrap_or(Ty::Unknown) |
1276 | .subst(&substs) | ||
1163 | } else { | 1277 | } else { |
1164 | Ty::Unknown | 1278 | Ty::Unknown |
1165 | }; | 1279 | }; |
@@ -1180,7 +1294,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1180 | let i = name.to_string().parse::<usize>().ok(); | 1294 | let i = name.to_string().parse::<usize>().ok(); |
1181 | i.and_then(|i| fields.get(i).cloned()) | 1295 | i.and_then(|i| fields.get(i).cloned()) |
1182 | } | 1296 | } |
1183 | Ty::Adt { def_id, .. } => self.db.type_for_field(def_id, name.clone()), | 1297 | Ty::Adt { |
1298 | def_id, ref substs, .. | ||
1299 | } => self | ||
1300 | .db | ||
1301 | .type_for_field(def_id, name.clone()) | ||
1302 | .map(|ty| ty.subst(substs)), | ||
1184 | _ => None, | 1303 | _ => None, |
1185 | }) | 1304 | }) |
1186 | .unwrap_or(Ty::Unknown); | 1305 | .unwrap_or(Ty::Unknown); |
@@ -1193,7 +1312,6 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1193 | Expr::Cast { expr, type_ref } => { | 1312 | Expr::Cast { expr, type_ref } => { |
1194 | let _inner_ty = self.infer_expr(*expr, &Expectation::none()); | 1313 | let _inner_ty = self.infer_expr(*expr, &Expectation::none()); |
1195 | let cast_ty = self.make_ty(type_ref); | 1314 | let cast_ty = self.make_ty(type_ref); |
1196 | let cast_ty = self.insert_type_vars(cast_ty); | ||
1197 | // TODO check the cast... | 1315 | // TODO check the cast... |
1198 | cast_ty | 1316 | cast_ty |
1199 | } | 1317 | } |
@@ -1305,12 +1423,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1305 | type_ref, | 1423 | type_ref, |
1306 | initializer, | 1424 | initializer, |
1307 | } => { | 1425 | } => { |
1308 | let decl_ty = Ty::from_hir_opt( | 1426 | let decl_ty = type_ref |
1309 | self.db, | 1427 | .as_ref() |
1310 | &self.module, | 1428 | .map(|tr| self.make_ty(tr)) |
1311 | self.impl_block.as_ref(), | 1429 | .unwrap_or(Ty::Unknown); |
1312 | type_ref.as_ref(), | ||
1313 | ); | ||
1314 | let decl_ty = self.insert_type_vars(decl_ty); | 1430 | let decl_ty = self.insert_type_vars(decl_ty); |
1315 | let ty = if let Some(expr) = initializer { | 1431 | let ty = if let Some(expr) = initializer { |
1316 | let expr_ty = self.infer_expr(*expr, &Expectation::has_type(decl_ty)); | 1432 | let expr_ty = self.infer_expr(*expr, &Expectation::has_type(decl_ty)); |
@@ -1338,13 +1454,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1338 | let body = Arc::clone(&self.body); // avoid borrow checker problem | 1454 | let body = Arc::clone(&self.body); // avoid borrow checker problem |
1339 | for (type_ref, pat) in signature.params().iter().zip(body.params()) { | 1455 | for (type_ref, pat) in signature.params().iter().zip(body.params()) { |
1340 | let ty = self.make_ty(type_ref); | 1456 | let ty = self.make_ty(type_ref); |
1341 | let ty = self.insert_type_vars(ty); | ||
1342 | 1457 | ||
1343 | self.infer_pat(*pat, &ty); | 1458 | self.infer_pat(*pat, &ty); |
1344 | } | 1459 | } |
1345 | self.return_ty = { | 1460 | self.return_ty = { |
1346 | let ty = self.make_ty(signature.ret_type()); | 1461 | let ty = self.make_ty(signature.ret_type()); |
1347 | let ty = self.insert_type_vars(ty); | ||
1348 | ty | 1462 | ty |
1349 | }; | 1463 | }; |
1350 | } | 1464 | } |
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index b221bd142..53b6d15a8 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs | |||
@@ -8,7 +8,11 @@ use rustc_hash::FxHashMap; | |||
8 | 8 | ||
9 | use ra_db::SourceRootId; | 9 | use ra_db::SourceRootId; |
10 | 10 | ||
11 | use crate::{HirDatabase, DefId, module_tree::ModuleId, Module, Crate, Name, Function, impl_block::{ImplId, ImplBlock, ImplItem}}; | 11 | use crate::{ |
12 | HirDatabase, DefId, module_tree::ModuleId, Module, Crate, Name, Function, | ||
13 | impl_block::{ImplId, ImplBlock, ImplItem}, | ||
14 | generics::Generics | ||
15 | }; | ||
12 | use super::Ty; | 16 | use super::Ty; |
13 | 17 | ||
14 | /// This is used as a key for indexing impls. | 18 | /// This is used as a key for indexing impls. |
@@ -64,8 +68,15 @@ impl CrateImplBlocks { | |||
64 | if let Some(_target_trait) = impl_data.target_trait() { | 68 | if let Some(_target_trait) = impl_data.target_trait() { |
65 | // ignore for now | 69 | // ignore for now |
66 | } else { | 70 | } else { |
67 | let target_ty = | 71 | // TODO provide generics of impl |
68 | Ty::from_hir(db, &module, Some(&impl_block), impl_data.target_type()); | 72 | let generics = Generics::default(); |
73 | let target_ty = Ty::from_hir( | ||
74 | db, | ||
75 | &module, | ||
76 | Some(&impl_block), | ||
77 | &generics, | ||
78 | impl_data.target_type(), | ||
79 | ); | ||
69 | if let Some(target_ty_fp) = TyFingerprint::for_impl(&target_ty) { | 80 | if let Some(target_ty_fp) = TyFingerprint::for_impl(&target_ty) { |
70 | self.impls | 81 | self.impls |
71 | .entry(target_ty_fp) | 82 | .entry(target_ty_fp) |
diff --git a/crates/ra_hir/src/ty/tests/data/function_generics.txt b/crates/ra_hir/src/ty/tests/data/function_generics.txt index 179e136a0..e44d26cfd 100644 --- a/crates/ra_hir/src/ty/tests/data/function_generics.txt +++ b/crates/ra_hir/src/ty/tests/data/function_generics.txt | |||
@@ -2,13 +2,13 @@ | |||
2 | [21; 26) '{ t }': [unknown] | 2 | [21; 26) '{ t }': [unknown] |
3 | [23; 24) 't': [unknown] | 3 | [23; 24) 't': [unknown] |
4 | [38; 98) '{ ...(1); }': () | 4 | [38; 98) '{ ...(1); }': () |
5 | [44; 46) 'id': fn([unknown]) -> [unknown] | 5 | [44; 46) 'id': fn(T) -> T |
6 | [44; 52) 'id(1u32)': [unknown] | 6 | [44; 52) 'id(1u32)': T |
7 | [47; 51) '1u32': [unknown] | 7 | [47; 51) '1u32': u32 |
8 | [58; 68) 'id::<i128>': fn([unknown]) -> [unknown] | 8 | [58; 68) 'id::<i128>': fn(T) -> T |
9 | [58; 71) 'id::<i128>(1)': [unknown] | 9 | [58; 71) 'id::<i128>(1)': T |
10 | [69; 70) '1': [unknown] | 10 | [69; 70) '1': T |
11 | [81; 82) 'x': u64 | 11 | [81; 82) 'x': T |
12 | [90; 92) 'id': fn([unknown]) -> u64 | 12 | [90; 92) 'id': fn(T) -> T |
13 | [90; 95) 'id(1)': u64 | 13 | [90; 95) 'id(1)': T |
14 | [93; 94) '1': [unknown] | 14 | [93; 94) '1': T |
diff --git a/crates/ra_hir/src/ty/tests/data/generic_chain.txt b/crates/ra_hir/src/ty/tests/data/generic_chain.txt index 720609153..568e00846 100644 --- a/crates/ra_hir/src/ty/tests/data/generic_chain.txt +++ b/crates/ra_hir/src/ty/tests/data/generic_chain.txt | |||
@@ -1,29 +1,29 @@ | |||
1 | [53; 57) 'self': A | 1 | [53; 57) 'self': A<[unknown]> |
2 | [65; 87) '{ ... }': [unknown] | 2 | [65; 87) '{ ... }': [unknown] |
3 | [75; 79) 'self': A | 3 | [75; 79) 'self': A<[unknown]> |
4 | [75; 81) 'self.x': [unknown] | 4 | [75; 81) 'self.x': [unknown] |
5 | [99; 100) 't': [unknown] | 5 | [99; 100) 't': [unknown] |
6 | [110; 115) '{ t }': [unknown] | 6 | [110; 115) '{ t }': [unknown] |
7 | [112; 113) 't': [unknown] | 7 | [112; 113) 't': [unknown] |
8 | [135; 261) '{ ....x() }': i128 | 8 | [135; 261) '{ ....x() }': i128 |
9 | [146; 147) 'x': [unknown] | 9 | [146; 147) 'x': T |
10 | [150; 151) '1': [unknown] | 10 | [150; 151) '1': T |
11 | [162; 163) 'y': [unknown] | 11 | [162; 163) 'y': T |
12 | [166; 168) 'id': fn([unknown]) -> [unknown] | 12 | [166; 168) 'id': fn(T) -> T |
13 | [166; 171) 'id(x)': [unknown] | 13 | [166; 171) 'id(x)': T |
14 | [169; 170) 'x': [unknown] | 14 | [169; 170) 'x': T |
15 | [182; 183) 'a': A | 15 | [182; 183) 'a': A<T> |
16 | [186; 200) 'A { x: id(y) }': A | 16 | [186; 200) 'A { x: id(y) }': A<T> |
17 | [193; 195) 'id': fn([unknown]) -> [unknown] | 17 | [193; 195) 'id': fn(T) -> T |
18 | [193; 198) 'id(y)': [unknown] | 18 | [193; 198) 'id(y)': T |
19 | [196; 197) 'y': [unknown] | 19 | [196; 197) 'y': T |
20 | [211; 212) 'z': [unknown] | 20 | [211; 212) 'z': T |
21 | [215; 217) 'id': fn([unknown]) -> [unknown] | 21 | [215; 217) 'id': fn(T) -> T |
22 | [215; 222) 'id(a.x)': [unknown] | 22 | [215; 222) 'id(a.x)': T |
23 | [218; 219) 'a': A | 23 | [218; 219) 'a': A<T> |
24 | [218; 221) 'a.x': [unknown] | 24 | [218; 221) 'a.x': T |
25 | [233; 234) 'b': A | 25 | [233; 234) 'b': A<T> |
26 | [237; 247) 'A { x: z }': A | 26 | [237; 247) 'A { x: z }': A<T> |
27 | [244; 245) 'z': [unknown] | 27 | [244; 245) 'z': T |
28 | [254; 255) 'b': A | 28 | [254; 255) 'b': A<T> |
29 | [254; 259) 'b.x()': i128 | 29 | [254; 259) 'b.x()': i128 |
diff --git a/crates/ra_hir/src/ty/tests/data/struct_generics.txt b/crates/ra_hir/src/ty/tests/data/struct_generics.txt index d1026b459..88cd2b409 100644 --- a/crates/ra_hir/src/ty/tests/data/struct_generics.txt +++ b/crates/ra_hir/src/ty/tests/data/struct_generics.txt | |||
@@ -1,15 +1,15 @@ | |||
1 | [36; 38) 'a1': A | 1 | [36; 38) 'a1': A<[unknown]> |
2 | [48; 49) 'i': i32 | 2 | [48; 49) 'i': i32 |
3 | [56; 147) '{ ...3.x; }': () | 3 | [56; 147) '{ ...3.x; }': () |
4 | [62; 64) 'a1': A | 4 | [62; 64) 'a1': A<[unknown]> |
5 | [62; 66) 'a1.x': [unknown] | 5 | [62; 66) 'a1.x': [unknown] |
6 | [76; 78) 'a2': A | 6 | [76; 78) 'a2': A<i32> |
7 | [81; 91) 'A { x: i }': A | 7 | [81; 91) 'A { x: i }': A<i32> |
8 | [88; 89) 'i': i32 | 8 | [88; 89) 'i': i32 |
9 | [97; 99) 'a2': A | 9 | [97; 99) 'a2': A<i32> |
10 | [97; 101) 'a2.x': [unknown] | 10 | [97; 101) 'a2.x': i32 |
11 | [111; 113) 'a3': A | 11 | [111; 113) 'a3': A<i32> |
12 | [116; 134) 'A::<i1...x: 1 }': A | 12 | [116; 134) 'A::<i1...x: 1 }': A<i32> |
13 | [131; 132) '1': [unknown] | 13 | [131; 132) '1': i32 |
14 | [140; 142) 'a3': A | 14 | [140; 142) 'a3': A<i32> |
15 | [140; 144) 'a3.x': [unknown] | 15 | [140; 144) 'a3.x': i32 |
diff --git a/crates/ra_ide_api/src/completion/complete_dot.rs b/crates/ra_ide_api/src/completion/complete_dot.rs index 473edc50e..76c2f8173 100644 --- a/crates/ra_ide_api/src/completion/complete_dot.rs +++ b/crates/ra_ide_api/src/completion/complete_dot.rs | |||
@@ -24,7 +24,9 @@ pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) { | |||
24 | fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) { | 24 | fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) { |
25 | for receiver in receiver.autoderef(ctx.db) { | 25 | for receiver in receiver.autoderef(ctx.db) { |
26 | match receiver { | 26 | match receiver { |
27 | Ty::Adt { def_id, .. } => { | 27 | Ty::Adt { |
28 | def_id, ref substs, .. | ||
29 | } => { | ||
28 | match def_id.resolve(ctx.db) { | 30 | match def_id.resolve(ctx.db) { |
29 | Def::Struct(s) => { | 31 | Def::Struct(s) => { |
30 | for field in s.fields(ctx.db) { | 32 | for field in s.fields(ctx.db) { |
@@ -33,7 +35,7 @@ fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) | |||
33 | field.name().to_string(), | 35 | field.name().to_string(), |
34 | ) | 36 | ) |
35 | .kind(CompletionItemKind::Field) | 37 | .kind(CompletionItemKind::Field) |
36 | .set_detail(field.ty(ctx.db).map(|ty| ty.to_string())) | 38 | .set_detail(field.ty(ctx.db).map(|ty| ty.subst(substs).to_string())) |
37 | .add_to(acc); | 39 | .add_to(acc); |
38 | } | 40 | } |
39 | } | 41 | } |
diff --git a/crates/ra_ide_api/src/db.rs b/crates/ra_ide_api/src/db.rs index c2978f909..d53919973 100644 --- a/crates/ra_ide_api/src/db.rs +++ b/crates/ra_ide_api/src/db.rs | |||
@@ -129,6 +129,7 @@ salsa::database_storage! { | |||
129 | fn body_hir() for hir::db::BodyHirQuery; | 129 | fn body_hir() for hir::db::BodyHirQuery; |
130 | fn body_syntax_mapping() for hir::db::BodySyntaxMappingQuery; | 130 | fn body_syntax_mapping() for hir::db::BodySyntaxMappingQuery; |
131 | fn fn_signature() for hir::db::FnSignatureQuery; | 131 | fn fn_signature() for hir::db::FnSignatureQuery; |
132 | fn generics() for hir::db::GenericsQuery; | ||
132 | } | 133 | } |
133 | } | 134 | } |
134 | } | 135 | } |