mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-26 04:53:34 +00:00
Merge #11844
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:
commit
63c4d6b20d
2 changed files with 47 additions and 5 deletions
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue