From 44cf7b34fe1a486168590f7fead442f12602c419 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Wed, 14 Aug 2019 22:20:18 +0300 Subject: [PATCH] Fix never in if expressions --- crates/ra_hir/src/marks.rs | 2 ++ crates/ra_hir/src/ty/infer.rs | 13 ++++++++--- 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 3795debc1a..1adf5cd538 100644 --- a/crates/ra_hir/src/marks.rs +++ b/crates/ra_hir/src/marks.rs @@ -16,4 +16,6 @@ test_utils::marks!( match_second_arm_never match_all_arms_never match_no_never_arms + if_never + if_else_never ); diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index b310bf6bd6..d01063766e 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> { let then_ty = self.infer_expr(*then_branch, expected); match else_branch { Some(else_branch) => { - self.infer_expr(*else_branch, expected); + let else_ty = self.infer_expr(*else_branch, expected); + if Self::is_never(&then_ty) { + tested_by!(if_never); + else_ty + } else { + tested_by!(if_else_never); + then_ty + } } None => { // no else branch -> unit self.unify(&then_ty, &Ty::unit()); // actually coerce + then_ty } - }; - then_ty + } } Expr::Block { statements, tail } => self.infer_block(statements, *tail, expected), Expr::TryBlock { body } => { diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index 7ec834836c..94b0fe3b3a 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() { ); } -mod match_with_never_tests { +mod branching_with_never_tests { use super::type_at; use test_utils::covers; @@ -3644,6 +3644,46 @@ fn test(a: i32) { assert_eq!(t, "f64"); } + #[test] + fn if_never() { + covers!(if_never); + let t = type_at( + r#" +//- /main.rs +fn test() { + let i = if true { + loop {} + } else { + 3.0 + }; + i<|> + () +} +"#, + ); + assert_eq!(t, "f64"); + } + + #[test] + fn if_else_never() { + covers!(if_else_never); + let t = type_at( + r#" +//- /main.rs +fn test(input: bool) { + let i = if input { + 2.0 + } else { + return + }; + i<|> + () +} +"#, + ); + assert_eq!(t, "f64"); + } + #[test] fn match_second_arm_never() { covers!(match_second_arm_never);