mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-13 21:54:42 +00:00
Auto merge of #17174 - Kohei316:fix-infer-async-block-with-tail-return-expr, r=Veykril
Fix: infer type of async block with tail return expr
Fixes #17106
The `infer_async_block` method calls the `infer_block` method internally, which returns the never type without coercion when `tail_expr` is `None` and `ctx.diverges` is `Diverges::Always`.This is the reason for the bug in this issue.
cfce2bb46d/crates/hir-ty/src/infer/expr.rs (L1411-L1413)
This PR solves the bug by adding a process to coerce after calling `infer_block` method.
This code passes all the tests, including tests I added for this isuue, however, I am not sure if this solution is right. I think that this solution is an ad hoc solution. So, I would appreciate to have your review.
I apologize if I'm off the mark, but `infer_async_block` method should be rewritten to share code with the process of infering type of `expr::Closure` instead of the `infer_block` method. That way it will be closer to the infer process of rustc.
This commit is contained in:
commit
dec43b6cb3
2 changed files with 43 additions and 1 deletions
|
@ -933,8 +933,24 @@ impl InferenceContext<'_> {
|
|||
let prev_ret_coercion =
|
||||
mem::replace(&mut self.return_coercion, Some(CoerceMany::new(ret_ty.clone())));
|
||||
|
||||
// FIXME: We should handle async blocks like we handle closures
|
||||
let expected = &Expectation::has_type(ret_ty);
|
||||
let (_, inner_ty) = self.with_breakable_ctx(BreakableKind::Border, None, None, |this| {
|
||||
this.infer_block(tgt_expr, *id, statements, *tail, None, &Expectation::has_type(ret_ty))
|
||||
let ty = this.infer_block(tgt_expr, *id, statements, *tail, None, expected);
|
||||
if let Some(target) = expected.only_has_type(&mut this.table) {
|
||||
match this.coerce(Some(tgt_expr), &ty, &target) {
|
||||
Ok(res) => res,
|
||||
Err(_) => {
|
||||
this.result.type_mismatches.insert(
|
||||
tgt_expr.into(),
|
||||
TypeMismatch { expected: target.clone(), actual: ty.clone() },
|
||||
);
|
||||
target
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ty
|
||||
}
|
||||
});
|
||||
|
||||
self.diverges = prev_diverges;
|
||||
|
|
|
@ -1120,4 +1120,30 @@ fn test() {
|
|||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn type_hints_async_block() {
|
||||
check_types(
|
||||
r#"
|
||||
//- minicore: future
|
||||
async fn main() {
|
||||
let _x = async { 8_i32 };
|
||||
//^^ impl Future<Output = i32>
|
||||
}"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn type_hints_async_block_with_tail_return_exp() {
|
||||
check_types(
|
||||
r#"
|
||||
//- minicore: future
|
||||
async fn main() {
|
||||
let _x = async {
|
||||
//^^ impl Future<Output = i32>
|
||||
return 8_i32;
|
||||
};
|
||||
}"#,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue