diff options
-rw-r--r-- | crates/ra_hir/src/marks.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 13 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 42 |
3 files changed, 53 insertions, 4 deletions
diff --git a/crates/ra_hir/src/marks.rs b/crates/ra_hir/src/marks.rs index 3795debc1..1adf5cd53 100644 --- a/crates/ra_hir/src/marks.rs +++ b/crates/ra_hir/src/marks.rs | |||
@@ -16,4 +16,6 @@ test_utils::marks!( | |||
16 | match_second_arm_never | 16 | match_second_arm_never |
17 | match_all_arms_never | 17 | match_all_arms_never |
18 | match_no_never_arms | 18 | match_no_never_arms |
19 | if_never | ||
20 | if_else_never | ||
19 | ); | 21 | ); |
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index b310bf6bd..d01063766 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs | |||
@@ -987,14 +987,21 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
987 | let then_ty = self.infer_expr(*then_branch, expected); | 987 | let then_ty = self.infer_expr(*then_branch, expected); |
988 | match else_branch { | 988 | match else_branch { |
989 | Some(else_branch) => { | 989 | Some(else_branch) => { |
990 | self.infer_expr(*else_branch, expected); | 990 | let else_ty = self.infer_expr(*else_branch, expected); |
991 | if Self::is_never(&then_ty) { | ||
992 | tested_by!(if_never); | ||
993 | else_ty | ||
994 | } else { | ||
995 | tested_by!(if_else_never); | ||
996 | then_ty | ||
997 | } | ||
991 | } | 998 | } |
992 | None => { | 999 | None => { |
993 | // no else branch -> unit | 1000 | // no else branch -> unit |
994 | self.unify(&then_ty, &Ty::unit()); // actually coerce | 1001 | self.unify(&then_ty, &Ty::unit()); // actually coerce |
1002 | then_ty | ||
995 | } | 1003 | } |
996 | }; | 1004 | } |
997 | then_ty | ||
998 | } | 1005 | } |
999 | Expr::Block { statements, tail } => self.infer_block(statements, *tail, expected), | 1006 | Expr::Block { statements, tail } => self.infer_block(statements, *tail, expected), |
1000 | Expr::TryBlock { body } => { | 1007 | Expr::TryBlock { body } => { |
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index 7ec834836..94b0fe3b3 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs | |||
@@ -3595,7 +3595,7 @@ fn no_such_field_diagnostics() { | |||
3595 | ); | 3595 | ); |
3596 | } | 3596 | } |
3597 | 3597 | ||
3598 | mod match_with_never_tests { | 3598 | mod branching_with_never_tests { |
3599 | use super::type_at; | 3599 | use super::type_at; |
3600 | use test_utils::covers; | 3600 | use test_utils::covers; |
3601 | 3601 | ||
@@ -3645,6 +3645,46 @@ fn test(a: i32) { | |||
3645 | } | 3645 | } |
3646 | 3646 | ||
3647 | #[test] | 3647 | #[test] |
3648 | fn if_never() { | ||
3649 | covers!(if_never); | ||
3650 | let t = type_at( | ||
3651 | r#" | ||
3652 | //- /main.rs | ||
3653 | fn test() { | ||
3654 | let i = if true { | ||
3655 | loop {} | ||
3656 | } else { | ||
3657 | 3.0 | ||
3658 | }; | ||
3659 | i<|> | ||
3660 | () | ||
3661 | } | ||
3662 | "#, | ||
3663 | ); | ||
3664 | assert_eq!(t, "f64"); | ||
3665 | } | ||
3666 | |||
3667 | #[test] | ||
3668 | fn if_else_never() { | ||
3669 | covers!(if_else_never); | ||
3670 | let t = type_at( | ||
3671 | r#" | ||
3672 | //- /main.rs | ||
3673 | fn test(input: bool) { | ||
3674 | let i = if input { | ||
3675 | 2.0 | ||
3676 | } else { | ||
3677 | return | ||
3678 | }; | ||
3679 | i<|> | ||
3680 | () | ||
3681 | } | ||
3682 | "#, | ||
3683 | ); | ||
3684 | assert_eq!(t, "f64"); | ||
3685 | } | ||
3686 | |||
3687 | #[test] | ||
3648 | fn match_second_arm_never() { | 3688 | fn match_second_arm_never() { |
3649 | covers!(match_second_arm_never); | 3689 | covers!(match_second_arm_never); |
3650 | let t = type_at( | 3690 | let t = type_at( |