diff options
Diffstat (limited to 'crates/ra_hir/src/ty.rs')
-rw-r--r-- | crates/ra_hir/src/ty.rs | 72 |
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); |