Fix never in if expressions

This commit is contained in:
Kirill Bulatov 2019-08-14 22:20:18 +03:00
parent c1f47c3788
commit 44cf7b34fe
3 changed files with 53 additions and 4 deletions

View file

@ -16,4 +16,6 @@ test_utils::marks!(
match_second_arm_never
match_all_arms_never
match_no_never_arms
if_never
if_else_never
);

View file

@ -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 } => {

View file

@ -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);