diff options
Diffstat (limited to 'crates/ra_hir/src/ty/infer.rs')
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 152 |
1 files changed, 92 insertions, 60 deletions
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index def787fb1..cbbba8b23 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs | |||
@@ -297,23 +297,35 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
297 | fn unify_inner_trivial(&mut self, ty1: &Ty, ty2: &Ty) -> bool { | 297 | fn unify_inner_trivial(&mut self, ty1: &Ty, ty2: &Ty) -> bool { |
298 | match (ty1, ty2) { | 298 | match (ty1, ty2) { |
299 | (Ty::Unknown, _) | (_, Ty::Unknown) => true, | 299 | (Ty::Unknown, _) | (_, Ty::Unknown) => true, |
300 | |||
300 | (Ty::Infer(InferTy::TypeVar(tv1)), Ty::Infer(InferTy::TypeVar(tv2))) | 301 | (Ty::Infer(InferTy::TypeVar(tv1)), Ty::Infer(InferTy::TypeVar(tv2))) |
301 | | (Ty::Infer(InferTy::IntVar(tv1)), Ty::Infer(InferTy::IntVar(tv2))) | 302 | | (Ty::Infer(InferTy::IntVar(tv1)), Ty::Infer(InferTy::IntVar(tv2))) |
302 | | (Ty::Infer(InferTy::FloatVar(tv1)), Ty::Infer(InferTy::FloatVar(tv2))) => { | 303 | | (Ty::Infer(InferTy::FloatVar(tv1)), Ty::Infer(InferTy::FloatVar(tv2))) |
304 | | ( | ||
305 | Ty::Infer(InferTy::MaybeNeverTypeVar(tv1)), | ||
306 | Ty::Infer(InferTy::MaybeNeverTypeVar(tv2)), | ||
307 | ) => { | ||
303 | // both type vars are unknown since we tried to resolve them | 308 | // both type vars are unknown since we tried to resolve them |
304 | self.var_unification_table.union(*tv1, *tv2); | 309 | self.var_unification_table.union(*tv1, *tv2); |
305 | true | 310 | true |
306 | } | 311 | } |
312 | |||
313 | // The order of MaybeNeverTypeVar matters here. | ||
314 | // Unifying MaybeNeverTypeVar and TypeVar will let the latter become MaybeNeverTypeVar. | ||
315 | // Unifying MaybeNeverTypeVar and other concrete type will let the former become it. | ||
307 | (Ty::Infer(InferTy::TypeVar(tv)), other) | 316 | (Ty::Infer(InferTy::TypeVar(tv)), other) |
308 | | (other, Ty::Infer(InferTy::TypeVar(tv))) | 317 | | (other, Ty::Infer(InferTy::TypeVar(tv))) |
309 | | (Ty::Infer(InferTy::IntVar(tv)), other) | 318 | | (Ty::Infer(InferTy::MaybeNeverTypeVar(tv)), other) |
310 | | (other, Ty::Infer(InferTy::IntVar(tv))) | 319 | | (other, Ty::Infer(InferTy::MaybeNeverTypeVar(tv))) |
311 | | (Ty::Infer(InferTy::FloatVar(tv)), other) | 320 | | (Ty::Infer(InferTy::IntVar(tv)), other @ ty_app!(TypeCtor::Int(_))) |
312 | | (other, Ty::Infer(InferTy::FloatVar(tv))) => { | 321 | | (other @ ty_app!(TypeCtor::Int(_)), Ty::Infer(InferTy::IntVar(tv))) |
322 | | (Ty::Infer(InferTy::FloatVar(tv)), other @ ty_app!(TypeCtor::Float(_))) | ||
323 | | (other @ ty_app!(TypeCtor::Float(_)), Ty::Infer(InferTy::FloatVar(tv))) => { | ||
313 | // the type var is unknown since we tried to resolve it | 324 | // the type var is unknown since we tried to resolve it |
314 | self.var_unification_table.union_value(*tv, TypeVarValue::Known(other.clone())); | 325 | self.var_unification_table.union_value(*tv, TypeVarValue::Known(other.clone())); |
315 | true | 326 | true |
316 | } | 327 | } |
328 | |||
317 | _ => false, | 329 | _ => false, |
318 | } | 330 | } |
319 | } | 331 | } |
@@ -330,6 +342,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
330 | Ty::Infer(InferTy::FloatVar(self.var_unification_table.new_key(TypeVarValue::Unknown))) | 342 | Ty::Infer(InferTy::FloatVar(self.var_unification_table.new_key(TypeVarValue::Unknown))) |
331 | } | 343 | } |
332 | 344 | ||
345 | fn new_maybe_never_type_var(&mut self) -> Ty { | ||
346 | Ty::Infer(InferTy::MaybeNeverTypeVar( | ||
347 | self.var_unification_table.new_key(TypeVarValue::Unknown), | ||
348 | )) | ||
349 | } | ||
350 | |||
333 | /// Replaces Ty::Unknown by a new type var, so we can maybe still infer it. | 351 | /// Replaces Ty::Unknown by a new type var, so we can maybe still infer it. |
334 | fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty { | 352 | fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty { |
335 | match ty { | 353 | match ty { |
@@ -817,6 +835,24 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
817 | ty | 835 | ty |
818 | } | 836 | } |
819 | 837 | ||
838 | /// Merge two types from different branches, with possible implicit coerce. | ||
839 | /// | ||
840 | /// Note that it is only possible that one type are coerced to another. | ||
841 | /// Coercing both types to another least upper bound type is not possible in rustc, | ||
842 | /// which will simply result in "incompatible types" error. | ||
843 | fn coerce_merge_branch<'t>(&mut self, ty1: &Ty, ty2: &Ty) -> Ty { | ||
844 | if self.coerce(ty1, ty2) { | ||
845 | ty2.clone() | ||
846 | } else if self.coerce(ty2, ty1) { | ||
847 | ty1.clone() | ||
848 | } else { | ||
849 | tested_by!(coerce_merge_fail_fallback); | ||
850 | // For incompatible types, we use the latter one as result | ||
851 | // to be better recovery for `if` without `else`. | ||
852 | ty2.clone() | ||
853 | } | ||
854 | } | ||
855 | |||
820 | /// Unify two types, but may coerce the first one to the second one | 856 | /// Unify two types, but may coerce the first one to the second one |
821 | /// using "implicit coercion rules" if needed. | 857 | /// using "implicit coercion rules" if needed. |
822 | /// | 858 | /// |
@@ -828,12 +864,26 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
828 | } | 864 | } |
829 | 865 | ||
830 | fn coerce_inner(&mut self, mut from_ty: Ty, to_ty: &Ty) -> bool { | 866 | fn coerce_inner(&mut self, mut from_ty: Ty, to_ty: &Ty) -> bool { |
831 | match (&mut from_ty, &*to_ty) { | 867 | match (&from_ty, to_ty) { |
832 | // Top and bottom type | 868 | // Never type will make type variable to fallback to Never Type instead of Unknown. |
869 | (ty_app!(TypeCtor::Never), Ty::Infer(InferTy::TypeVar(tv))) => { | ||
870 | let var = self.new_maybe_never_type_var(); | ||
871 | self.var_unification_table.union_value(*tv, TypeVarValue::Known(var)); | ||
872 | return true; | ||
873 | } | ||
833 | (ty_app!(TypeCtor::Never), _) => return true, | 874 | (ty_app!(TypeCtor::Never), _) => return true, |
834 | 875 | ||
835 | // FIXME: Solve `FromTy: CoerceUnsized<ToTy>` instead of listing common impls here. | 876 | // Trivial cases, this should go after `never` check to |
877 | // avoid infer result type to be never | ||
878 | _ => { | ||
879 | if self.unify_inner_trivial(&from_ty, &to_ty) { | ||
880 | return true; | ||
881 | } | ||
882 | } | ||
883 | } | ||
836 | 884 | ||
885 | // Pointer weakening and function to pointer | ||
886 | match (&mut from_ty, to_ty) { | ||
837 | // `*mut T`, `&mut T, `&T`` -> `*const T` | 887 | // `*mut T`, `&mut T, `&T`` -> `*const T` |
838 | // `&mut T` -> `&T` | 888 | // `&mut T` -> `&T` |
839 | // `&mut T` -> `*mut T` | 889 | // `&mut T` -> `*mut T` |
@@ -866,71 +916,67 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
866 | } | 916 | } |
867 | } | 917 | } |
868 | 918 | ||
869 | // Trivial cases, this should go after `never` check to | 919 | _ => {} |
870 | // avoid infer result type to be never | ||
871 | _ => { | ||
872 | if self.unify_inner_trivial(&from_ty, &to_ty) { | ||
873 | return true; | ||
874 | } | ||
875 | } | ||
876 | } | 920 | } |
877 | 921 | ||
878 | // Try coerce or unify | 922 | // FIXME: Solve `FromTy: CoerceUnsized<ToTy>` instead of listing common impls here. |
879 | match (&from_ty, &to_ty) { | 923 | match (&from_ty, &to_ty) { |
880 | // FIXME: Solve `FromTy: CoerceUnsized<ToTy>` instead of listing common impls here. | 924 | // Mutilibity is checked above |
881 | (ty_app!(TypeCtor::Ref(_), st1), ty_app!(TypeCtor::Ref(_), st2)) | 925 | (ty_app!(TypeCtor::Ref(_), st1), ty_app!(TypeCtor::Ref(_), st2)) |
882 | | (ty_app!(TypeCtor::RawPtr(_), st1), ty_app!(TypeCtor::RawPtr(_), st2)) => { | 926 | | (ty_app!(TypeCtor::RawPtr(_), st1), ty_app!(TypeCtor::RawPtr(_), st2)) => { |
883 | match self.try_coerce_unsized(&st1[0], &st2[0], 0) { | 927 | if self.try_coerce_unsized(&st1[0], &st2[0], 0) { |
884 | Some(ret) => return ret, | 928 | return true; |
885 | None => {} | ||
886 | } | 929 | } |
887 | } | 930 | } |
888 | _ => {} | 931 | _ => {} |
889 | } | 932 | } |
890 | 933 | ||
891 | // Auto Deref if cannot coerce | 934 | // Auto Deref if cannot coerce |
892 | match (&from_ty, &to_ty) { | 935 | match (&from_ty, to_ty) { |
936 | // FIXME: DerefMut | ||
893 | (ty_app!(TypeCtor::Ref(_), st1), ty_app!(TypeCtor::Ref(_), st2)) => { | 937 | (ty_app!(TypeCtor::Ref(_), st1), ty_app!(TypeCtor::Ref(_), st2)) => { |
894 | self.unify_autoderef_behind_ref(&st1[0], &st2[0]) | 938 | self.unify_autoderef_behind_ref(&st1[0], &st2[0]) |
895 | } | 939 | } |
896 | 940 | ||
897 | // Normal unify | 941 | // Otherwise, normal unify |
898 | _ => self.unify(&from_ty, &to_ty), | 942 | _ => self.unify(&from_ty, to_ty), |
899 | } | 943 | } |
900 | } | 944 | } |
901 | 945 | ||
902 | /// Coerce a type to a DST if `FromTy: Unsize<ToTy>` | 946 | /// Coerce a type to a DST if `FromTy: Unsize<ToTy>` |
903 | /// | 947 | /// |
904 | /// See: `https://doc.rust-lang.org/nightly/std/marker/trait.Unsize.html` | 948 | /// See: `https://doc.rust-lang.org/nightly/std/marker/trait.Unsize.html` |
905 | fn try_coerce_unsized(&mut self, from_ty: &Ty, to_ty: &Ty, depth: usize) -> Option<bool> { | 949 | fn try_coerce_unsized(&mut self, from_ty: &Ty, to_ty: &Ty, depth: usize) -> bool { |
906 | if depth > 1000 { | 950 | if depth > 1000 { |
907 | panic!("Infinite recursion in coercion"); | 951 | panic!("Infinite recursion in coercion"); |
908 | } | 952 | } |
909 | 953 | ||
910 | // FIXME: Correctly handle | ||
911 | match (&from_ty, &to_ty) { | 954 | match (&from_ty, &to_ty) { |
912 | // `[T; N]` -> `[T]` | 955 | // `[T; N]` -> `[T]` |
913 | (ty_app!(TypeCtor::Array, st1), ty_app!(TypeCtor::Slice, st2)) => { | 956 | (ty_app!(TypeCtor::Array, st1), ty_app!(TypeCtor::Slice, st2)) => { |
914 | Some(self.unify(&st1[0], &st2[0])) | 957 | self.unify(&st1[0], &st2[0]) |
915 | } | 958 | } |
916 | 959 | ||
917 | // `T` -> `dyn Trait` when `T: Trait` | 960 | // `T` -> `dyn Trait` when `T: Trait` |
918 | (_, Ty::Dyn(_)) => { | 961 | (_, Ty::Dyn(_)) => { |
919 | // FIXME: Check predicates | 962 | // FIXME: Check predicates |
920 | Some(true) | 963 | true |
921 | } | 964 | } |
922 | 965 | ||
923 | (ty_app!(ctor1, st1), ty_app!(ctor2, st2)) if ctor1 == ctor2 => { | 966 | ( |
967 | ty_app!(TypeCtor::Adt(Adt::Struct(struct1)), st1), | ||
968 | ty_app!(TypeCtor::Adt(Adt::Struct(struct2)), st2), | ||
969 | ) if struct1 == struct2 => { | ||
970 | // FIXME: Check preconditions here | ||
924 | for (ty1, ty2) in st1.iter().zip(st2.iter()) { | 971 | for (ty1, ty2) in st1.iter().zip(st2.iter()) { |
925 | match self.try_coerce_unsized(ty1, ty2, depth + 1) { | 972 | if !self.try_coerce_unsized(ty1, ty2, depth + 1) { |
926 | Some(true) => {} | 973 | return false; |
927 | ret => return ret, | ||
928 | } | 974 | } |
929 | } | 975 | } |
930 | Some(true) | 976 | true |
931 | } | 977 | } |
932 | 978 | ||
933 | _ => None, | 979 | _ => false, |
934 | } | 980 | } |
935 | } | 981 | } |
936 | 982 | ||
@@ -980,18 +1026,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
980 | self.infer_expr(*condition, &Expectation::has_type(Ty::simple(TypeCtor::Bool))); | 1026 | self.infer_expr(*condition, &Expectation::has_type(Ty::simple(TypeCtor::Bool))); |
981 | 1027 | ||
982 | let then_ty = self.infer_expr_inner(*then_branch, &expected); | 1028 | let then_ty = self.infer_expr_inner(*then_branch, &expected); |
983 | self.coerce(&then_ty, &expected.ty); | ||
984 | |||
985 | let else_ty = match else_branch { | 1029 | let else_ty = match else_branch { |
986 | Some(else_branch) => self.infer_expr_inner(*else_branch, &expected), | 1030 | Some(else_branch) => self.infer_expr_inner(*else_branch, &expected), |
987 | None => Ty::unit(), | 1031 | None => Ty::unit(), |
988 | }; | 1032 | }; |
989 | if !self.coerce(&else_ty, &expected.ty) { | 1033 | |
990 | self.coerce(&expected.ty, &else_ty); | 1034 | self.coerce_merge_branch(&then_ty, &else_ty) |
991 | else_ty.clone() | ||
992 | } else { | ||
993 | expected.ty.clone() | ||
994 | } | ||
995 | } | 1035 | } |
996 | Expr::Block { statements, tail } => self.infer_block(statements, *tail, expected), | 1036 | Expr::Block { statements, tail } => self.infer_block(statements, *tail, expected), |
997 | Expr::TryBlock { body } => { | 1037 | Expr::TryBlock { body } => { |
@@ -1087,11 +1127,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1087 | .infer_method_call(tgt_expr, *receiver, &args, &method_name, generic_args.as_ref()), | 1127 | .infer_method_call(tgt_expr, *receiver, &args, &method_name, generic_args.as_ref()), |
1088 | Expr::Match { expr, arms } => { | 1128 | Expr::Match { expr, arms } => { |
1089 | let input_ty = self.infer_expr(*expr, &Expectation::none()); | 1129 | let input_ty = self.infer_expr(*expr, &Expectation::none()); |
1090 | let mut expected = match expected.ty { | 1130 | |
1091 | Ty::Unknown => Expectation::has_type(Ty::simple(TypeCtor::Never)), | 1131 | let mut result_ty = self.new_maybe_never_type_var(); |
1092 | _ => expected.clone(), | ||
1093 | }; | ||
1094 | let mut all_never = true; | ||
1095 | 1132 | ||
1096 | for arm in arms { | 1133 | for arm in arms { |
1097 | for &pat in &arm.pats { | 1134 | for &pat in &arm.pats { |
@@ -1103,22 +1140,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1103 | &Expectation::has_type(Ty::simple(TypeCtor::Bool)), | 1140 | &Expectation::has_type(Ty::simple(TypeCtor::Bool)), |
1104 | ); | 1141 | ); |
1105 | } | 1142 | } |
1143 | |||
1106 | let arm_ty = self.infer_expr_inner(arm.expr, &expected); | 1144 | let arm_ty = self.infer_expr_inner(arm.expr, &expected); |
1107 | match &arm_ty { | 1145 | result_ty = self.coerce_merge_branch(&result_ty, &arm_ty); |
1108 | ty_app!(TypeCtor::Never) => (), | ||
1109 | _ => all_never = false, | ||
1110 | } | ||
1111 | if !self.coerce(&arm_ty, &expected.ty) { | ||
1112 | self.coerce(&expected.ty, &arm_ty); | ||
1113 | expected = Expectation::has_type(arm_ty); | ||
1114 | } | ||
1115 | } | 1146 | } |
1116 | 1147 | ||
1117 | if all_never { | 1148 | result_ty |
1118 | Ty::simple(TypeCtor::Never) | ||
1119 | } else { | ||
1120 | expected.ty | ||
1121 | } | ||
1122 | } | 1149 | } |
1123 | Expr::Path(p) => { | 1150 | Expr::Path(p) => { |
1124 | // FIXME this could be more efficient... | 1151 | // FIXME this could be more efficient... |
@@ -1558,12 +1585,16 @@ pub enum InferTy { | |||
1558 | TypeVar(TypeVarId), | 1585 | TypeVar(TypeVarId), |
1559 | IntVar(TypeVarId), | 1586 | IntVar(TypeVarId), |
1560 | FloatVar(TypeVarId), | 1587 | FloatVar(TypeVarId), |
1588 | MaybeNeverTypeVar(TypeVarId), | ||
1561 | } | 1589 | } |
1562 | 1590 | ||
1563 | impl InferTy { | 1591 | impl InferTy { |
1564 | fn to_inner(self) -> TypeVarId { | 1592 | fn to_inner(self) -> TypeVarId { |
1565 | match self { | 1593 | match self { |
1566 | InferTy::TypeVar(ty) | InferTy::IntVar(ty) | InferTy::FloatVar(ty) => ty, | 1594 | InferTy::TypeVar(ty) |
1595 | | InferTy::IntVar(ty) | ||
1596 | | InferTy::FloatVar(ty) | ||
1597 | | InferTy::MaybeNeverTypeVar(ty) => ty, | ||
1567 | } | 1598 | } |
1568 | } | 1599 | } |
1569 | 1600 | ||
@@ -1576,6 +1607,7 @@ impl InferTy { | |||
1576 | InferTy::FloatVar(..) => Ty::simple(TypeCtor::Float( | 1607 | InferTy::FloatVar(..) => Ty::simple(TypeCtor::Float( |
1577 | primitive::UncertainFloatTy::Known(primitive::FloatTy::f64()), | 1608 | primitive::UncertainFloatTy::Known(primitive::FloatTy::f64()), |
1578 | )), | 1609 | )), |
1610 | InferTy::MaybeNeverTypeVar(..) => Ty::simple(TypeCtor::Never), | ||
1579 | } | 1611 | } |
1580 | } | 1612 | } |
1581 | } | 1613 | } |