Skip to content

Commit b8e1d09

Browse files
bors[bot]Veykril
andauthored
Merge #11806
11806: fix: Fix async block type inference using containing function return type r=Veykril a=Veykril Fixes #11804 Should fix #11798 (comment) Co-authored-by: Lukas Wirth <[email protected]>
2 parents 15fdb95 + ed0c625 commit b8e1d09

File tree

3 files changed

+56
-2
lines changed

3 files changed

+56
-2
lines changed

crates/hir_ty/src/infer.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,7 @@ pub(crate) struct InferenceContext<'a> {
364364
table: unify::InferenceTable<'a>,
365365
trait_env: Arc<TraitEnvironment>,
366366
result: InferenceResult,
367-
/// The return type of the function being inferred, or the closure if we're
367+
/// The return type of the function being inferred, the closure or async block if we're
368368
/// currently within one.
369369
///
370370
/// We might consider using a nested inference context for checking

crates/hir_ty/src/infer/expr.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,9 +157,17 @@ impl<'a> InferenceContext<'a> {
157157
self.err_ty()
158158
}
159159
Expr::Async { body } => {
160+
let ret_ty = self.table.new_type_var();
161+
let prev_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
162+
let prev_ret_ty = mem::replace(&mut self.return_ty, ret_ty.clone());
163+
164+
let inner_ty = self.infer_expr_coerce(*body, &Expectation::has_type(ret_ty));
165+
166+
self.diverges = prev_diverges;
167+
self.return_ty = prev_ret_ty;
168+
160169
// Use the first type parameter as the output type of future.
161170
// existential type AsyncBlockImplTrait<InnerType>: Future<Output = InnerType>
162-
let inner_ty = self.infer_expr(*body, &Expectation::none());
163171
let impl_trait_id = crate::ImplTraitId::AsyncBlockTypeImplTrait(self.owner, *body);
164172
let opaque_ty_id = self.db.intern_impl_trait_id(impl_trait_id).into();
165173
TyKind::OpaqueType(opaque_ty_id, Substitution::from1(Interner, inner_ty))

crates/hir_ty/src/tests/simple.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1952,6 +1952,52 @@ async fn main() {
19521952
"#]],
19531953
)
19541954
}
1955+
#[test]
1956+
fn async_block_early_return() {
1957+
check_infer(
1958+
r#"
1959+
//- minicore: future, result, fn
1960+
fn test<I, E, F: FnMut() -> Fut, Fut: core::future::Future<Output = Result<I, E>>>(f: F) {}
1961+
1962+
fn main() {
1963+
async {
1964+
return Err(());
1965+
Ok(())
1966+
};
1967+
test(|| async {
1968+
return Err(());
1969+
Ok(())
1970+
});
1971+
}
1972+
"#,
1973+
expect![[r#"
1974+
83..84 'f': F
1975+
89..91 '{}': ()
1976+
103..231 '{ ... }); }': ()
1977+
109..161 'async ... }': Result<(), ()>
1978+
109..161 'async ... }': impl Future<Output = Result<(), ()>>
1979+
125..139 'return Err(())': !
1980+
132..135 'Err': Err<(), ()>(()) -> Result<(), ()>
1981+
132..139 'Err(())': Result<(), ()>
1982+
136..138 '()': ()
1983+
149..151 'Ok': Ok<(), ()>(()) -> Result<(), ()>
1984+
149..155 'Ok(())': Result<(), ()>
1985+
152..154 '()': ()
1986+
167..171 'test': fn test<(), (), || -> impl Future<Output = Result<(), ()>>, impl Future<Output = Result<(), ()>>>(|| -> impl Future<Output = Result<(), ()>>)
1987+
167..228 'test(|... })': ()
1988+
172..227 '|| asy... }': || -> impl Future<Output = Result<(), ()>>
1989+
175..227 'async ... }': Result<(), ()>
1990+
175..227 'async ... }': impl Future<Output = Result<(), ()>>
1991+
191..205 'return Err(())': !
1992+
198..201 'Err': Err<(), ()>(()) -> Result<(), ()>
1993+
198..205 'Err(())': Result<(), ()>
1994+
202..204 '()': ()
1995+
215..217 'Ok': Ok<(), ()>(()) -> Result<(), ()>
1996+
215..221 'Ok(())': Result<(), ()>
1997+
218..220 '()': ()
1998+
"#]],
1999+
)
2000+
}
19552001

19562002
#[test]
19572003
fn infer_generic_from_later_assignment() {

0 commit comments

Comments
 (0)