aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty.rs
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 /crates/ra_hir/src/ty.rs
parentbe1b4034a523081cfeea1c7a1d61130d5d1778e1 (diff)
Make pattern inference work w/o proper expecations
Diffstat (limited to 'crates/ra_hir/src/ty.rs')
-rw-r--r--crates/ra_hir/src/ty.rs72
1 files changed, 38 insertions, 34 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);