about summary refs log tree commit diff
diff options
context:
space:
mode:
authorStuart Cook <Zalathar@users.noreply.github.com>2024-12-31 14:12:47 +1100
committerGitHub <noreply@github.com>2024-12-31 14:12:47 +1100
commita93bef61618c87ed2ebab391a2994bc622d79e44 (patch)
treec5b38fa1a1a26b66f6756f5616079f2ad33bb80f
parente49929e44d08aa94b4e1a5aab001c062b16c7680 (diff)
parented9a4cfdeb0c81f26c7f6d8b8e56e36aa23cf420 (diff)
downloadrust-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
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs23
-rw-r--r--tests/ui/async-await/async-closures/async-future-out-must-be-sized.rs20
-rw-r--r--tests/ui/async-await/async-closures/async-future-out-must-be-sized.stderr31
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`.