diff options
author | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-01-27 18:00:08 +0000 |
---|---|---|
committer | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-01-27 18:00:08 +0000 |
commit | 19f77603c0aed92ec70a836dae4d447b8fcab922 (patch) | |
tree | a1739442c9f79c5c6addc0efc7d25a7da678ce02 | |
parent | 3f4f50baaa21cb2d0f6c102f1ca521946071a8dc (diff) | |
parent | 6249989e6c133792ff457896d4723c0eb0f42137 (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.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir/src/ty.rs | 162 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/snapshots/tests__infer_backwards.snap | 8 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/snapshots/tests__infer_binary_op.snap | 8 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/snapshots/tests__infer_function_generics.snap | 24 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/snapshots/tests__infer_generic_chain.snap | 46 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/snapshots/tests__infer_paths.snap | 10 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/snapshots/tests__infer_type_param.snap | 26 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 23 |
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; | |||
20 | pub(crate) mod method_resolution; | 20 | pub(crate) mod method_resolution; |
21 | 21 | ||
22 | use std::borrow::Cow; | 22 | use std::borrow::Cow; |
23 | use std::iter::repeat; | ||
23 | use std::ops::Index; | 24 | use std::ops::Index; |
24 | use std::sync::Arc; | 25 | use std::sync::Arc; |
25 | use std::{fmt, mem}; | 26 | use 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. |
610 | fn type_for_fn(db: &impl HirDatabase, f: Function) -> Ty { | 667 | fn 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 | ||
631 | fn make_substs(generics: &GenericParams) -> Substs { | 695 | fn 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 | --- |
2 | created: "2019-01-22T14:44:59.880187500+00:00" | 2 | created: "2019-01-26T17:46:03.842478456+00:00" |
3 | creator: insta@0.4.0 | 3 | creator: insta@0.5.2 |
4 | expression: "&result" | 4 | expression: "&result" |
5 | source: "crates\\ra_hir\\src\\ty\\tests.rs" | 5 | source: 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 | --- |
2 | created: "2019-01-22T14:44:59.880187500+00:00" | 2 | created: "2019-01-26T17:46:03.853259898+00:00" |
3 | creator: insta@0.4.0 | 3 | creator: insta@0.5.2 |
4 | expression: "&result" | 4 | expression: "&result" |
5 | source: "crates\\ra_hir\\src\\ty\\tests.rs" | 5 | source: 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 | --- |
2 | created: "2019-01-22T14:44:59.954958500+00:00" | 2 | created: "2019-01-26T18:16:16.530712344+00:00" |
3 | creator: insta@0.4.0 | 3 | creator: insta@0.5.2 |
4 | expression: "&result" | 4 | expression: "&result" |
5 | source: "crates\\ra_hir\\src\\ty\\tests.rs" | 5 | source: 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 | --- |
2 | created: "2019-01-22T14:44:59.961936900+00:00" | 2 | created: "2019-01-26T17:46:03.866825843+00:00" |
3 | creator: insta@0.4.0 | 3 | creator: insta@0.5.2 |
4 | expression: "&result" | 4 | expression: "&result" |
5 | source: "crates\\ra_hir\\src\\ty\\tests.rs" | 5 | source: 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 | --- |
2 | created: "2019-01-22T14:44:59.975899500+00:00" | 2 | created: "2019-01-26T17:46:03.928773630+00:00" |
3 | creator: insta@0.4.0 | 3 | creator: insta@0.5.2 |
4 | expression: "&result" | 4 | expression: "&result" |
5 | source: "crates\\ra_hir\\src\\ty\\tests.rs" | 5 | source: 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 | --- | ||
2 | created: "2019-01-27T16:54:18.368427685+00:00" | ||
3 | creator: [email protected] | ||
4 | expression: "&result" | ||
5 | source: 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] | ||
598 | fn infer_type_param() { | ||
599 | check_inference( | ||
600 | "infer_type_param", | ||
601 | r#" | ||
602 | fn id<T>(x: T) -> T { | ||
603 | x | ||
604 | } | ||
605 | |||
606 | fn clone<T>(x: &T) -> T { | ||
607 | x | ||
608 | } | ||
609 | |||
610 | fn test() { | ||
611 | let y = 10u32; | ||
612 | id(y); | ||
613 | let x: bool = clone(z); | ||
614 | id::<i128>(1); | ||
615 | } | ||
616 | "#, | ||
617 | ); | ||
618 | } | ||
619 | |||
597 | fn infer(content: &str) -> String { | 620 | fn 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); |