mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-30 13:51:31 +00:00
Handle divergence in type inference for blocks
This commit is contained in:
parent
31f22d8549
commit
f491567fb3
2 changed files with 72 additions and 3 deletions
|
@ -1602,6 +1602,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||||
tail: Option<ExprId>,
|
tail: Option<ExprId>,
|
||||||
expected: &Expectation,
|
expected: &Expectation,
|
||||||
) -> Ty {
|
) -> Ty {
|
||||||
|
let mut diverges = false;
|
||||||
for stmt in statements {
|
for stmt in statements {
|
||||||
match stmt {
|
match stmt {
|
||||||
Statement::Let { pat, type_ref, initializer } => {
|
Statement::Let { pat, type_ref, initializer } => {
|
||||||
|
@ -1623,16 +1624,23 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||||
self.infer_pat(*pat, &ty, BindingMode::default());
|
self.infer_pat(*pat, &ty, BindingMode::default());
|
||||||
}
|
}
|
||||||
Statement::Expr(expr) => {
|
Statement::Expr(expr) => {
|
||||||
self.infer_expr(*expr, &Expectation::none());
|
if let ty_app!(TypeCtor::Never) = self.infer_expr(*expr, &Expectation::none()) {
|
||||||
|
diverges = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(expr) = tail {
|
let ty = if let Some(expr) = tail {
|
||||||
self.infer_expr_coerce(expr, expected)
|
self.infer_expr_coerce(expr, expected)
|
||||||
} else {
|
} else {
|
||||||
self.coerce(&Ty::unit(), &expected.ty);
|
self.coerce(&Ty::unit(), &expected.ty);
|
||||||
Ty::unit()
|
Ty::unit()
|
||||||
|
};
|
||||||
|
if diverges {
|
||||||
|
Ty::simple(TypeCtor::Never)
|
||||||
|
} else {
|
||||||
|
ty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -218,7 +218,7 @@ fn test(a: u32, b: isize, c: !, d: &str) {
|
||||||
[17; 18) 'b': isize
|
[17; 18) 'b': isize
|
||||||
[27; 28) 'c': !
|
[27; 28) 'c': !
|
||||||
[33; 34) 'd': &str
|
[33; 34) 'd': &str
|
||||||
[42; 121) '{ ...f32; }': ()
|
[42; 121) '{ ...f32; }': !
|
||||||
[48; 49) 'a': u32
|
[48; 49) 'a': u32
|
||||||
[55; 56) 'b': isize
|
[55; 56) 'b': isize
|
||||||
[62; 63) 'c': !
|
[62; 63) 'c': !
|
||||||
|
@ -980,6 +980,67 @@ fn main(foo: Foo) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn infer_if_match_with_return() {
|
||||||
|
assert_snapshot!(
|
||||||
|
infer(r#"
|
||||||
|
fn foo() {
|
||||||
|
let _x1 = if true {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let _x2 = if true {
|
||||||
|
2
|
||||||
|
} else {
|
||||||
|
return
|
||||||
|
};
|
||||||
|
let _x3 = match true {
|
||||||
|
true => 3,
|
||||||
|
_ => {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let _x4 = match true {
|
||||||
|
true => 4,
|
||||||
|
_ => return
|
||||||
|
};
|
||||||
|
}"#),
|
||||||
|
@r###"
|
||||||
|
[10; 323) '{ ... }; }': ()
|
||||||
|
[20; 23) '_x1': i32
|
||||||
|
[26; 80) 'if tru... }': i32
|
||||||
|
[29; 33) 'true': bool
|
||||||
|
[34; 51) '{ ... }': i32
|
||||||
|
[44; 45) '1': i32
|
||||||
|
[57; 80) '{ ... }': !
|
||||||
|
[67; 73) 'return': !
|
||||||
|
[90; 93) '_x2': i32
|
||||||
|
[96; 149) 'if tru... }': i32
|
||||||
|
[99; 103) 'true': bool
|
||||||
|
[104; 121) '{ ... }': i32
|
||||||
|
[114; 115) '2': i32
|
||||||
|
[127; 149) '{ ... }': !
|
||||||
|
[137; 143) 'return': !
|
||||||
|
[159; 162) '_x3': i32
|
||||||
|
[165; 247) 'match ... }': i32
|
||||||
|
[171; 175) 'true': bool
|
||||||
|
[186; 190) 'true': bool
|
||||||
|
[194; 195) '3': i32
|
||||||
|
[205; 206) '_': bool
|
||||||
|
[210; 241) '{ ... }': !
|
||||||
|
[224; 230) 'return': !
|
||||||
|
[257; 260) '_x4': i32
|
||||||
|
[263; 320) 'match ... }': i32
|
||||||
|
[269; 273) 'true': bool
|
||||||
|
[284; 288) 'true': bool
|
||||||
|
[292; 293) '4': i32
|
||||||
|
[303; 304) '_': bool
|
||||||
|
[308; 314) 'return': !
|
||||||
|
"###
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn infer_inherent_method() {
|
fn infer_inherent_method() {
|
||||||
assert_snapshot!(
|
assert_snapshot!(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue