aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty/infer.rs
diff options
context:
space:
mode:
authoruHOOCCOOHu <[email protected]>2019-09-17 20:59:51 +0100
committeruHOOCCOOHu <[email protected]>2019-09-25 23:04:43 +0100
commitbf161fa3e58d57d9b15bd965405036d834f18595 (patch)
tree62f7103143462ed75544985b7c3ad0cb2ddda96b /crates/ra_hir/src/ty/infer.rs
parent4bb66df6de6a832f53f09128ea038fc1c0068515 (diff)
Better handle never type and branch merging
Split out tests for never type to another file
Diffstat (limited to 'crates/ra_hir/src/ty/infer.rs')
-rw-r--r--crates/ra_hir/src/ty/infer.rs152
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
1563impl InferTy { 1591impl 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}