diff options
| author | Stuart Cook <Zalathar@users.noreply.github.com> | 2024-12-31 14:12:47 +1100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-12-31 14:12:47 +1100 |
| commit | a93bef61618c87ed2ebab391a2994bc622d79e44 (patch) | |
| tree | c5b38fa1a1a26b66f6756f5616079f2ad33bb80f | |
| parent | e49929e44d08aa94b4e1a5aab001c062b16c7680 (diff) | |
| parent | ed9a4cfdeb0c81f26c7f6d8b8e56e36aa23cf420 (diff) | |
| download | rust-a93bef61618c87ed2ebab391a2994bc622d79e44.tar.gz rust-a93bef61618c87ed2ebab391a2994bc622d79e44.zip | |
Rollup merge of #134933 - compiler-errors:async-fn-future-sized, r=lqd
Make sure we check the future type is `Sized` in `AsyncFn*` Fixes #134817
3 files changed, 71 insertions, 3 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 962b6b94fa6..3619d16cde2 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -896,6 +896,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { sig.tupled_inputs_ty, ]) }); + + // Note that unlike below, we don't need to check `Future + Sized` for + // the output coroutine because they are `Future + Sized` by construction. + (trait_ref, args.kind_ty()) } ty::FnDef(..) | ty::FnPtr(..) => { @@ -907,7 +911,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ]) }); - // We must additionally check that the return type impls `Future`. + // We must additionally check that the return type impls `Future + Sized`. let future_trait_def_id = tcx.require_lang_item(LangItem::Future, None); nested.push(obligation.with( tcx, @@ -915,6 +919,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::TraitRef::new(tcx, future_trait_def_id, [output_ty]) }), )); + let sized_trait_def_id = tcx.require_lang_item(LangItem::Sized, None); + nested.push(obligation.with( + tcx, + sig.output().map_bound(|output_ty| { + ty::TraitRef::new(tcx, sized_trait_def_id, [output_ty]) + }), + )); (trait_ref, Ty::from_closure_kind(tcx, ty::ClosureKind::Fn)) } @@ -928,14 +939,20 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ]) }); - // We must additionally check that the return type impls `Future`. - // See FIXME in last branch for why we instantiate the binder eagerly. + // We must additionally check that the return type impls `Future + Sized`. let future_trait_def_id = tcx.require_lang_item(LangItem::Future, None); let placeholder_output_ty = self.infcx.enter_forall_and_leak_universe(sig.output()); nested.push(obligation.with( tcx, ty::TraitRef::new(tcx, future_trait_def_id, [placeholder_output_ty]), )); + let sized_trait_def_id = tcx.require_lang_item(LangItem::Sized, None); + nested.push(obligation.with( + tcx, + sig.output().map_bound(|output_ty| { + ty::TraitRef::new(tcx, sized_trait_def_id, [output_ty]) + }), + )); (trait_ref, args.kind_ty()) } diff --git a/tests/ui/async-await/async-closures/async-future-out-must-be-sized.rs b/tests/ui/async-await/async-closures/async-future-out-must-be-sized.rs new file mode 100644 index 00000000000..e5d70e30eb5 --- /dev/null +++ b/tests/ui/async-await/async-closures/async-future-out-must-be-sized.rs @@ -0,0 +1,20 @@ +//@ edition: 2021 + +// Ensure that the output of a `fn` pointer that implements `AsyncFn*` is `Sized`, +// like other built-in impls of an fn pointer, like `Fn*`. + +use std::future::Future; + +fn foo() -> fn() -> dyn Future<Output = ()> { + todo!() +} + +async fn is_async_fn(f: impl AsyncFn()) { + f().await; +} + +fn main() { + is_async_fn(foo()); + //~^ ERROR the size for values of type `dyn Future<Output = ()>` cannot be known at compilation time + //~| ERROR the size for values of type `dyn Future<Output = ()>` cannot be known at compilation time +} diff --git a/tests/ui/async-await/async-closures/async-future-out-must-be-sized.stderr b/tests/ui/async-await/async-closures/async-future-out-must-be-sized.stderr new file mode 100644 index 00000000000..f993247d8b9 --- /dev/null +++ b/tests/ui/async-await/async-closures/async-future-out-must-be-sized.stderr @@ -0,0 +1,31 @@ +error[E0277]: the size for values of type `dyn Future<Output = ()>` cannot be known at compilation time + --> $DIR/async-future-out-must-be-sized.rs:17:17 + | +LL | is_async_fn(foo()); + | ----------- ^^^^^ doesn't have a size known at compile-time + | | + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `dyn Future<Output = ()>` +note: required by a bound in `is_async_fn` + --> $DIR/async-future-out-must-be-sized.rs:12:30 + | +LL | async fn is_async_fn(f: impl AsyncFn()) { + | ^^^^^^^^^ required by this bound in `is_async_fn` + +error[E0277]: the size for values of type `dyn Future<Output = ()>` cannot be known at compilation time + --> $DIR/async-future-out-must-be-sized.rs:17:5 + | +LL | is_async_fn(foo()); + | ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `dyn Future<Output = ()>` +note: required by a bound in `is_async_fn` + --> $DIR/async-future-out-must-be-sized.rs:12:30 + | +LL | async fn is_async_fn(f: impl AsyncFn()) { + | ^^^^^^^^^ required by this bound in `is_async_fn` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. |
