Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make sure we check the future type is Sized in AsyncFn* #134933

Merged
merged 1 commit into from
Dec 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 20 additions & 3 deletions compiler/rustc_trait_selection/src/traits/select/confirmation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(..) => {
Expand All @@ -907,14 +911,21 @@ 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,
sig.output().map_bound(|output_ty| {
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))
}
Expand All @@ -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())
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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
}
Original file line number Diff line number Diff line change
@@ -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`.
Loading