Skip to content

Commit ffb04ae

Browse files
committed
Auto merge of rust-lang#14461 - HKalbasi:dev, r=Veykril
Use async block in async fn type inference fix rust-lang#14456 At some point we should probably go further and completely desugar async fn in hir lowering.
2 parents 853fb44 + 8a6ca86 commit ffb04ae

File tree

7 files changed

+68
-57
lines changed

7 files changed

+68
-57
lines changed

crates/hir-def/src/data.rs

-2
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ pub struct FunctionData {
3030
pub name: Name,
3131
pub params: Vec<(Option<Name>, Interned<TypeRef>)>,
3232
pub ret_type: Interned<TypeRef>,
33-
pub async_ret_type: Option<Interned<TypeRef>>,
3433
pub attrs: Attrs,
3534
pub visibility: RawVisibility,
3635
pub abi: Option<Interned<str>>,
@@ -104,7 +103,6 @@ impl FunctionData {
104103
})
105104
.collect(),
106105
ret_type: func.ret_type.clone(),
107-
async_ret_type: func.async_ret_type.clone(),
108106
attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()),
109107
visibility,
110108
abi: func.abi.clone(),

crates/hir-def/src/item_tree.rs

-1
Original file line numberDiff line numberDiff line change
@@ -608,7 +608,6 @@ pub struct Function {
608608
pub abi: Option<Interned<str>>,
609609
pub params: IdxRange<Param>,
610610
pub ret_type: Interned<TypeRef>,
611-
pub async_ret_type: Option<Interned<TypeRef>>,
612611
pub ast_id: FileAstId<ast::Fn>,
613612
pub(crate) flags: FnFlags,
614613
}

crates/hir-def/src/item_tree/lower.rs

+3-5
Original file line numberDiff line numberDiff line change
@@ -364,13 +364,12 @@ impl<'a> Ctx<'a> {
364364
None => TypeRef::unit(),
365365
};
366366

367-
let (ret_type, async_ret_type) = if func.async_token().is_some() {
368-
let async_ret_type = ret_type.clone();
367+
let ret_type = if func.async_token().is_some() {
369368
let future_impl = desugar_future_path(ret_type);
370369
let ty_bound = Interned::new(TypeBound::Path(future_impl, TraitBoundModifier::None));
371-
(TypeRef::ImplTrait(vec![ty_bound]), Some(async_ret_type))
370+
TypeRef::ImplTrait(vec![ty_bound])
372371
} else {
373-
(ret_type, None)
372+
ret_type
374373
};
375374

376375
let abi = func.abi().map(lower_abi);
@@ -404,7 +403,6 @@ impl<'a> Ctx<'a> {
404403
abi,
405404
params,
406405
ret_type: Interned::new(ret_type),
407-
async_ret_type: async_ret_type.map(Interned::new),
408406
ast_id,
409407
flags,
410408
};

crates/hir-def/src/item_tree/pretty.rs

-1
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,6 @@ impl<'a> Printer<'a> {
233233
abi,
234234
params,
235235
ret_type,
236-
async_ret_type: _,
237236
ast_id: _,
238237
flags,
239238
} = &self.tree[it];

crates/hir-ty/src/infer.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,7 @@ pub(crate) struct InferenceContext<'a> {
459459
resume_yield_tys: Option<(Ty, Ty)>,
460460
diverges: Diverges,
461461
breakables: Vec<BreakableContext>,
462+
is_async_fn: bool,
462463
}
463464

464465
#[derive(Clone, Debug)]
@@ -526,6 +527,7 @@ impl<'a> InferenceContext<'a> {
526527
resolver,
527528
diverges: Diverges::Maybe,
528529
breakables: Vec::new(),
530+
is_async_fn: false,
529531
}
530532
}
531533

@@ -636,12 +638,10 @@ impl<'a> InferenceContext<'a> {
636638

637639
self.infer_top_pat(*pat, &ty);
638640
}
639-
let error_ty = &TypeRef::Error;
640-
let return_ty = if data.has_async_kw() {
641-
data.async_ret_type.as_deref().unwrap_or(error_ty)
642-
} else {
643-
&*data.ret_type
644-
};
641+
let return_ty = &*data.ret_type;
642+
if data.has_async_kw() {
643+
self.is_async_fn = true;
644+
}
645645

646646
let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver)
647647
.with_impl_trait_mode(ImplTraitLoweringMode::Opaque);

crates/hir-ty/src/infer/expr.rs

+45-42
Original file line numberDiff line numberDiff line change
@@ -162,35 +162,7 @@ impl<'a> InferenceContext<'a> {
162162
.1
163163
}
164164
Expr::Async { id, statements, tail } => {
165-
let ret_ty = self.table.new_type_var();
166-
let prev_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
167-
let prev_ret_ty = mem::replace(&mut self.return_ty, ret_ty.clone());
168-
let prev_ret_coercion =
169-
mem::replace(&mut self.return_coercion, Some(CoerceMany::new(ret_ty.clone())));
170-
171-
let (_, inner_ty) =
172-
self.with_breakable_ctx(BreakableKind::Border, None, None, |this| {
173-
this.infer_block(
174-
tgt_expr,
175-
*id,
176-
statements,
177-
*tail,
178-
None,
179-
&Expectation::has_type(ret_ty),
180-
)
181-
});
182-
183-
self.diverges = prev_diverges;
184-
self.return_ty = prev_ret_ty;
185-
self.return_coercion = prev_ret_coercion;
186-
187-
// Use the first type parameter as the output type of future.
188-
// existential type AsyncBlockImplTrait<InnerType>: Future<Output = InnerType>
189-
let impl_trait_id =
190-
crate::ImplTraitId::AsyncBlockTypeImplTrait(self.owner, tgt_expr);
191-
let opaque_ty_id = self.db.intern_impl_trait_id(impl_trait_id).into();
192-
TyKind::OpaqueType(opaque_ty_id, Substitution::from1(Interner, inner_ty))
193-
.intern(Interner)
165+
self.infer_async_block(tgt_expr, id, statements, tail)
194166
}
195167
&Expr::Loop { body, label } => {
196168
// FIXME: should be:
@@ -260,18 +232,7 @@ impl<'a> InferenceContext<'a> {
260232
None => self.table.new_type_var(),
261233
};
262234
if let ClosureKind::Async = closure_kind {
263-
// Use the first type parameter as the output type of future.
264-
// existential type AsyncBlockImplTrait<InnerType>: Future<Output = InnerType>
265-
let impl_trait_id =
266-
crate::ImplTraitId::AsyncBlockTypeImplTrait(self.owner, *body);
267-
let opaque_ty_id = self.db.intern_impl_trait_id(impl_trait_id).into();
268-
sig_tys.push(
269-
TyKind::OpaqueType(
270-
opaque_ty_id,
271-
Substitution::from1(Interner, ret_ty.clone()),
272-
)
273-
.intern(Interner),
274-
);
235+
sig_tys.push(self.lower_async_block_type_impl_trait(ret_ty.clone(), *body));
275236
} else {
276237
sig_tys.push(ret_ty.clone());
277238
}
@@ -332,6 +293,7 @@ impl<'a> InferenceContext<'a> {
332293

333294
// FIXME: lift these out into a struct
334295
let prev_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
296+
let prev_is_async_fn = mem::replace(&mut self.is_async_fn, false);
335297
let prev_ret_ty = mem::replace(&mut self.return_ty, ret_ty.clone());
336298
let prev_ret_coercion =
337299
mem::replace(&mut self.return_coercion, Some(CoerceMany::new(ret_ty)));
@@ -345,6 +307,7 @@ impl<'a> InferenceContext<'a> {
345307
self.diverges = prev_diverges;
346308
self.return_ty = prev_ret_ty;
347309
self.return_coercion = prev_ret_coercion;
310+
self.is_async_fn = prev_is_async_fn;
348311
self.resume_yield_tys = prev_resume_yield_tys;
349312

350313
ty
@@ -900,6 +863,42 @@ impl<'a> InferenceContext<'a> {
900863
ty
901864
}
902865

866+
fn infer_async_block(
867+
&mut self,
868+
tgt_expr: ExprId,
869+
id: &Option<BlockId>,
870+
statements: &[Statement],
871+
tail: &Option<ExprId>,
872+
) -> Ty {
873+
let ret_ty = self.table.new_type_var();
874+
let prev_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
875+
let prev_ret_ty = mem::replace(&mut self.return_ty, ret_ty.clone());
876+
let prev_ret_coercion =
877+
mem::replace(&mut self.return_coercion, Some(CoerceMany::new(ret_ty.clone())));
878+
879+
let (_, inner_ty) = self.with_breakable_ctx(BreakableKind::Border, None, None, |this| {
880+
this.infer_block(tgt_expr, *id, statements, *tail, None, &Expectation::has_type(ret_ty))
881+
});
882+
883+
self.diverges = prev_diverges;
884+
self.return_ty = prev_ret_ty;
885+
self.return_coercion = prev_ret_coercion;
886+
887+
self.lower_async_block_type_impl_trait(inner_ty, tgt_expr)
888+
}
889+
890+
pub(crate) fn lower_async_block_type_impl_trait(
891+
&mut self,
892+
inner_ty: Ty,
893+
tgt_expr: ExprId,
894+
) -> Ty {
895+
// Use the first type parameter as the output type of future.
896+
// existential type AsyncBlockImplTrait<InnerType>: Future<Output = InnerType>
897+
let impl_trait_id = crate::ImplTraitId::AsyncBlockTypeImplTrait(self.owner, tgt_expr);
898+
let opaque_ty_id = self.db.intern_impl_trait_id(impl_trait_id).into();
899+
TyKind::OpaqueType(opaque_ty_id, Substitution::from1(Interner, inner_ty)).intern(Interner)
900+
}
901+
903902
fn infer_expr_array(
904903
&mut self,
905904
array: &Array,
@@ -964,7 +963,11 @@ impl<'a> InferenceContext<'a> {
964963
.as_mut()
965964
.expect("infer_return called outside function body")
966965
.expected_ty();
967-
let return_expr_ty = self.infer_expr_inner(expr, &Expectation::HasType(ret_ty));
966+
let return_expr_ty = if self.is_async_fn {
967+
self.infer_async_block(expr, &None, &[], &Some(expr))
968+
} else {
969+
self.infer_expr_inner(expr, &Expectation::HasType(ret_ty))
970+
};
968971
let mut coerce_many = self.return_coercion.take().unwrap();
969972
coerce_many.coerce(self, Some(expr), &return_expr_ty);
970973
self.return_coercion = Some(coerce_many);

crates/hir-ty/src/tests/regression.rs

+14
Original file line numberDiff line numberDiff line change
@@ -1757,6 +1757,20 @@ const C: usize = 2 + 2;
17571757
);
17581758
}
17591759

1760+
#[test]
1761+
fn regression_14456() {
1762+
check_no_mismatches(
1763+
r#"
1764+
//- minicore: future
1765+
async fn x() {}
1766+
fn f() {
1767+
let fut = x();
1768+
let t = [0u8; 2 + 2];
1769+
}
1770+
"#,
1771+
);
1772+
}
1773+
17601774
#[test]
17611775
fn regression_14164() {
17621776
check_types(

0 commit comments

Comments
 (0)