From ea1d0bccef335ed55ddc7af1312074990249eb77 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Tue, 29 Mar 2022 21:55:34 +0200 Subject: [PATCH] Fix divergence detection for bare match arms Fixes #11814 and #11837. --- crates/hir_ty/src/infer/expr.rs | 8 ++--- crates/hir_ty/src/tests/never_type.rs | 44 ++++++++++++++++++++++++++- 2 files changed, 47 insertions(+), 5 deletions(-) diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index 0b67f2c32e..01022f20bd 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs @@ -45,10 +45,6 @@ use super::{ impl<'a> InferenceContext<'a> { pub(crate) fn infer_expr(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { 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) { let could_unify = self.unify(&ty, &expected_ty); if !could_unify { @@ -800,6 +796,10 @@ impl<'a> InferenceContext<'a> { // use a new type variable if we got unknown here let ty = self.insert_type_vars_shallow(ty); 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 } diff --git a/crates/hir_ty/src/tests/never_type.rs b/crates/hir_ty/src/tests/never_type.rs index 3ca0a5b391..fbdc8209f8 100644 --- a/crates/hir_ty/src/tests/never_type.rs +++ b/crates/hir_ty/src/tests/never_type.rs @@ -1,6 +1,6 @@ use expect_test::expect; -use super::{check_infer_with_mismatches, check_types}; +use super::{check_infer_with_mismatches, check_no_mismatches, check_types}; #[test] 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 = 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, + }; +} +"#, + ); +}