aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2019-01-12 20:27:35 +0000
committerFlorian Diebold <[email protected]>2019-01-19 15:02:06 +0000
commit688a45e00b53412a7a16360c6d678a5d91a95789 (patch)
treed3f3481bbad9889d22867729e9efcde184e45671
parent415cdc52108807126f0339fbf812856582f01c18 (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.rs5
-rw-r--r--crates/ra_hir/src/code_model_api.rs21
-rw-r--r--crates/ra_hir/src/db.rs4
-rw-r--r--crates/ra_hir/src/generics.rs48
-rw-r--r--crates/ra_hir/src/lib.rs1
-rw-r--r--crates/ra_hir/src/mock.rs1
-rw-r--r--crates/ra_hir/src/ty.rs180
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs17
-rw-r--r--crates/ra_hir/src/ty/tests/data/function_generics.txt20
-rw-r--r--crates/ra_hir/src/ty/tests/data/generic_chain.txt44
-rw-r--r--crates/ra_hir/src/ty/tests/data/struct_generics.txt22
-rw-r--r--crates/ra_ide_api/src/completion/complete_dot.rs6
-rw-r--r--crates/ra_ide_api/src/db.rs1
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
1use std::sync::Arc; 4use std::sync::Arc;
2 5
3use ra_syntax::{ 6use 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
6use std::sync::Arc;
7
8use ra_syntax::ast::{TypeParamList, AstNode, NameOwner};
9
10use crate::{db::HirDatabase, DefId, Name, AsName};
11
12/// Data about a generic parameter (to a function, struct, impl, ...).
13#[derive(Clone, PartialEq, Eq, Debug)]
14pub 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)]
21pub struct Generics {
22 pub(crate) params: Vec<GenericParam>,
23}
24
25impl 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;
24mod ty; 24mod ty;
25mod impl_block; 25mod impl_block;
26mod expr; 26mod expr;
27mod generics;
27 28
28mod code_model_api; 29mod code_model_api;
29mod code_model_impl; 30mod 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)]
157pub 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)]
158pub enum Ty { 163pub 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)]
254pub struct FnSig { 265pub 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
399impl fmt::Display for Ty { 461impl 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
532fn 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
454fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty { 543fn 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
461pub(crate) fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty { 552pub(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
9use ra_db::SourceRootId; 9use ra_db::SourceRootId;
10 10
11use crate::{HirDatabase, DefId, module_tree::ModuleId, Module, Crate, Name, Function, impl_block::{ImplId, ImplBlock, ImplItem}}; 11use crate::{
12 HirDatabase, DefId, module_tree::ModuleId, Module, Crate, Name, Function,
13 impl_block::{ImplId, ImplBlock, ImplItem},
14 generics::Generics
15};
12use super::Ty; 16use 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) {
24fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) { 24fn 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}