Skip to content

Relax CallOnceFuture/CallRefFuture bound from Future to IntoFuture #127225

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

Closed
Closed
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
4 changes: 3 additions & 1 deletion compiler/rustc_hir/src/lang_items.rs
Original file line number Diff line number Diff line change
@@ -241,6 +241,9 @@ language_item_table! {
FusedIterator, sym::fused_iterator, fused_iterator_trait, Target::Trait, GenericRequirement::Exact(0);
Future, sym::future_trait, future_trait, Target::Trait, GenericRequirement::Exact(0);
FutureOutput, sym::future_output, future_output, Target::AssocTy, GenericRequirement::Exact(0);
IntoFuture, sym::into_future, into_future_trait, Target::Trait, GenericRequirement::Exact(0);
IntoFutureOutput, sym::into_future_output, into_future_output, Target::AssocTy, GenericRequirement::Exact(0);
IntoFutureIntoFuture, sym::into_future_into_future, into_future_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
AsyncIterator, sym::async_iterator, async_iterator_trait, Target::Trait, GenericRequirement::Exact(0);

CoroutineState, sym::coroutine_state, coroutine_state, Target::Enum, GenericRequirement::None;
@@ -377,7 +380,6 @@ language_item_table! {
ControlFlowContinue, sym::Continue, cf_continue_variant, Target::Variant, GenericRequirement::None;
ControlFlowBreak, sym::Break, cf_break_variant, Target::Variant, GenericRequirement::None;

IntoFutureIntoFuture, sym::into_future, into_future_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
IntoIterIntoIter, sym::into_iter, into_iter_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
IteratorNext, sym::next, next_fn, Target::Method(MethodKind::Trait { body: false}), GenericRequirement::None;

2 changes: 2 additions & 0 deletions compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
@@ -610,6 +610,8 @@ fn trait_lang_item_to_lang_item(lang_item: TraitSolverLangItem) -> LangItem {
TraitSolverLangItem::FusedIterator => LangItem::FusedIterator,
TraitSolverLangItem::Future => LangItem::Future,
TraitSolverLangItem::FutureOutput => LangItem::FutureOutput,
TraitSolverLangItem::IntoFuture => LangItem::IntoFuture,
TraitSolverLangItem::IntoFutureOutput => LangItem::IntoFutureOutput,
TraitSolverLangItem::Iterator => LangItem::Iterator,
TraitSolverLangItem::Metadata => LangItem::Metadata,
TraitSolverLangItem::Option => LangItem::Option,
4 changes: 2 additions & 2 deletions compiler/rustc_mir_transform/src/coroutine/by_move_body.rs
Original file line number Diff line number Diff line change
@@ -31,10 +31,10 @@
//! However, what happens when we call `closure` with `AsyncFnOnce` (or `FnOnce`,
//! since all async closures implement that too)? Well, recall the signature:
//! ```
//! use std::future::Future;
//! use std::future::IntoFuture;
//! pub trait AsyncFnOnce<Args>
//! {
//! type CallOnceFuture: Future<Output = Self::Output>;
//! type CallOnceFuture: IntoFuture<Output = Self::Output>;
//! type Output;
//! fn async_call_once(
//! self,
Original file line number Diff line number Diff line change
@@ -458,15 +458,15 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<I:
ty::FnDef(..) | ty::FnPtr(..) => {
let bound_sig = self_ty.fn_sig(cx);
let sig = bound_sig.skip_binder();
let future_trait_def_id = cx.require_lang_item(TraitSolverLangItem::Future);
let future_trait_def_id = cx.require_lang_item(TraitSolverLangItem::IntoFuture);
// `FnDef` and `FnPtr` only implement `AsyncFn*` when their
// return type implements `Future`.
let nested = vec![
bound_sig
.rebind(ty::TraitRef::new(cx, future_trait_def_id, [sig.output()]))
.upcast(cx),
];
let future_output_def_id = cx.require_lang_item(TraitSolverLangItem::FutureOutput);
let future_output_def_id = cx.require_lang_item(TraitSolverLangItem::IntoFutureOutput);
let future_output_ty = Ty::new_projection(cx, future_output_def_id, [sig.output()]);
Ok((
bound_sig.rebind(AsyncCallableRelevantTypes {
@@ -481,7 +481,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<I:
let args = args.as_closure();
let bound_sig = args.sig();
let sig = bound_sig.skip_binder();
let future_trait_def_id = cx.require_lang_item(TraitSolverLangItem::Future);
let future_trait_def_id = cx.require_lang_item(TraitSolverLangItem::IntoFuture);
// `Closure`s only implement `AsyncFn*` when their return type
// implements `Future`.
let mut nested = vec![
@@ -517,7 +517,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<I:
);
}

let future_output_def_id = cx.require_lang_item(TraitSolverLangItem::FutureOutput);
let future_output_def_id = cx.require_lang_item(TraitSolverLangItem::IntoFutureOutput);
let future_output_ty = Ty::new_projection(cx, future_output_def_id, [sig.output()]);
Ok((
bound_sig.rebind(AsyncCallableRelevantTypes {
2 changes: 2 additions & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
@@ -1042,6 +1042,8 @@ symbols! {
integral,
into_async_iter_into_iter,
into_future,
into_future_into_future,
into_future_output,
into_iter,
intra_doc_pointers,
intrinsics,
6 changes: 4 additions & 2 deletions compiler/rustc_trait_selection/src/traits/project.rs
Original file line number Diff line number Diff line change
@@ -1877,7 +1877,8 @@ fn confirm_async_closure_candidate<'cx, 'tcx>(
let term = match item_name {
sym::CallOnceFuture | sym::CallRefFuture => sig.output(),
sym::Output => {
let future_output_def_id = tcx.require_lang_item(LangItem::FutureOutput, None);
let future_output_def_id =
tcx.require_lang_item(LangItem::IntoFutureOutput, None);
Ty::new_projection(tcx, future_output_def_id, [sig.output()])
}
name => bug!("no such associated type: {name}"),
@@ -1910,7 +1911,8 @@ fn confirm_async_closure_candidate<'cx, 'tcx>(
let term = match item_name {
sym::CallOnceFuture | sym::CallRefFuture => sig.output(),
sym::Output => {
let future_output_def_id = tcx.require_lang_item(LangItem::FutureOutput, None);
let future_output_def_id =
tcx.require_lang_item(LangItem::IntoFutureOutput, None);
Ty::new_projection(tcx, future_output_def_id, [sig.output()])
}
name => bug!("no such associated type: {name}"),
Original file line number Diff line number Diff line change
@@ -951,7 +951,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// traits expressly allow the user to write. To fix this correctly,
// we'd need to instantiate trait bounds before we get to selection,
// like the new trait solver does.
let future_trait_def_id = tcx.require_lang_item(LangItem::Future, None);
let future_trait_def_id = tcx.require_lang_item(LangItem::IntoFuture, None);
let placeholder_output_ty = self.infcx.enter_forall_and_leak_universe(sig.output());
nested.push(obligation.with(
tcx,
@@ -973,7 +973,7 @@ 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.
let future_trait_def_id = tcx.require_lang_item(LangItem::Future, None);
let future_trait_def_id = tcx.require_lang_item(LangItem::IntoFuture, None);
let placeholder_output_ty = self.infcx.enter_forall_and_leak_universe(sig.output());
nested.push(obligation.with(
tcx,
2 changes: 2 additions & 0 deletions compiler/rustc_type_ir/src/lang_items.rs
Original file line number Diff line number Diff line change
@@ -26,6 +26,8 @@ pub enum TraitSolverLangItem {
FusedIterator,
Future,
FutureOutput,
IntoFuture,
IntoFutureOutput,
Iterator,
Metadata,
Option,
5 changes: 4 additions & 1 deletion library/core/src/future/into_future.rs
Original file line number Diff line number Diff line change
@@ -105,9 +105,11 @@ use crate::future::Future;
message = "`{Self}` is not a future",
note = "{Self} must be a future or must implement `IntoFuture` to be awaited"
)]
#[cfg_attr(not(bootstrap), lang = "into_future")]
pub trait IntoFuture {
/// The output that the future will produce on completion.
#[stable(feature = "into_future", since = "1.64.0")]
#[cfg_attr(not(bootstrap), lang = "into_future_output")]
type Output;

/// Which kind of future are we turning this into?
@@ -130,7 +132,8 @@ pub trait IntoFuture {
/// # }
/// ```
#[stable(feature = "into_future", since = "1.64.0")]
#[lang = "into_future"]
#[cfg_attr(not(bootstrap), lang = "into_future_into_future")]
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed the existing lang item to into_future_into_future, and reused that name for the trait name for consistency!

#[cfg_attr(bootstrap, lang = "into_future")]
fn into_future(self) -> Self::IntoFuture;
}

6 changes: 3 additions & 3 deletions library/core/src/ops/async_function.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::future::Future;
use crate::future::IntoFuture;
use crate::marker::Tuple;

/// An async-aware version of the [`Fn`](crate::ops::Fn) trait.
@@ -27,7 +27,7 @@ pub trait AsyncFnMut<Args: Tuple>: AsyncFnOnce<Args> {
/// Future returned by [`AsyncFnMut::async_call_mut`] and [`AsyncFn::async_call`].
#[unstable(feature = "async_fn_traits", issue = "none")]
#[lang = "call_ref_future"]
type CallRefFuture<'a>: Future<Output = Self::Output>
type CallRefFuture<'a>: IntoFuture<Output = Self::Output>
where
Self: 'a;

@@ -48,7 +48,7 @@ pub trait AsyncFnOnce<Args: Tuple> {
/// Future returned by [`AsyncFnOnce::async_call_once`].
#[unstable(feature = "async_fn_traits", issue = "none")]
#[lang = "call_once_future"]
type CallOnceFuture: Future<Output = Self::Output>;
type CallOnceFuture: IntoFuture<Output = Self::Output>;

/// Output type of the called closure's future.
#[unstable(feature = "async_fn_traits", issue = "none")]