aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcus Klaas de Vries <[email protected]>2019-01-17 09:54:47 +0000
committerAleksey Kladov <[email protected]>2019-01-19 12:37:25 +0000
commit9433a108cfcf3a9c7de9299d6641a5abf9031a17 (patch)
treed7054f505217be400c1e4b77417a2b9c525dd90f
parentbe1b4034a523081cfeea1c7a1d61130d5d1778e1 (diff)
Make pattern inference work w/o proper expecations
-rw-r--r--crates/ra_hir/src/ty.rs72
-rw-r--r--crates/ra_hir/src/ty/tests/data/pattern.txt26
2 files changed, 63 insertions, 35 deletions
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 75794b732..8ad80990e 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -911,7 +911,6 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
911 return Ty::Unknown; 911 return Ty::Unknown;
912 }; 912 };
913 913
914 // walk subpats
915 if fields.len() != sub_pats.len() { 914 if fields.len() != sub_pats.len() {
916 return Ty::Unknown; 915 return Ty::Unknown;
917 } 916 }
@@ -944,44 +943,49 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
944 ty 943 ty
945 } 944 }
946 945
947 // FIXME: Expectation should probably contain a reference to a Ty instead of 946 // TODO: Expectation should probably contain a Cow pointer to Ty?
948 // a Ty itself 947 // so that we can make new expectations of subtypes cheaply
949 fn infer_pat(&mut self, pat: PatId, expected: &Expectation) -> Ty { 948 fn infer_pat(&mut self, pat: PatId, expected: &Expectation) -> Ty {
950 let body = Arc::clone(&self.body); // avoid borrow checker problem 949 let body = Arc::clone(&self.body); // avoid borrow checker problem
951 950
952 // FIXME: we can do some inference even if the expected ty isnt already 951 let ty = match &body[pat] {
953 // of the right form 952 Pat::Tuple(ref args) => {
954 let ty = match (&body[pat], &expected.ty) { 953 // this can probably be done without cloning/ collecting
955 (Pat::Tuple(ref args), &Ty::Tuple(ref tuple_args)) 954 let expectations = match expected.ty {
956 if args.len() == tuple_args.len() => 955 Ty::Tuple(ref tuple_args) if args.len() == tuple_args.len() => {
957 { 956 tuple_args.iter().cloned().collect()
958 for (&pat, ty) in args.iter().zip(tuple_args.iter()) { 957 }
959 // FIXME: can we do w/o cloning? 958 _ => vec![Ty::Unknown; args.len()],
960 self.infer_pat(pat, &Expectation::has_type(ty.clone())); 959 };
961 } 960
962 expected.ty.clone() 961 let inner_tys = args
962 .iter()
963 .zip(expectations.into_iter())
964 .map(|(&pat, ty)| self.infer_pat(pat, &Expectation::has_type(ty)))
965 .collect::<Vec<_>>()
966 .into();
967
968 Ty::Tuple(inner_tys)
963 } 969 }
964 (&Pat::Ref { pat, mutability }, &Ty::Ref(ref sub_ty, ty_mut)) 970 Pat::Ref { pat, mutability } => {
965 if mutability == ty_mut => 971 let expectation = match expected.ty {
966 { 972 Ty::Ref(ref sub_ty, exp_mut) if *mutability == exp_mut => {
967 self.infer_pat(pat, &Expectation::has_type((&**sub_ty).clone())); 973 Expectation::has_type((&**sub_ty).clone())
968 expected.ty.clone() 974 }
975 _ => Expectation::none(),
976 };
977 let subty = self.infer_pat(*pat, &expectation);
978 Ty::Ref(subty.into(), *mutability)
969 } 979 }
970 ( 980 Pat::TupleStruct {
971 &Pat::TupleStruct { 981 path: ref p,
972 path: ref p, 982 args: ref sub_pats,
973 args: ref sub_pats, 983 } => self.infer_tuple_struct(p.as_ref(), sub_pats),
974 }, 984 Pat::Struct {
975 _, 985 path: ref p,
976 ) => self.infer_tuple_struct(p.as_ref(), sub_pats), 986 args: ref fields,
977 ( 987 } => self.infer_struct(p.as_ref(), fields),
978 &Pat::Struct { 988 _ => Ty::Unknown,
979 path: ref p,
980 args: ref fields,
981 },
982 _,
983 ) => self.infer_struct(p.as_ref(), fields),
984 (_, ref _expected_ty) => expected.ty.clone(),
985 }; 989 };
986 // use a new type variable if we got Ty::Unknown here 990 // use a new type variable if we got Ty::Unknown here
987 let ty = self.insert_type_vars_shallow(ty); 991 let ty = self.insert_type_vars_shallow(ty);
diff --git a/crates/ra_hir/src/ty/tests/data/pattern.txt b/crates/ra_hir/src/ty/tests/data/pattern.txt
index cca521833..8b7c967c4 100644
--- a/crates/ra_hir/src/ty/tests/data/pattern.txt
+++ b/crates/ra_hir/src/ty/tests/data/pattern.txt
@@ -1,5 +1,5 @@
1[9; 10) 'x': &i32 1[9; 10) 'x': &i32
2[18; 98) '{ ...o"); }': () 2[18; 259) '{ ...c }; }': ()
3[28; 29) 'y': &i32 3[28; 29) 'y': &i32
4[32; 33) 'x': &i32 4[32; 33) 'x': &i32
5[43; 45) '&z': &i32 5[43; 45) '&z': &i32
@@ -13,3 +13,27 @@
13[83; 95) '(1, "hello")': (i32, &str) 13[83; 95) '(1, "hello")': (i32, &str)
14[84; 85) '1': i32 14[84; 85) '1': i32
15[87; 94) '"hello"': &str 15[87; 94) '"hello"': &str
16[102; 152) 'for (e... }': ()
17[106; 112) '(e, f)': ([unknown], [unknown])
18[107; 108) 'e': [unknown]
19[110; 111) 'f': [unknown]
20[116; 125) 'some_iter': [unknown]
21[126; 152) '{ ... }': ()
22[140; 141) 'g': [unknown]
23[144; 145) 'e': [unknown]
24[158; 205) 'if let... }': ()
25[165; 170) '[val]': [unknown]
26[173; 176) 'opt': [unknown]
27[177; 205) '{ ... }': ()
28[191; 192) 'h': [unknown]
29[195; 198) 'val': [unknown]
30[215; 221) 'lambda': [unknown]
31[224; 256) '|a: u6...b; c }': [unknown]
32[225; 226) 'a': u64
33[233; 234) 'b': u64
34[236; 237) 'c': i32
35[244; 256) '{ a + b; c }': i32
36[246; 247) 'a': u64
37[246; 251) 'a + b': u64
38[250; 251) 'b': u64
39[253; 254) 'c': i32