aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <bors[bot]@users.noreply.github.com>2019-01-27 18:00:08 +0000
committerbors[bot] <bors[bot]@users.noreply.github.com>2019-01-27 18:00:08 +0000
commit19f77603c0aed92ec70a836dae4d447b8fcab922 (patch)
treea1739442c9f79c5c6addc0efc7d25a7da678ce02
parent3f4f50baaa21cb2d0f6c102f1ca521946071a8dc (diff)
parent6249989e6c133792ff457896d4723c0eb0f42137 (diff)
Merge #661
661: Implement type generics for functions r=flodiebold a=marcusklaas Pretty printing of function types isn't as nice any more since the current implementation does not store its argument types directly. We could store some more information to print more information on the argument and return types, at a cost of course. Co-authored-by: Marcus Klaas de Vries <[email protected]>
-rw-r--r--crates/ra_hir/src/code_model_api.rs4
-rw-r--r--crates/ra_hir/src/ty.rs162
-rw-r--r--crates/ra_hir/src/ty/snapshots/tests__infer_backwards.snap8
-rw-r--r--crates/ra_hir/src/ty/snapshots/tests__infer_binary_op.snap8
-rw-r--r--crates/ra_hir/src/ty/snapshots/tests__infer_function_generics.snap24
-rw-r--r--crates/ra_hir/src/ty/snapshots/tests__infer_generic_chain.snap46
-rw-r--r--crates/ra_hir/src/ty/snapshots/tests__infer_paths.snap10
-rw-r--r--crates/ra_hir/src/ty/snapshots/tests__infer_type_param.snap26
-rw-r--r--crates/ra_hir/src/ty/tests.rs23
9 files changed, 227 insertions, 84 deletions
diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs
index 191104890..e4008058c 100644
--- a/crates/ra_hir/src/code_model_api.rs
+++ b/crates/ra_hir/src/code_model_api.rs
@@ -424,6 +424,10 @@ impl Function {
424 self.id.module(db) 424 self.id.module(db)
425 } 425 }
426 426
427 pub fn name(&self, db: &impl HirDatabase) -> Name {
428 self.signature(db).name.clone()
429 }
430
427 pub fn body_syntax_mapping(&self, db: &impl HirDatabase) -> Arc<BodySyntaxMapping> { 431 pub fn body_syntax_mapping(&self, db: &impl HirDatabase) -> Arc<BodySyntaxMapping> {
428 db.body_syntax_mapping(*self) 432 db.body_syntax_mapping(*self)
429 } 433 }
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 31ea45706..37715a903 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -20,6 +20,7 @@ mod tests;
20pub(crate) mod method_resolution; 20pub(crate) mod method_resolution;
21 21
22use std::borrow::Cow; 22use std::borrow::Cow;
23use std::iter::repeat;
23use std::ops::Index; 24use std::ops::Index;
24use std::sync::Arc; 25use std::sync::Arc;
25use std::{fmt, mem}; 26use std::{fmt, mem};
@@ -185,7 +186,7 @@ pub enum Ty {
185 186
186 /// Structures, enumerations and unions. 187 /// Structures, enumerations and unions.
187 Adt { 188 Adt {
188 /// The DefId of the struct/enum. 189 /// The definition of the struct/enum.
189 def_id: AdtDef, 190 def_id: AdtDef,
190 /// The name, for displaying. 191 /// The name, for displaying.
191 name: Name, 192 name: Name,
@@ -209,6 +210,27 @@ pub enum Ty {
209 /// `&'a mut T` or `&'a T`. 210 /// `&'a mut T` or `&'a T`.
210 Ref(Arc<Ty>, Mutability), 211 Ref(Arc<Ty>, Mutability),
211 212
213 /// The anonymous type of a function declaration/definition. Each
214 /// function has a unique type, which is output (for a function
215 /// named `foo` returning an `i32`) as `fn() -> i32 {foo}`.
216 ///
217 /// For example the type of `bar` here:
218 ///
219 /// ```rust
220 /// fn foo() -> i32 { 1 }
221 /// let bar = foo; // bar: fn() -> i32 {foo}
222 /// ```
223 FnDef {
224 // Function definition
225 def: Function,
226 /// For display
227 name: Name,
228 /// Parameters and return type
229 sig: Arc<FnSig>,
230 /// Substitutions for the generic parameters of the type
231 substs: Substs,
232 },
233
212 /// A pointer to a function. Written as `fn() -> i32`. 234 /// A pointer to a function. Written as `fn() -> i32`.
213 /// 235 ///
214 /// For example the type of `bar` here: 236 /// For example the type of `bar` here:
@@ -448,12 +470,12 @@ impl Ty {
448 } 470 }
449 // add placeholders for args that were not provided 471 // add placeholders for args that were not provided
450 // TODO: handle defaults 472 // TODO: handle defaults
451 for _ in segment 473 let supplied_params = segment
452 .args_and_bindings 474 .args_and_bindings
453 .as_ref() 475 .as_ref()
454 .map(|ga| ga.args.len()) 476 .map(|ga| ga.args.len())
455 .unwrap_or(0)..def_generics.params.len() 477 .unwrap_or(0);
456 { 478 for _ in supplied_params..def_generics.params.len() {
457 substs.push(Ty::Unknown); 479 substs.push(Ty::Unknown);
458 } 480 }
459 assert_eq!(substs.len(), def_generics.params.len()); 481 assert_eq!(substs.len(), def_generics.params.len());
@@ -485,6 +507,19 @@ impl Ty {
485 } 507 }
486 sig_mut.output.walk_mut(f); 508 sig_mut.output.walk_mut(f);
487 } 509 }
510 Ty::FnDef { substs, sig, .. } => {
511 let sig_mut = Arc::make_mut(sig);
512 for input in &mut sig_mut.input {
513 input.walk_mut(f);
514 }
515 sig_mut.output.walk_mut(f);
516 // Without an Arc::make_mut_slice, we can't avoid the clone here:
517 let mut v: Vec<_> = substs.0.iter().cloned().collect();
518 for t in &mut v {
519 t.walk_mut(f);
520 }
521 substs.0 = v.into();
522 }
488 Ty::Adt { substs, .. } => { 523 Ty::Adt { substs, .. } => {
489 // Without an Arc::make_mut_slice, we can't avoid the clone here: 524 // Without an Arc::make_mut_slice, we can't avoid the clone here:
490 let mut v: Vec<_> = substs.0.iter().cloned().collect(); 525 let mut v: Vec<_> = substs.0.iter().cloned().collect();
@@ -524,6 +559,12 @@ impl Ty {
524 name, 559 name,
525 substs, 560 substs,
526 }, 561 },
562 Ty::FnDef { def, name, sig, .. } => Ty::FnDef {
563 def,
564 name,
565 sig,
566 substs,
567 },
527 _ => self, 568 _ => self,
528 } 569 }
529 } 570 }
@@ -551,7 +592,7 @@ impl Ty {
551 /// or function); so if `self` is `Option<u32>`, this returns the `u32`. 592 /// or function); so if `self` is `Option<u32>`, this returns the `u32`.
552 fn substs(&self) -> Option<Substs> { 593 fn substs(&self) -> Option<Substs> {
553 match self { 594 match self {
554 Ty::Adt { substs, .. } => Some(substs.clone()), 595 Ty::Adt { substs, .. } | Ty::FnDef { substs, .. } => Some(substs.clone()),
555 _ => None, 596 _ => None,
556 } 597 }
557 } 598 }
@@ -586,6 +627,22 @@ impl fmt::Display for Ty {
586 .to_fmt(f)?; 627 .to_fmt(f)?;
587 write!(f, " -> {}", sig.output) 628 write!(f, " -> {}", sig.output)
588 } 629 }
630 Ty::FnDef {
631 name, substs, sig, ..
632 } => {
633 write!(f, "fn {}", name)?;
634 if substs.0.len() > 0 {
635 join(substs.0.iter())
636 .surround_with("<", ">")
637 .separator(", ")
638 .to_fmt(f)?;
639 }
640 join(sig.input.iter())
641 .surround_with("(", ")")
642 .separator(", ")
643 .to_fmt(f)?;
644 write!(f, " -> {}", sig.output)
645 }
589 Ty::Adt { name, substs, .. } => { 646 Ty::Adt { name, substs, .. } => {
590 write!(f, "{}", name)?; 647 write!(f, "{}", name)?;
591 if substs.0.len() > 0 { 648 if substs.0.len() > 0 {
@@ -607,11 +664,11 @@ impl fmt::Display for Ty {
607 664
608/// Compute the declared type of a function. This should not need to look at the 665/// Compute the declared type of a function. This should not need to look at the
609/// function body. 666/// function body.
610fn type_for_fn(db: &impl HirDatabase, f: Function) -> Ty { 667fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty {
611 let signature = f.signature(db); 668 let signature = def.signature(db);
612 let module = f.module(db); 669 let module = def.module(db);
613 let impl_block = f.impl_block(db); 670 let impl_block = def.impl_block(db);
614 let generics = f.generic_params(db); 671 let generics = def.generic_params(db);
615 let input = signature 672 let input = signature
616 .params() 673 .params()
617 .iter() 674 .iter()
@@ -624,8 +681,15 @@ fn type_for_fn(db: &impl HirDatabase, f: Function) -> Ty {
624 &generics, 681 &generics,
625 signature.ret_type(), 682 signature.ret_type(),
626 ); 683 );
627 let sig = FnSig { input, output }; 684 let sig = Arc::new(FnSig { input, output });
628 Ty::FnPtr(Arc::new(sig)) 685 let substs = make_substs(&generics);
686 let name = def.name(db);
687 Ty::FnDef {
688 def,
689 sig,
690 name,
691 substs,
692 }
629} 693}
630 694
631fn make_substs(generics: &GenericParams) -> Substs { 695fn make_substs(generics: &GenericParams) -> Substs {
@@ -1102,7 +1166,18 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1102 .into(); 1166 .into();
1103 let typable = typable?; 1167 let typable = typable?;
1104 let ty = self.db.type_for_def(typable); 1168 let ty = self.db.type_for_def(typable);
1169 let generics = GenericParams::default();
1170 let substs = Ty::substs_from_path(
1171 self.db,
1172 &self.module,
1173 self.impl_block.as_ref(),
1174 &generics,
1175 path,
1176 typable,
1177 );
1178 let ty = ty.apply_substs(substs);
1105 let ty = self.insert_type_vars(ty); 1179 let ty = self.insert_type_vars(ty);
1180
1106 Some(ty) 1181 Some(ty)
1107 } 1182 }
1108 1183
@@ -1142,7 +1217,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1142 let ty = self.insert_type_vars(ty.apply_substs(substs)); 1217 let ty = self.insert_type_vars(ty.apply_substs(substs));
1143 (ty, Some(var.into())) 1218 (ty, Some(var.into()))
1144 } 1219 }
1145 TypableDef::Enum(_) | TypableDef::Function(_) => (Ty::Unknown, None), 1220 TypableDef::Function(_) | TypableDef::Enum(_) => (Ty::Unknown, None),
1146 } 1221 }
1147 } 1222 }
1148 1223
@@ -1196,9 +1271,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1196 Ty::Tuple(ref tuple_args) => &**tuple_args, 1271 Ty::Tuple(ref tuple_args) => &**tuple_args,
1197 _ => &[], 1272 _ => &[],
1198 }; 1273 };
1199 let expectations_iter = expectations 1274 let expectations_iter = expectations.into_iter().chain(repeat(&Ty::Unknown));
1200 .into_iter()
1201 .chain(std::iter::repeat(&Ty::Unknown));
1202 1275
1203 let inner_tys = args 1276 let inner_tys = args
1204 .iter() 1277 .iter()
@@ -1332,18 +1405,25 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1332 Expr::Call { callee, args } => { 1405 Expr::Call { callee, args } => {
1333 let callee_ty = self.infer_expr(*callee, &Expectation::none()); 1406 let callee_ty = self.infer_expr(*callee, &Expectation::none());
1334 let (param_tys, ret_ty) = match &callee_ty { 1407 let (param_tys, ret_ty) = match &callee_ty {
1335 Ty::FnPtr(sig) => (&sig.input[..], sig.output.clone()), 1408 Ty::FnPtr(sig) => (sig.input.clone(), sig.output.clone()),
1409 Ty::FnDef { substs, sig, .. } => {
1410 let ret_ty = sig.output.clone().subst(&substs);
1411 let param_tys = sig
1412 .input
1413 .iter()
1414 .map(|ty| ty.clone().subst(&substs))
1415 .collect();
1416 (param_tys, ret_ty)
1417 }
1336 _ => { 1418 _ => {
1337 // not callable 1419 // not callable
1338 // TODO report an error? 1420 // TODO report an error?
1339 (&[][..], Ty::Unknown) 1421 (Vec::new(), Ty::Unknown)
1340 } 1422 }
1341 }; 1423 };
1342 for (i, arg) in args.iter().enumerate() { 1424 let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown));
1343 self.infer_expr( 1425 for (arg, param) in args.iter().zip(param_iter) {
1344 *arg, 1426 self.infer_expr(*arg, &Expectation::has_type(param));
1345 &Expectation::has_type(param_tys.get(i).cloned().unwrap_or(Ty::Unknown)),
1346 );
1347 } 1427 }
1348 ret_ty 1428 ret_ty
1349 } 1429 }
@@ -1365,21 +1445,34 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1365 let (expected_receiver_ty, param_tys, ret_ty) = match &method_ty { 1445 let (expected_receiver_ty, param_tys, ret_ty) = match &method_ty {
1366 Ty::FnPtr(sig) => { 1446 Ty::FnPtr(sig) => {
1367 if sig.input.len() > 0 { 1447 if sig.input.len() > 0 {
1368 (&sig.input[0], &sig.input[1..], sig.output.clone()) 1448 (
1449 sig.input[0].clone(),
1450 sig.input[1..].iter().cloned().collect(),
1451 sig.output.clone(),
1452 )
1369 } else { 1453 } else {
1370 (&Ty::Unknown, &[][..], sig.output.clone()) 1454 (Ty::Unknown, Vec::new(), sig.output.clone())
1371 } 1455 }
1372 } 1456 }
1373 _ => (&Ty::Unknown, &[][..], Ty::Unknown), 1457 Ty::FnDef { substs, sig, .. } => {
1458 let ret_ty = sig.output.clone().subst(&substs);
1459
1460 if sig.input.len() > 0 {
1461 let mut arg_iter = sig.input.iter().map(|ty| ty.clone().subst(&substs));
1462 let receiver_ty = arg_iter.next().unwrap();
1463 (receiver_ty, arg_iter.collect(), ret_ty)
1464 } else {
1465 (Ty::Unknown, Vec::new(), ret_ty)
1466 }
1467 }
1468 _ => (Ty::Unknown, Vec::new(), Ty::Unknown),
1374 }; 1469 };
1375 // TODO we would have to apply the autoderef/autoref steps here 1470 // TODO we would have to apply the autoderef/autoref steps here
1376 // to get the correct receiver type to unify... 1471 // to get the correct receiver type to unify...
1377 self.unify(expected_receiver_ty, &receiver_ty); 1472 self.unify(&expected_receiver_ty, &receiver_ty);
1378 for (i, arg) in args.iter().enumerate() { 1473 let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown));
1379 self.infer_expr( 1474 for (arg, param) in args.iter().zip(param_iter) {
1380 *arg, 1475 self.infer_expr(*arg, &Expectation::has_type(param));
1381 &Expectation::has_type(param_tys.get(i).cloned().unwrap_or(Ty::Unknown)),
1382 );
1383 } 1476 }
1384 ret_ty 1477 ret_ty
1385 } 1478 }
@@ -1609,10 +1702,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1609 1702
1610 self.infer_pat(*pat, &ty); 1703 self.infer_pat(*pat, &ty);
1611 } 1704 }
1612 self.return_ty = { 1705 self.return_ty = self.make_ty(signature.ret_type());
1613 let ty = self.make_ty(signature.ret_type());
1614 ty
1615 };
1616 } 1706 }
1617 1707
1618 fn infer_body(&mut self) { 1708 fn infer_body(&mut self) {
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_backwards.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_backwards.snap
index 5c74bd8c7..f5840a934 100644
--- a/crates/ra_hir/src/ty/snapshots/tests__infer_backwards.snap
+++ b/crates/ra_hir/src/ty/snapshots/tests__infer_backwards.snap
@@ -1,8 +1,8 @@
1--- 1---
2created: "2019-01-22T14:44:59.880187500+00:00" 2created: "2019-01-26T17:46:03.842478456+00:00"
3creator: insta@0.4.0 3creator: insta@0.5.2
4expression: "&result" 4expression: "&result"
5source: "crates\\ra_hir\\src\\ty\\tests.rs" 5source: crates/ra_hir/src/ty/tests.rs
6--- 6---
7[14; 15) 'x': u32 7[14; 15) 'x': u32
8[22; 24) '{}': () 8[22; 24) '{}': ()
@@ -10,7 +10,7 @@ source: "crates\\ra_hir\\src\\ty\\tests.rs"
10[88; 89) 'a': u32 10[88; 89) 'a': u32
11[92; 108) 'unknow...nction': [unknown] 11[92; 108) 'unknow...nction': [unknown]
12[92; 110) 'unknow...tion()': u32 12[92; 110) 'unknow...tion()': u32
13[116; 125) 'takes_u32': fn(u32) -> () 13[116; 125) 'takes_u32': fn takes_u32(u32) -> ()
14[116; 128) 'takes_u32(a)': () 14[116; 128) 'takes_u32(a)': ()
15[126; 127) 'a': u32 15[126; 127) 'a': u32
16[138; 139) 'b': i32 16[138; 139) 'b': i32
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_binary_op.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_binary_op.snap
index c506bcadd..b9dda2bc0 100644
--- a/crates/ra_hir/src/ty/snapshots/tests__infer_binary_op.snap
+++ b/crates/ra_hir/src/ty/snapshots/tests__infer_binary_op.snap
@@ -1,8 +1,8 @@
1--- 1---
2created: "2019-01-22T14:44:59.880187500+00:00" 2created: "2019-01-26T17:46:03.853259898+00:00"
3creator: insta@0.4.0 3creator: insta@0.5.2
4expression: "&result" 4expression: "&result"
5source: "crates\\ra_hir\\src\\ty\\tests.rs" 5source: crates/ra_hir/src/ty/tests.rs
6--- 6---
7[6; 7) 'x': bool 7[6; 7) 'x': bool
8[22; 34) '{ 0i32 }': i32 8[22; 34) '{ 0i32 }': i32
@@ -28,7 +28,7 @@ source: "crates\\ra_hir\\src\\ty\\tests.rs"
28[174; 196) 'minus_...ONST_2': bool 28[174; 196) 'minus_...ONST_2': bool
29[189; 196) 'CONST_2': isize 29[189; 196) 'CONST_2': isize
30[206; 207) 'c': i32 30[206; 207) 'c': i32
31[210; 211) 'f': fn(bool) -> i32 31[210; 211) 'f': fn f(bool) -> i32
32[210; 219) 'f(z || y)': i32 32[210; 219) 'f(z || y)': i32
33[210; 223) 'f(z || y) + 5': i32 33[210; 223) 'f(z || y) + 5': i32
34[212; 213) 'z': bool 34[212; 213) 'z': bool
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_function_generics.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_function_generics.snap
index 7203ad1e2..8ff6e55a6 100644
--- a/crates/ra_hir/src/ty/snapshots/tests__infer_function_generics.snap
+++ b/crates/ra_hir/src/ty/snapshots/tests__infer_function_generics.snap
@@ -1,21 +1,21 @@
1--- 1---
2created: "2019-01-22T14:44:59.954958500+00:00" 2created: "2019-01-26T18:16:16.530712344+00:00"
3creator: insta@0.4.0 3creator: insta@0.5.2
4expression: "&result" 4expression: "&result"
5source: "crates\\ra_hir\\src\\ty\\tests.rs" 5source: crates/ra_hir/src/ty/tests.rs
6--- 6---
7[10; 11) 't': [unknown] 7[10; 11) 't': [unknown]
8[21; 26) '{ t }': [unknown] 8[21; 26) '{ t }': [unknown]
9[23; 24) 't': [unknown] 9[23; 24) 't': [unknown]
10[38; 98) '{ ...(1); }': () 10[38; 98) '{ ...(1); }': ()
11[44; 46) 'id': fn(T) -> T 11[44; 46) 'id': fn id<u32>(T) -> T
12[44; 52) 'id(1u32)': T 12[44; 52) 'id(1u32)': u32
13[47; 51) '1u32': u32 13[47; 51) '1u32': u32
14[58; 68) 'id::<i128>': fn(T) -> T 14[58; 68) 'id::<i128>': fn id<i128>(T) -> T
15[58; 71) 'id::<i128>(1)': T 15[58; 71) 'id::<i128>(1)': i128
16[69; 70) '1': T 16[69; 70) '1': i128
17[81; 82) 'x': T 17[81; 82) 'x': u64
18[90; 92) 'id': fn(T) -> T 18[90; 92) 'id': fn id<u64>(T) -> T
19[90; 95) 'id(1)': T 19[90; 95) 'id(1)': u64
20[93; 94) '1': T 20[93; 94) '1': u64
21 21
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_generic_chain.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_generic_chain.snap
index 4435180a1..f21bffa75 100644
--- a/crates/ra_hir/src/ty/snapshots/tests__infer_generic_chain.snap
+++ b/crates/ra_hir/src/ty/snapshots/tests__infer_generic_chain.snap
@@ -1,8 +1,8 @@
1--- 1---
2created: "2019-01-22T14:44:59.961936900+00:00" 2created: "2019-01-26T17:46:03.866825843+00:00"
3creator: insta@0.4.0 3creator: insta@0.5.2
4expression: "&result" 4expression: "&result"
5source: "crates\\ra_hir\\src\\ty\\tests.rs" 5source: crates/ra_hir/src/ty/tests.rs
6--- 6---
7[53; 57) 'self': A<[unknown]> 7[53; 57) 'self': A<[unknown]>
8[65; 87) '{ ... }': [unknown] 8[65; 87) '{ ... }': [unknown]
@@ -12,25 +12,25 @@ source: "crates\\ra_hir\\src\\ty\\tests.rs"
12[110; 115) '{ t }': [unknown] 12[110; 115) '{ t }': [unknown]
13[112; 113) 't': [unknown] 13[112; 113) 't': [unknown]
14[135; 261) '{ ....x() }': i128 14[135; 261) '{ ....x() }': i128
15[146; 147) 'x': T 15[146; 147) 'x': i32
16[150; 151) '1': T 16[150; 151) '1': i32
17[162; 163) 'y': T 17[162; 163) 'y': i32
18[166; 168) 'id': fn(T) -> T 18[166; 168) 'id': fn id<i32>(T) -> T
19[166; 171) 'id(x)': T 19[166; 171) 'id(x)': i32
20[169; 170) 'x': T 20[169; 170) 'x': i32
21[182; 183) 'a': A<T> 21[182; 183) 'a': A<i32>
22[186; 200) 'A { x: id(y) }': A<T> 22[186; 200) 'A { x: id(y) }': A<i32>
23[193; 195) 'id': fn(T) -> T 23[193; 195) 'id': fn id<i32>(T) -> T
24[193; 198) 'id(y)': T 24[193; 198) 'id(y)': i32
25[196; 197) 'y': T 25[196; 197) 'y': i32
26[211; 212) 'z': T 26[211; 212) 'z': i32
27[215; 217) 'id': fn(T) -> T 27[215; 217) 'id': fn id<i32>(T) -> T
28[215; 222) 'id(a.x)': T 28[215; 222) 'id(a.x)': i32
29[218; 219) 'a': A<T> 29[218; 219) 'a': A<i32>
30[218; 221) 'a.x': T 30[218; 221) 'a.x': i32
31[233; 234) 'b': A<T> 31[233; 234) 'b': A<i32>
32[237; 247) 'A { x: z }': A<T> 32[237; 247) 'A { x: z }': A<i32>
33[244; 245) 'z': T 33[244; 245) 'z': i32
34[254; 255) 'b': A<T> 34[254; 255) 'b': A<i32>
35[254; 259) 'b.x()': i128 35[254; 259) 'b.x()': i128
36 36
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_paths.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_paths.snap
index 0bceffaef..afbe2f747 100644
--- a/crates/ra_hir/src/ty/snapshots/tests__infer_paths.snap
+++ b/crates/ra_hir/src/ty/snapshots/tests__infer_paths.snap
@@ -1,16 +1,16 @@
1--- 1---
2created: "2019-01-22T14:44:59.975899500+00:00" 2created: "2019-01-26T17:46:03.928773630+00:00"
3creator: insta@0.4.0 3creator: insta@0.5.2
4expression: "&result" 4expression: "&result"
5source: "crates\\ra_hir\\src\\ty\\tests.rs" 5source: crates/ra_hir/src/ty/tests.rs
6--- 6---
7[15; 20) '{ 1 }': u32 7[15; 20) '{ 1 }': u32
8[17; 18) '1': u32 8[17; 18) '1': u32
9[48; 53) '{ 1 }': u32 9[48; 53) '{ 1 }': u32
10[50; 51) '1': u32 10[50; 51) '1': u32
11[67; 91) '{ ...c(); }': () 11[67; 91) '{ ...c(); }': ()
12[73; 74) 'a': fn() -> u32 12[73; 74) 'a': fn a() -> u32
13[73; 76) 'a()': u32 13[73; 76) 'a()': u32
14[82; 86) 'b::c': fn() -> u32 14[82; 86) 'b::c': fn c() -> u32
15[82; 88) 'b::c()': u32 15[82; 88) 'b::c()': u32
16 16
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_type_param.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_type_param.snap
new file mode 100644
index 000000000..a99323264
--- /dev/null
+++ b/crates/ra_hir/src/ty/snapshots/tests__infer_type_param.snap
@@ -0,0 +1,26 @@
1---
2created: "2019-01-27T16:54:18.368427685+00:00"
3creator: [email protected]
4expression: "&result"
5source: crates/ra_hir/src/ty/tests.rs
6---
7[10; 11) 'x': [unknown]
8[21; 30) '{ x }': [unknown]
9[27; 28) 'x': [unknown]
10[44; 45) 'x': &[unknown]
11[56; 65) '{ x }': &[unknown]
12[62; 63) 'x': &[unknown]
13[77; 157) '{ ...(1); }': ()
14[87; 88) 'y': u32
15[91; 96) '10u32': u32
16[102; 104) 'id': fn id<u32>(T) -> T
17[102; 107) 'id(y)': u32
18[105; 106) 'y': u32
19[117; 118) 'x': bool
20[127; 132) 'clone': fn clone<bool>(&T) -> T
21[127; 135) 'clone(z)': bool
22[133; 134) 'z': &bool
23[141; 151) 'id::<i128>': fn id<i128>(T) -> T
24[141; 154) 'id::<i128>(1)': i128
25[152; 153) '1': i128
26
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index f74d6f5ea..ac12d974b 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -594,6 +594,29 @@ fn test() {
594 ); 594 );
595} 595}
596 596
597#[test]
598fn infer_type_param() {
599 check_inference(
600 "infer_type_param",
601 r#"
602fn id<T>(x: T) -> T {
603 x
604}
605
606fn clone<T>(x: &T) -> T {
607 x
608}
609
610fn test() {
611 let y = 10u32;
612 id(y);
613 let x: bool = clone(z);
614 id::<i128>(1);
615}
616"#,
617 );
618}
619
597fn infer(content: &str) -> String { 620fn infer(content: &str) -> String {
598 let (db, _, file_id) = MockDatabase::with_single_file(content); 621 let (db, _, file_id) = MockDatabase::with_single_file(content);
599 let source_file = db.parse(file_id); 622 let source_file = db.parse(file_id);