diff options
Diffstat (limited to 'crates/ra_hir/src/ty.rs')
-rw-r--r-- | crates/ra_hir/src/ty.rs | 72 |
1 files changed, 50 insertions, 22 deletions
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 453520bbe..7203a8a10 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -879,11 +879,22 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
879 | ty | 879 | ty |
880 | } | 880 | } |
881 | 881 | ||
882 | fn unify_substs(&mut self, substs1: &Substs, substs2: &Substs) -> bool { | 882 | fn unify_substs(&mut self, substs1: &Substs, substs2: &Substs, depth: usize) -> bool { |
883 | substs1.0.iter().zip(substs2.0.iter()).all(|(t1, t2)| self.unify(t1, t2)) | 883 | substs1.0.iter().zip(substs2.0.iter()).all(|(t1, t2)| self.unify_inner(t1, t2, depth)) |
884 | } | 884 | } |
885 | 885 | ||
886 | fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool { | 886 | fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool { |
887 | self.unify_inner(ty1, ty2, 0) | ||
888 | } | ||
889 | |||
890 | fn unify_inner(&mut self, ty1: &Ty, ty2: &Ty, depth: usize) -> bool { | ||
891 | if depth > 1000 { | ||
892 | // prevent stackoverflows | ||
893 | panic!("infinite recursion in unification"); | ||
894 | } | ||
895 | if ty1 == ty2 { | ||
896 | return true; | ||
897 | } | ||
887 | // try to resolve type vars first | 898 | // try to resolve type vars first |
888 | let ty1 = self.resolve_ty_shallow(ty1); | 899 | let ty1 = self.resolve_ty_shallow(ty1); |
889 | let ty2 = self.resolve_ty_shallow(ty2); | 900 | let ty2 = self.resolve_ty_shallow(ty2); |
@@ -904,13 +915,15 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
904 | ( | 915 | ( |
905 | Ty::Adt { def_id: def_id1, substs: substs1, .. }, | 916 | Ty::Adt { def_id: def_id1, substs: substs1, .. }, |
906 | Ty::Adt { def_id: def_id2, substs: substs2, .. }, | 917 | Ty::Adt { def_id: def_id2, substs: substs2, .. }, |
907 | ) if def_id1 == def_id2 => self.unify_substs(substs1, substs2), | 918 | ) if def_id1 == def_id2 => self.unify_substs(substs1, substs2, depth + 1), |
908 | (Ty::Slice(t1), Ty::Slice(t2)) => self.unify(t1, t2), | 919 | (Ty::Slice(t1), Ty::Slice(t2)) => self.unify_inner(t1, t2, depth + 1), |
909 | (Ty::RawPtr(t1, m1), Ty::RawPtr(t2, m2)) if m1 == m2 => self.unify(t1, t2), | 920 | (Ty::RawPtr(t1, m1), Ty::RawPtr(t2, m2)) if m1 == m2 => { |
910 | (Ty::Ref(t1, m1), Ty::Ref(t2, m2)) if m1 == m2 => self.unify(t1, t2), | 921 | self.unify_inner(t1, t2, depth + 1) |
922 | } | ||
923 | (Ty::Ref(t1, m1), Ty::Ref(t2, m2)) if m1 == m2 => self.unify_inner(t1, t2, depth + 1), | ||
911 | (Ty::FnPtr(sig1), Ty::FnPtr(sig2)) if sig1 == sig2 => true, | 924 | (Ty::FnPtr(sig1), Ty::FnPtr(sig2)) if sig1 == sig2 => true, |
912 | (Ty::Tuple(ts1), Ty::Tuple(ts2)) if ts1.len() == ts2.len() => { | 925 | (Ty::Tuple(ts1), Ty::Tuple(ts2)) if ts1.len() == ts2.len() => { |
913 | ts1.iter().zip(ts2.iter()).all(|(t1, t2)| self.unify(t1, t2)) | 926 | ts1.iter().zip(ts2.iter()).all(|(t1, t2)| self.unify_inner(t1, t2, depth + 1)) |
914 | } | 927 | } |
915 | (Ty::Infer(InferTy::TypeVar(tv1)), Ty::Infer(InferTy::TypeVar(tv2))) | 928 | (Ty::Infer(InferTy::TypeVar(tv1)), Ty::Infer(InferTy::TypeVar(tv2))) |
916 | | (Ty::Infer(InferTy::IntVar(tv1)), Ty::Infer(InferTy::IntVar(tv2))) | 929 | | (Ty::Infer(InferTy::IntVar(tv1)), Ty::Infer(InferTy::IntVar(tv2))) |
@@ -989,19 +1002,30 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
989 | /// If `ty` is a type variable with known type, returns that type; | 1002 | /// If `ty` is a type variable with known type, returns that type; |
990 | /// otherwise, return ty. | 1003 | /// otherwise, return ty. |
991 | fn resolve_ty_shallow<'b>(&mut self, ty: &'b Ty) -> Cow<'b, Ty> { | 1004 | fn resolve_ty_shallow<'b>(&mut self, ty: &'b Ty) -> Cow<'b, Ty> { |
992 | match ty { | 1005 | let mut ty = Cow::Borrowed(ty); |
993 | Ty::Infer(tv) => { | 1006 | // The type variable could resolve to a int/float variable. Hence try |
994 | let inner = tv.to_inner(); | 1007 | // resolving up to three times; each type of variable shouldn't occur |
995 | match self.var_unification_table.probe_value(inner).known() { | 1008 | // more than once |
996 | Some(known_ty) => { | 1009 | for i in 0..3 { |
997 | // The known_ty can't be a type var itself | 1010 | if i > 0 { |
998 | Cow::Owned(known_ty.clone()) | 1011 | tested_by!(type_var_resolves_to_int_var); |
1012 | } | ||
1013 | match &*ty { | ||
1014 | Ty::Infer(tv) => { | ||
1015 | let inner = tv.to_inner(); | ||
1016 | match self.var_unification_table.probe_value(inner).known() { | ||
1017 | Some(known_ty) => { | ||
1018 | // The known_ty can't be a type var itself | ||
1019 | ty = Cow::Owned(known_ty.clone()); | ||
1020 | } | ||
1021 | _ => return ty, | ||
999 | } | 1022 | } |
1000 | _ => Cow::Borrowed(ty), | ||
1001 | } | 1023 | } |
1024 | _ => return ty, | ||
1002 | } | 1025 | } |
1003 | _ => Cow::Borrowed(ty), | ||
1004 | } | 1026 | } |
1027 | log::error!("Inference variable still not resolved: {:?}", ty); | ||
1028 | ty | ||
1005 | } | 1029 | } |
1006 | 1030 | ||
1007 | /// Resolves the type completely; type variables without known type are | 1031 | /// Resolves the type completely; type variables without known type are |
@@ -1185,17 +1209,21 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1185 | self.infer_path_expr(&resolver, &path).unwrap_or(Ty::Unknown) | 1209 | self.infer_path_expr(&resolver, &path).unwrap_or(Ty::Unknown) |
1186 | } | 1210 | } |
1187 | Pat::Bind { mode, name: _name, subpat } => { | 1211 | Pat::Bind { mode, name: _name, subpat } => { |
1188 | let subty = if let Some(subpat) = subpat { | 1212 | let inner_ty = if let Some(subpat) = subpat { |
1189 | self.infer_pat(*subpat, expected) | 1213 | self.infer_pat(*subpat, expected) |
1190 | } else { | 1214 | } else { |
1191 | expected.clone() | 1215 | expected.clone() |
1192 | }; | 1216 | }; |
1217 | let inner_ty = self.insert_type_vars_shallow(inner_ty); | ||
1193 | 1218 | ||
1194 | match mode { | 1219 | let bound_ty = match mode { |
1195 | BindingAnnotation::Ref => Ty::Ref(subty.into(), Mutability::Shared), | 1220 | BindingAnnotation::Ref => Ty::Ref(inner_ty.clone().into(), Mutability::Shared), |
1196 | BindingAnnotation::RefMut => Ty::Ref(subty.into(), Mutability::Mut), | 1221 | BindingAnnotation::RefMut => Ty::Ref(inner_ty.clone().into(), Mutability::Mut), |
1197 | BindingAnnotation::Mutable | BindingAnnotation::Unannotated => subty, | 1222 | BindingAnnotation::Mutable | BindingAnnotation::Unannotated => inner_ty.clone(), |
1198 | } | 1223 | }; |
1224 | let bound_ty = self.resolve_ty_as_possible(&mut vec![], bound_ty); | ||
1225 | self.write_pat_ty(pat, bound_ty); | ||
1226 | return inner_ty; | ||
1199 | } | 1227 | } |
1200 | _ => Ty::Unknown, | 1228 | _ => Ty::Unknown, |
1201 | }; | 1229 | }; |