aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir')
-rw-r--r--crates/ra_hir/src/generics.rs13
-rw-r--r--crates/ra_hir/src/ty.rs86
-rw-r--r--crates/ra_hir/src/ty/snapshots/tests__infer_struct.snap6
-rw-r--r--crates/ra_hir/src/ty/snapshots/tests__infer_tuple_struct_generics.snap23
-rw-r--r--crates/ra_hir/src/ty/tests.rs21
5 files changed, 107 insertions, 42 deletions
diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs
index fcc513353..c494beeb0 100644
--- a/crates/ra_hir/src/generics.rs
+++ b/crates/ra_hir/src/generics.rs
@@ -87,4 +87,17 @@ impl GenericParams {
87 let parent_count = self.count_parent_params(); 87 let parent_count = self.count_parent_params();
88 parent_count + self.params.len() 88 parent_count + self.params.len()
89 } 89 }
90
91 fn for_each_param<'a>(&'a self, f: &mut impl FnMut(&'a GenericParam)) {
92 if let Some(parent) = &self.parent_params {
93 parent.for_each_param(f);
94 }
95 self.params.iter().for_each(f);
96 }
97
98 pub fn params_including_parent(&self) -> Vec<&GenericParam> {
99 let mut vec = Vec::with_capacity(self.count_params_including_parent());
100 self.for_each_param(&mut |p| vec.push(p));
101 vec
102 }
90} 103}
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 89e854dd7..ae595c16d 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -40,7 +40,7 @@ use crate::{
40 name::{KnownName}, 40 name::{KnownName},
41 expr::{Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat, self}, 41 expr::{Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat, self},
42 generics::GenericParams, 42 generics::GenericParams,
43 path::GenericArg, 43 path::{ GenericArgs, GenericArg},
44 adt::VariantDef, 44 adt::VariantDef,
45 resolve::{Resolver, Resolution}, nameres::Namespace 45 resolve::{Resolver, Resolution}, nameres::Namespace
46}; 46};
@@ -165,17 +165,6 @@ impl Substs {
165 pub fn empty() -> Substs { 165 pub fn empty() -> Substs {
166 Substs(Arc::new([])) 166 Substs(Arc::new([]))
167 } 167 }
168
169 /// Replaces the end of the substitutions by other ones.
170 pub(crate) fn replace_tail(self, replace_by: Vec<Ty>) -> Substs {
171 // again missing Arc::make_mut_slice...
172 let len = replace_by.len().min(self.0.len());
173 let parent_len = self.0.len() - len;
174 let mut result = Vec::with_capacity(parent_len + len);
175 result.extend(self.0.iter().take(parent_len).cloned());
176 result.extend(replace_by);
177 Substs(result.into())
178 }
179} 168}
180 169
181/// A type. This is based on the `TyKind` enum in rustc (librustc/ty/sty.rs). 170/// A type. This is based on the `TyKind` enum in rustc (librustc/ty/sty.rs).
@@ -454,7 +443,7 @@ impl Ty {
454 for _ in supplied_params..def_generics.count_params_including_parent() { 443 for _ in supplied_params..def_generics.count_params_including_parent() {
455 substs.push(Ty::Unknown); 444 substs.push(Ty::Unknown);
456 } 445 }
457 assert_eq!(substs.len(), def_generics.params.len()); 446 assert_eq!(substs.len(), def_generics.count_params_including_parent());
458 Substs(substs.into()) 447 Substs(substs.into())
459 } 448 }
460 449
@@ -639,8 +628,11 @@ impl fmt::Display for Ty {
639 join(sig.input.iter()).surround_with("fn(", ")").separator(", ").to_fmt(f)?; 628 join(sig.input.iter()).surround_with("fn(", ")").separator(", ").to_fmt(f)?;
640 write!(f, " -> {}", sig.output) 629 write!(f, " -> {}", sig.output)
641 } 630 }
642 Ty::FnDef { name, substs, sig, .. } => { 631 Ty::FnDef { def, name, substs, sig, .. } => {
643 write!(f, "fn {}", name)?; 632 match def {
633 CallableDef::Function(_) => write!(f, "fn {}", name)?,
634 CallableDef::Struct(_) | CallableDef::EnumVariant(_) => write!(f, "{}", name)?,
635 }
644 if substs.0.len() > 0 { 636 if substs.0.len() > 0 {
645 join(substs.0.iter()).surround_with("<", ">").separator(", ").to_fmt(f)?; 637 join(substs.0.iter()).surround_with("<", ">").separator(", ").to_fmt(f)?;
646 } 638 }
@@ -712,16 +704,18 @@ fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) ->
712 .iter() 704 .iter()
713 .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref)) 705 .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref))
714 .collect::<Vec<_>>(); 706 .collect::<Vec<_>>();
715 let output = type_for_enum(db, def.parent_enum(db));
716 let sig = Arc::new(FnSig { input, output });
717 let substs = make_substs(&generics); 707 let substs = make_substs(&generics);
708 let output = type_for_enum(db, def.parent_enum(db)).apply_substs(substs.clone());
709 let sig = Arc::new(FnSig { input, output });
718 Ty::FnDef { def: def.into(), sig, name, substs } 710 Ty::FnDef { def: def.into(), sig, name, substs }
719} 711}
720 712
721fn make_substs(generics: &GenericParams) -> Substs { 713fn make_substs(generics: &GenericParams) -> Substs {
722 Substs( 714 Substs(
723 (0..generics.count_params_including_parent()) 715 generics
724 .map(|_p| Ty::Unknown) 716 .params_including_parent()
717 .into_iter()
718 .map(|p| Ty::Param { idx: p.idx, name: p.name.clone() })
725 .collect::<Vec<_>>() 719 .collect::<Vec<_>>()
726 .into(), 720 .into(),
727 ) 721 )
@@ -736,7 +730,7 @@ fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty {
736 } 730 }
737} 731}
738 732
739pub(crate) fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty { 733fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty {
740 let generics = s.generic_params(db); 734 let generics = s.generic_params(db);
741 Ty::Adt { 735 Ty::Adt {
742 def_id: s.into(), 736 def_id: s.into(),
@@ -1393,6 +1387,37 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1393 ty 1387 ty
1394 } 1388 }
1395 1389
1390 fn substs_for_method_call(
1391 &mut self,
1392 def_generics: Option<Arc<GenericParams>>,
1393 generic_args: &Option<GenericArgs>,
1394 ) -> Substs {
1395 let (parent_param_count, param_count) =
1396 def_generics.map_or((0, 0), |g| (g.count_parent_params(), g.params.len()));
1397 let mut substs = Vec::with_capacity(parent_param_count + param_count);
1398 for _ in 0..parent_param_count {
1399 substs.push(Ty::Unknown);
1400 }
1401 // handle provided type arguments
1402 if let Some(generic_args) = generic_args {
1403 // if args are provided, it should be all of them, but we can't rely on that
1404 for arg in generic_args.args.iter().take(param_count) {
1405 match arg {
1406 GenericArg::Type(type_ref) => {
1407 let ty = self.make_ty(type_ref);
1408 substs.push(ty);
1409 }
1410 }
1411 }
1412 };
1413 let supplied_params = substs.len();
1414 for _ in supplied_params..parent_param_count + param_count {
1415 substs.push(Ty::Unknown);
1416 }
1417 assert_eq!(substs.len(), parent_param_count + param_count);
1418 Substs(substs.into())
1419 }
1420
1396 fn infer_expr(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { 1421 fn infer_expr(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
1397 let body = Arc::clone(&self.body); // avoid borrow checker problem 1422 let body = Arc::clone(&self.body); // avoid borrow checker problem
1398 let ty = match &body[tgt_expr] { 1423 let ty = match &body[tgt_expr] {
@@ -1483,25 +1508,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1483 } 1508 }
1484 None => (Ty::Unknown, receiver_ty, None), 1509 None => (Ty::Unknown, receiver_ty, None),
1485 }; 1510 };
1486 // handle provided type arguments 1511 let substs = self.substs_for_method_call(def_generics, generic_args);
1487 let method_ty = if let Some(generic_args) = generic_args { 1512 let method_ty = method_ty.apply_substs(substs);
1488 // if args are provided, it should be all of them, but we can't rely on that
1489 let param_count = def_generics.map(|g| g.params.len()).unwrap_or(0);
1490 let mut new_substs = Vec::with_capacity(generic_args.args.len());
1491 for arg in generic_args.args.iter().take(param_count) {
1492 match arg {
1493 GenericArg::Type(type_ref) => {
1494 let ty = self.make_ty(type_ref);
1495 new_substs.push(ty);
1496 }
1497 }
1498 }
1499 let substs = method_ty.substs().unwrap_or_else(Substs::empty);
1500 let substs = substs.replace_tail(new_substs);
1501 method_ty.apply_substs(substs)
1502 } else {
1503 method_ty
1504 };
1505 let method_ty = self.insert_type_vars(method_ty); 1513 let method_ty = self.insert_type_vars(method_ty);
1506 let (expected_receiver_ty, param_tys, ret_ty) = match &method_ty { 1514 let (expected_receiver_ty, param_tys, ret_ty) = match &method_ty {
1507 Ty::FnPtr(sig) => { 1515 Ty::FnPtr(sig) => {
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_struct.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_struct.snap
index 294186b06..32f1fa108 100644
--- a/crates/ra_hir/src/ty/snapshots/tests__infer_struct.snap
+++ b/crates/ra_hir/src/ty/snapshots/tests__infer_struct.snap
@@ -1,19 +1,19 @@
1--- 1---
2created: "2019-02-17T16:16:58.863630956Z" 2created: "2019-02-20T21:31:12.910924715Z"
3creator: [email protected] 3creator: [email protected]
4source: crates/ra_hir/src/ty/tests.rs 4source: crates/ra_hir/src/ty/tests.rs
5expression: "&result" 5expression: "&result"
6--- 6---
7[72; 154) '{ ...a.c; }': () 7[72; 154) '{ ...a.c; }': ()
8[82; 83) 'c': C 8[82; 83) 'c': C
9[86; 87) 'C': fn C(usize) -> C 9[86; 87) 'C': C(usize) -> C
10[86; 90) 'C(1)': C 10[86; 90) 'C(1)': C
11[88; 89) '1': usize 11[88; 89) '1': usize
12[96; 97) 'B': B 12[96; 97) 'B': B
13[107; 108) 'a': A 13[107; 108) 'a': A
14[114; 133) 'A { b:...C(1) }': A 14[114; 133) 'A { b:...C(1) }': A
15[121; 122) 'B': B 15[121; 122) 'B': B
16[127; 128) 'C': fn C(usize) -> C 16[127; 128) 'C': C(usize) -> C
17[127; 131) 'C(1)': C 17[127; 131) 'C(1)': C
18[129; 130) '1': usize 18[129; 130) '1': usize
19[139; 140) 'a': A 19[139; 140) 'a': A
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_tuple_struct_generics.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_tuple_struct_generics.snap
new file mode 100644
index 000000000..783795cfd
--- /dev/null
+++ b/crates/ra_hir/src/ty/snapshots/tests__infer_tuple_struct_generics.snap
@@ -0,0 +1,23 @@
1---
2created: "2019-02-20T21:31:12.911275141Z"
3creator: [email protected]
4source: crates/ra_hir/src/ty/tests.rs
5expression: "&result"
6---
7[77; 185) '{ ...one; }': ()
8[83; 84) 'A': A<i32>(T) -> A<T>
9[83; 88) 'A(42)': A<i32>
10[85; 87) '42': i32
11[94; 95) 'A': A<u128>(T) -> A<T>
12[94; 103) 'A(42u128)': A<u128>
13[96; 102) '42u128': u128
14[109; 113) 'Some': Some<&str>(T) -> Option<T>
15[109; 118) 'Some("x")': Option<&str>
16[114; 117) '"x"': &str
17[124; 136) 'Option::Some': Some<&str>(T) -> Option<T>
18[124; 141) 'Option...e("x")': Option<&str>
19[137; 140) '"x"': &str
20[147; 151) 'None': Option<[unknown]>
21[161; 162) 'x': Option<i64>
22[178; 182) 'None': Option<i64>
23
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index fee6ed0b3..f04e9109c 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -466,6 +466,27 @@ fn test(a1: A<u32>, i: i32) {
466} 466}
467 467
468#[test] 468#[test]
469fn infer_tuple_struct_generics() {
470 check_inference(
471 "infer_tuple_struct_generics",
472 r#"
473struct A<T>(T);
474enum Option<T> { Some(T), None };
475use Option::*;
476
477fn test() {
478 A(42);
479 A(42u128);
480 Some("x");
481 Option::Some("x");
482 None;
483 let x: Option<i64> = None;
484}
485"#,
486 );
487}
488
489#[test]
469fn infer_generics_in_patterns() { 490fn infer_generics_in_patterns() {
470 check_inference( 491 check_inference(
471 "infer_generics_in_patterns", 492 "infer_generics_in_patterns",