aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir/src/marks.rs1
-rw-r--r--crates/ra_hir/src/ty/infer.rs152
-rw-r--r--crates/ra_hir/src/ty/infer/unify.rs1
-rw-r--r--crates/ra_hir/src/ty/tests.rs161
-rw-r--r--crates/ra_hir/src/ty/tests/never_type.rs258
5 files changed, 392 insertions, 181 deletions
diff --git a/crates/ra_hir/src/marks.rs b/crates/ra_hir/src/marks.rs
index fe119b97c..b2111be05 100644
--- a/crates/ra_hir/src/marks.rs
+++ b/crates/ra_hir/src/marks.rs
@@ -13,4 +13,5 @@ test_utils::marks!(
13 infer_while_let 13 infer_while_let
14 macro_rules_from_other_crates_are_visible_with_macro_use 14 macro_rules_from_other_crates_are_visible_with_macro_use
15 prelude_is_macro_use 15 prelude_is_macro_use
16 coerce_merge_fail_fallback
16); 17);
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}
diff --git a/crates/ra_hir/src/ty/infer/unify.rs b/crates/ra_hir/src/ty/infer/unify.rs
index 9a0d2d8f9..b6ebee3b1 100644
--- a/crates/ra_hir/src/ty/infer/unify.rs
+++ b/crates/ra_hir/src/ty/infer/unify.rs
@@ -63,6 +63,7 @@ where
63 InferTy::TypeVar(_) => InferTy::TypeVar(root), 63 InferTy::TypeVar(_) => InferTy::TypeVar(root),
64 InferTy::IntVar(_) => InferTy::IntVar(root), 64 InferTy::IntVar(_) => InferTy::IntVar(root),
65 InferTy::FloatVar(_) => InferTy::FloatVar(root), 65 InferTy::FloatVar(_) => InferTy::FloatVar(root),
66 InferTy::MaybeNeverTypeVar(_) => InferTy::MaybeNeverTypeVar(root),
66 }; 67 };
67 let position = self.add(free_var); 68 let position = self.add(free_var);
68 Ty::Bound(position as u32) 69 Ty::Bound(position as u32)
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index 2ce0039b1..081bfe37c 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -20,6 +20,8 @@ use crate::{
20// against snapshots of the expected results using insta. Use cargo-insta to 20// against snapshots of the expected results using insta. Use cargo-insta to
21// update the snapshots. 21// update the snapshots.
22 22
23mod never_type;
24
23#[test] 25#[test]
24fn infer_await() { 26fn infer_await() {
25 let (mut db, pos) = MockDatabase::with_position( 27 let (mut db, pos) = MockDatabase::with_position(
@@ -1078,6 +1080,42 @@ fn test(i: i32) {
1078} 1080}
1079 1081
1080#[test] 1082#[test]
1083fn coerce_merge_one_by_one1() {
1084 covers!(coerce_merge_fail_fallback);
1085
1086 assert_snapshot!(
1087 infer(r#"
1088fn test() {
1089 let t = &mut 1;
1090 let x = match 1 {
1091 1 => t as *mut i32,
1092 2 => t as &i32,
1093 _ => t as *const i32,
1094 };
1095}
1096"#),
1097 @r###"
1098 [11; 145) '{ ... }; }': ()
1099 [21; 22) 't': &mut i32
1100 [25; 31) '&mut 1': &mut i32
1101 [30; 31) '1': i32
1102 [41; 42) 'x': *const i32
1103 [45; 142) 'match ... }': *const i32
1104 [51; 52) '1': i32
1105 [63; 64) '1': i32
1106 [68; 69) 't': &mut i32
1107 [68; 81) 't as *mut i32': *mut i32
1108 [91; 92) '2': i32
1109 [96; 97) 't': &mut i32
1110 [96; 105) 't as &i32': &i32
1111 [115; 116) '_': i32
1112 [120; 121) 't': &mut i32
1113 [120; 135) 't as *const i32': *const i32
1114 "###
1115 );
1116}
1117
1118#[test]
1081fn bug_484() { 1119fn bug_484() {
1082 assert_snapshot!( 1120 assert_snapshot!(
1083 infer(r#" 1121 infer(r#"
@@ -2458,7 +2496,6 @@ fn extra_compiler_flags() {
2458} 2496}
2459"#), 2497"#),
2460 @r###" 2498 @r###"
2461
2462 [27; 323) '{ ... } }': () 2499 [27; 323) '{ ... } }': ()
2463 [33; 321) 'for co... }': () 2500 [33; 321) 'for co... }': ()
2464 [37; 44) 'content': &{unknown} 2501 [37; 44) 'content': &{unknown}
@@ -2472,8 +2509,8 @@ fn extra_compiler_flags() {
2472 [135; 167) '{ ... }': &&{unknown} 2509 [135; 167) '{ ... }': &&{unknown}
2473 [149; 157) '&content': &&{unknown} 2510 [149; 157) '&content': &&{unknown}
2474 [150; 157) 'content': &{unknown} 2511 [150; 157) 'content': &{unknown}
2475 [182; 189) 'content': &&{unknown} 2512 [182; 189) 'content': &{unknown}
2476 [192; 314) 'if ICE... }': &&{unknown} 2513 [192; 314) 'if ICE... }': &{unknown}
2477 [195; 232) 'ICE_RE..._VALUE': {unknown} 2514 [195; 232) 'ICE_RE..._VALUE': {unknown}
2478 [195; 248) 'ICE_RE...&name)': bool 2515 [195; 248) 'ICE_RE...&name)': bool
2479 [242; 247) '&name': &&&{unknown} 2516 [242; 247) '&name': &&&{unknown}
@@ -4683,121 +4720,3 @@ fn no_such_field_diagnostics() {
4683 "### 4720 "###
4684 ); 4721 );
4685} 4722}
4686
4687mod branching_with_never_tests {
4688 use super::type_at;
4689
4690 #[test]
4691 fn if_never() {
4692 let t = type_at(
4693 r#"
4694//- /main.rs
4695fn test() {
4696 let i = if true {
4697 loop {}
4698 } else {
4699 3.0
4700 };
4701 i<|>
4702 ()
4703}
4704"#,
4705 );
4706 assert_eq!(t, "f64");
4707 }
4708
4709 #[test]
4710 fn if_else_never() {
4711 let t = type_at(
4712 r#"
4713//- /main.rs
4714fn test(input: bool) {
4715 let i = if input {
4716 2.0
4717 } else {
4718 return
4719 };
4720 i<|>
4721 ()
4722}
4723"#,
4724 );
4725 assert_eq!(t, "f64");
4726 }
4727
4728 #[test]
4729 fn match_first_arm_never() {
4730 let t = type_at(
4731 r#"
4732//- /main.rs
4733fn test(a: i32) {
4734 let i = match a {
4735 1 => return,
4736 2 => 2.0,
4737 3 => loop {},
4738 _ => 3.0,
4739 };
4740 i<|>
4741 ()
4742}
4743"#,
4744 );
4745 assert_eq!(t, "f64");
4746 }
4747
4748 #[test]
4749 fn match_second_arm_never() {
4750 let t = type_at(
4751 r#"
4752//- /main.rs
4753fn test(a: i32) {
4754 let i = match a {
4755 1 => 3.0,
4756 2 => loop {},
4757 3 => 3.0,
4758 _ => return,
4759 };
4760 i<|>
4761 ()
4762}
4763"#,
4764 );
4765 assert_eq!(t, "f64");
4766 }
4767
4768 #[test]
4769 fn match_all_arms_never() {
4770 let t = type_at(
4771 r#"
4772//- /main.rs
4773fn test(a: i32) {
4774 let i = match a {
4775 2 => return,
4776 _ => loop {},
4777 };
4778 i<|>
4779 ()
4780}
4781"#,
4782 );
4783 assert_eq!(t, "!");
4784 }
4785
4786 #[test]
4787 fn match_no_never_arms() {
4788 let t = type_at(
4789 r#"
4790//- /main.rs
4791fn test(a: i32) {
4792 let i = match a {
4793 2 => 2.0,
4794 _ => 3.0,
4795 };
4796 i<|>
4797 ()
4798}
4799"#,
4800 );
4801 assert_eq!(t, "f64");
4802 }
4803}
diff --git a/crates/ra_hir/src/ty/tests/never_type.rs b/crates/ra_hir/src/ty/tests/never_type.rs
new file mode 100644
index 000000000..b9af918e9
--- /dev/null
+++ b/crates/ra_hir/src/ty/tests/never_type.rs
@@ -0,0 +1,258 @@
1use super::type_at;
2
3#[test]
4fn infer_never1() {
5 let t = type_at(
6 r#"
7//- /main.rs
8fn test() {
9 let t = return;
10 t<|>;
11}
12"#,
13 );
14 assert_eq!(t, "!");
15}
16
17#[test]
18fn infer_never2() {
19 let t = type_at(
20 r#"
21//- /main.rs
22trait Foo { fn gen() -> Self; }
23impl Foo for ! { fn gen() -> Self { loop {} } }
24impl Foo for () { fn gen() -> Self { loop {} } }
25
26fn test() {
27 let a = Foo::gen();
28 if false { a } else { loop {} };
29 a<|>;
30}
31"#,
32 );
33 assert_eq!(t, "!");
34}
35
36#[test]
37fn infer_never3() {
38 let t = type_at(
39 r#"
40//- /main.rs
41trait Foo { fn gen() -> Self; }
42impl Foo for ! { fn gen() -> Self { loop {} } }
43impl Foo for () { fn gen() -> Self { loop {} } }
44
45fn test() {
46 let a = Foo::gen();
47 if false { loop {} } else { a };
48 a<|>;
49}
50"#,
51 );
52 assert_eq!(t, "!");
53}
54
55#[test]
56fn never_type_in_generic_args() {
57 let t = type_at(
58 r#"
59//- /main.rs
60enum Option<T> { None, Some(T) }
61
62fn test() {
63 let a = if true { Option::None } else { Option::Some(return) };
64 a<|>;
65}
66"#,
67 );
68 assert_eq!(t, "Option<!>");
69}
70
71#[test]
72fn never_type_can_be_reinferred1() {
73 let t = type_at(
74 r#"
75//- /main.rs
76trait Foo { fn gen() -> Self; }
77impl Foo for ! { fn gen() -> Self { loop {} } }
78impl Foo for () { fn gen() -> Self { loop {} } }
79
80fn test() {
81 let a = Foo::gen();
82 if false { loop {} } else { a };
83 a<|>;
84 if false { a };
85}
86"#,
87 );
88 assert_eq!(t, "()");
89}
90
91#[test]
92fn never_type_can_be_reinferred2() {
93 let t = type_at(
94 r#"
95//- /main.rs
96enum Option<T> { None, Some(T) }
97
98fn test() {
99 let a = if true { Option::None } else { Option::Some(return) };
100 a<|>;
101 match 42 {
102 42 => a,
103 _ => Option::Some(42),
104 };
105}
106"#,
107 );
108 assert_eq!(t, "Option<i32>");
109}
110#[test]
111fn never_type_can_be_reinferred3() {
112 let t = type_at(
113 r#"
114//- /main.rs
115enum Option<T> { None, Some(T) }
116
117fn test() {
118 let a = if true { Option::None } else { Option::Some(return) };
119 a<|>;
120 match 42 {
121 42 => a,
122 _ => Option::Some("str"),
123 };
124}
125"#,
126 );
127 assert_eq!(t, "Option<&str>");
128}
129
130#[test]
131fn match_no_arm() {
132 let t = type_at(
133 r#"
134//- /main.rs
135enum Void {}
136
137fn test(a: Void) {
138 let t = match a {};
139 t<|>;
140}
141"#,
142 );
143 assert_eq!(t, "!");
144}
145
146#[test]
147fn if_never() {
148 let t = type_at(
149 r#"
150//- /main.rs
151fn test() {
152 let i = if true {
153 loop {}
154 } else {
155 3.0
156 };
157 i<|>
158 ()
159}
160"#,
161 );
162 assert_eq!(t, "f64");
163}
164
165#[test]
166fn if_else_never() {
167 let t = type_at(
168 r#"
169//- /main.rs
170fn test(input: bool) {
171 let i = if input {
172 2.0
173 } else {
174 return
175 };
176 i<|>
177 ()
178}
179"#,
180 );
181 assert_eq!(t, "f64");
182}
183
184#[test]
185fn match_first_arm_never() {
186 let t = type_at(
187 r#"
188//- /main.rs
189fn test(a: i32) {
190 let i = match a {
191 1 => return,
192 2 => 2.0,
193 3 => loop {},
194 _ => 3.0,
195 };
196 i<|>
197 ()
198}
199"#,
200 );
201 assert_eq!(t, "f64");
202}
203
204#[test]
205fn match_second_arm_never() {
206 let t = type_at(
207 r#"
208//- /main.rs
209fn test(a: i32) {
210 let i = match a {
211 1 => 3.0,
212 2 => loop {},
213 3 => 3.0,
214 _ => return,
215 };
216 i<|>
217 ()
218}
219"#,
220 );
221 assert_eq!(t, "f64");
222}
223
224#[test]
225fn match_all_arms_never() {
226 let t = type_at(
227 r#"
228//- /main.rs
229fn test(a: i32) {
230 let i = match a {
231 2 => return,
232 _ => loop {},
233 };
234 i<|>
235 ()
236}
237"#,
238 );
239 assert_eq!(t, "!");
240}
241
242#[test]
243fn match_no_never_arms() {
244 let t = type_at(
245 r#"
246//- /main.rs
247fn test(a: i32) {
248 let i = match a {
249 2 => 2.0,
250 _ => 3.0,
251 };
252 i<|>
253 ()
254}
255"#,
256 );
257 assert_eq!(t, "f64");
258}