11844: Fix divergence detection for bare match arms r=flodiebold a=flodiebold

Fixes #11814 and #11837.

Co-authored-by: Florian Diebold <flodiebold@gmail.com>
This commit is contained in:
bors[bot] 2022-03-29 19:58:14 +00:00 committed by GitHub
commit 63c4d6b20d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 47 additions and 5 deletions

View file

@ -45,10 +45,6 @@ use super::{
impl<'a> InferenceContext<'a> { impl<'a> InferenceContext<'a> {
pub(crate) fn infer_expr(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { pub(crate) fn infer_expr(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
let ty = self.infer_expr_inner(tgt_expr, expected); let ty = self.infer_expr_inner(tgt_expr, expected);
if self.resolve_ty_shallow(&ty).is_never() {
// Any expression that produces a value of type `!` must have diverged
self.diverges = Diverges::Always;
}
if let Some(expected_ty) = expected.only_has_type(&mut self.table) { if let Some(expected_ty) = expected.only_has_type(&mut self.table) {
let could_unify = self.unify(&ty, &expected_ty); let could_unify = self.unify(&ty, &expected_ty);
if !could_unify { if !could_unify {
@ -800,6 +796,10 @@ impl<'a> InferenceContext<'a> {
// use a new type variable if we got unknown here // use a new type variable if we got unknown here
let ty = self.insert_type_vars_shallow(ty); let ty = self.insert_type_vars_shallow(ty);
self.write_expr_ty(tgt_expr, ty.clone()); self.write_expr_ty(tgt_expr, ty.clone());
if self.resolve_ty_shallow(&ty).is_never() {
// Any expression that produces a value of type `!` must have diverged
self.diverges = Diverges::Always;
}
ty ty
} }

View file

@ -1,6 +1,6 @@
use expect_test::expect; use expect_test::expect;
use super::{check_infer_with_mismatches, check_types}; use super::{check_infer_with_mismatches, check_no_mismatches, check_types};
#[test] #[test]
fn infer_never1() { fn infer_never1() {
@ -441,3 +441,45 @@ fn let_else_must_diverge() {
"#]], "#]],
); );
} }
#[test]
fn issue_11837() {
check_no_mismatches(
r#"
//- minicore: result
enum MyErr {
Err1,
Err2,
}
fn example_ng() {
let value: Result<i32, MyErr> = Ok(3);
loop {
let ret = match value {
Ok(value) => value,
Err(ref err) => {
match err {
MyErr::Err1 => break,
MyErr::Err2 => continue,
};
}
};
}
}
"#,
);
}
#[test]
fn issue_11814() {
check_no_mismatches(
r#"
fn example() -> bool {
match 1 {
_ => return true,
};
}
"#,
);
}