Rollup merge of #125733 - compiler-errors:async-fn-assoc-item, r=fmease
Add lang items for `AsyncFn*`, `Future`, `AsyncFnKindHelper`'s associated types Adds lang items for `AsyncFnOnce::Output`, `AsyncFnOnce::CallOnceFuture`, `AsyncFnMut::CallRefFuture`, and uses them in the new solver. I'm mostly interested in doing this to help accelerate uplifting the new trait solver into a separate crate. The old solver is kind of spaghetti, so I haven't moved that to use these lang items (i.e. it still uses `item_name`-based comparisons). update: Also adds lang items for `Future::Output` and `AsyncFnKindHelper::Upvars`. cc ``@lcnr``
This commit is contained in:
commit
1ae1388d2a
8 changed files with 40 additions and 62 deletions
|
@ -228,13 +228,18 @@ language_item_table! {
|
||||||
AsyncFn, sym::async_fn, async_fn_trait, Target::Trait, GenericRequirement::Exact(1);
|
AsyncFn, sym::async_fn, async_fn_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
AsyncFnMut, sym::async_fn_mut, async_fn_mut_trait, Target::Trait, GenericRequirement::Exact(1);
|
AsyncFnMut, sym::async_fn_mut, async_fn_mut_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
AsyncFnOnce, sym::async_fn_once, async_fn_once_trait, Target::Trait, GenericRequirement::Exact(1);
|
AsyncFnOnce, sym::async_fn_once, async_fn_once_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
|
AsyncFnOnceOutput, sym::async_fn_once_output, async_fn_once_output, Target::AssocTy, GenericRequirement::Exact(1);
|
||||||
|
CallOnceFuture, sym::call_once_future, call_once_future, Target::AssocTy, GenericRequirement::Exact(1);
|
||||||
|
CallRefFuture, sym::call_ref_future, call_ref_future, Target::AssocTy, GenericRequirement::Exact(2);
|
||||||
AsyncFnKindHelper, sym::async_fn_kind_helper, async_fn_kind_helper, Target::Trait, GenericRequirement::Exact(1);
|
AsyncFnKindHelper, sym::async_fn_kind_helper, async_fn_kind_helper, Target::Trait, GenericRequirement::Exact(1);
|
||||||
|
AsyncFnKindUpvars, sym::async_fn_kind_upvars, async_fn_kind_upvars, Target::AssocTy, GenericRequirement::Exact(5);
|
||||||
|
|
||||||
FnOnceOutput, sym::fn_once_output, fn_once_output, Target::AssocTy, GenericRequirement::None;
|
FnOnceOutput, sym::fn_once_output, fn_once_output, Target::AssocTy, GenericRequirement::None;
|
||||||
|
|
||||||
Iterator, sym::iterator, iterator_trait, Target::Trait, GenericRequirement::Exact(0);
|
Iterator, sym::iterator, iterator_trait, Target::Trait, GenericRequirement::Exact(0);
|
||||||
FusedIterator, sym::fused_iterator, fused_iterator_trait, Target::Trait, GenericRequirement::Exact(0);
|
FusedIterator, sym::fused_iterator, fused_iterator_trait, Target::Trait, GenericRequirement::Exact(0);
|
||||||
Future, sym::future_trait, future_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);
|
||||||
AsyncIterator, sym::async_iterator, async_iterator_trait, Target::Trait, GenericRequirement::Exact(0);
|
AsyncIterator, sym::async_iterator, async_iterator_trait, Target::Trait, GenericRequirement::Exact(0);
|
||||||
|
|
||||||
CoroutineState, sym::coroutine_state, coroutine_state, Target::Enum, GenericRequirement::None;
|
CoroutineState, sym::coroutine_state, coroutine_state, Target::Enum, GenericRequirement::None;
|
||||||
|
|
|
@ -1478,7 +1478,7 @@ pub fn suggest_impl_trait<'tcx>(
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
infcx.tcx.lang_items().future_trait(),
|
infcx.tcx.lang_items().future_trait(),
|
||||||
infcx.tcx.get_diagnostic_item(sym::FutureOutput),
|
infcx.tcx.lang_items().future_output(),
|
||||||
format_as_assoc,
|
format_as_assoc,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
|
|
|
@ -210,7 +210,6 @@ symbols! {
|
||||||
FsPermissions,
|
FsPermissions,
|
||||||
FusedIterator,
|
FusedIterator,
|
||||||
Future,
|
Future,
|
||||||
FutureOutput,
|
|
||||||
GlobalAlloc,
|
GlobalAlloc,
|
||||||
Hash,
|
Hash,
|
||||||
HashMap,
|
HashMap,
|
||||||
|
@ -439,8 +438,10 @@ symbols! {
|
||||||
async_fn,
|
async_fn,
|
||||||
async_fn_in_trait,
|
async_fn_in_trait,
|
||||||
async_fn_kind_helper,
|
async_fn_kind_helper,
|
||||||
|
async_fn_kind_upvars,
|
||||||
async_fn_mut,
|
async_fn_mut,
|
||||||
async_fn_once,
|
async_fn_once,
|
||||||
|
async_fn_once_output,
|
||||||
async_fn_track_caller,
|
async_fn_track_caller,
|
||||||
async_fn_traits,
|
async_fn_traits,
|
||||||
async_for_loop,
|
async_for_loop,
|
||||||
|
@ -498,6 +499,8 @@ symbols! {
|
||||||
call,
|
call,
|
||||||
call_mut,
|
call_mut,
|
||||||
call_once,
|
call_once,
|
||||||
|
call_once_future,
|
||||||
|
call_ref_future,
|
||||||
caller_location,
|
caller_location,
|
||||||
capture_disjoint_fields,
|
capture_disjoint_fields,
|
||||||
catch_unwind,
|
catch_unwind,
|
||||||
|
@ -911,6 +914,7 @@ symbols! {
|
||||||
fundamental,
|
fundamental,
|
||||||
fused_iterator,
|
fused_iterator,
|
||||||
future,
|
future,
|
||||||
|
future_output,
|
||||||
future_trait,
|
future_trait,
|
||||||
gdb_script_file,
|
gdb_script_file,
|
||||||
ge,
|
ge,
|
||||||
|
|
|
@ -9,7 +9,6 @@ use rustc_macros::{TypeFoldable, TypeVisitable};
|
||||||
use rustc_middle::bug;
|
use rustc_middle::bug;
|
||||||
use rustc_middle::traits::solve::Goal;
|
use rustc_middle::traits::solve::Goal;
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, Upcast};
|
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, Upcast};
|
||||||
use rustc_span::sym;
|
|
||||||
|
|
||||||
use crate::solve::EvalCtxt;
|
use crate::solve::EvalCtxt;
|
||||||
|
|
||||||
|
@ -454,12 +453,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc
|
||||||
.rebind(ty::TraitRef::new(tcx, future_trait_def_id, [sig.output()]))
|
.rebind(ty::TraitRef::new(tcx, future_trait_def_id, [sig.output()]))
|
||||||
.upcast(tcx),
|
.upcast(tcx),
|
||||||
];
|
];
|
||||||
let future_output_def_id = tcx
|
let future_output_def_id = tcx.require_lang_item(LangItem::FutureOutput, None);
|
||||||
.associated_items(future_trait_def_id)
|
|
||||||
.filter_by_name_unhygienic(sym::Output)
|
|
||||||
.next()
|
|
||||||
.unwrap()
|
|
||||||
.def_id;
|
|
||||||
let future_output_ty = Ty::new_projection(tcx, future_output_def_id, [sig.output()]);
|
let future_output_ty = Ty::new_projection(tcx, future_output_def_id, [sig.output()]);
|
||||||
Ok((
|
Ok((
|
||||||
bound_sig.rebind(AsyncCallableRelevantTypes {
|
bound_sig.rebind(AsyncCallableRelevantTypes {
|
||||||
|
@ -510,12 +504,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let future_output_def_id = tcx
|
let future_output_def_id = tcx.require_lang_item(LangItem::FutureOutput, None);
|
||||||
.associated_items(future_trait_def_id)
|
|
||||||
.filter_by_name_unhygienic(sym::Output)
|
|
||||||
.next()
|
|
||||||
.unwrap()
|
|
||||||
.def_id;
|
|
||||||
let future_output_ty = Ty::new_projection(tcx, future_output_def_id, [sig.output()]);
|
let future_output_ty = Ty::new_projection(tcx, future_output_def_id, [sig.output()]);
|
||||||
Ok((
|
Ok((
|
||||||
bound_sig.rebind(AsyncCallableRelevantTypes {
|
bound_sig.rebind(AsyncCallableRelevantTypes {
|
||||||
|
@ -592,13 +581,7 @@ fn coroutine_closure_to_ambiguous_coroutine<'tcx>(
|
||||||
args: ty::CoroutineClosureArgs<'tcx>,
|
args: ty::CoroutineClosureArgs<'tcx>,
|
||||||
sig: ty::CoroutineClosureSignature<'tcx>,
|
sig: ty::CoroutineClosureSignature<'tcx>,
|
||||||
) -> Ty<'tcx> {
|
) -> Ty<'tcx> {
|
||||||
let async_fn_kind_trait_def_id = tcx.require_lang_item(LangItem::AsyncFnKindHelper, None);
|
let upvars_projection_def_id = tcx.require_lang_item(LangItem::AsyncFnKindUpvars, None);
|
||||||
let upvars_projection_def_id = tcx
|
|
||||||
.associated_items(async_fn_kind_trait_def_id)
|
|
||||||
.filter_by_name_unhygienic(sym::Upvars)
|
|
||||||
.next()
|
|
||||||
.unwrap()
|
|
||||||
.def_id;
|
|
||||||
let tupled_upvars_ty = Ty::new_projection(
|
let tupled_upvars_ty = Ty::new_projection(
|
||||||
tcx,
|
tcx,
|
||||||
upvars_projection_def_id,
|
upvars_projection_def_id,
|
||||||
|
|
|
@ -407,16 +407,20 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
|
||||||
output_coroutine_ty,
|
output_coroutine_ty,
|
||||||
coroutine_return_ty,
|
coroutine_return_ty,
|
||||||
}| {
|
}| {
|
||||||
let (projection_term, term) = match tcx.item_name(goal.predicate.def_id()) {
|
let lang_items = tcx.lang_items();
|
||||||
sym::CallOnceFuture => (
|
let (projection_term, term) = if Some(goal.predicate.def_id())
|
||||||
|
== lang_items.call_once_future()
|
||||||
|
{
|
||||||
|
(
|
||||||
ty::AliasTerm::new(
|
ty::AliasTerm::new(
|
||||||
tcx,
|
tcx,
|
||||||
goal.predicate.def_id(),
|
goal.predicate.def_id(),
|
||||||
[goal.predicate.self_ty(), tupled_inputs_ty],
|
[goal.predicate.self_ty(), tupled_inputs_ty],
|
||||||
),
|
),
|
||||||
output_coroutine_ty.into(),
|
output_coroutine_ty.into(),
|
||||||
),
|
)
|
||||||
sym::CallRefFuture => (
|
} else if Some(goal.predicate.def_id()) == lang_items.call_ref_future() {
|
||||||
|
(
|
||||||
ty::AliasTerm::new(
|
ty::AliasTerm::new(
|
||||||
tcx,
|
tcx,
|
||||||
goal.predicate.def_id(),
|
goal.predicate.def_id(),
|
||||||
|
@ -427,8 +431,9 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
output_coroutine_ty.into(),
|
output_coroutine_ty.into(),
|
||||||
),
|
)
|
||||||
sym::Output => (
|
} else if Some(goal.predicate.def_id()) == lang_items.async_fn_once_output() {
|
||||||
|
(
|
||||||
ty::AliasTerm::new(
|
ty::AliasTerm::new(
|
||||||
tcx,
|
tcx,
|
||||||
goal.predicate.def_id(),
|
goal.predicate.def_id(),
|
||||||
|
@ -438,8 +443,9 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
coroutine_return_ty.into(),
|
coroutine_return_ty.into(),
|
||||||
),
|
)
|
||||||
name => bug!("no such associated type: {name}"),
|
} else {
|
||||||
|
bug!("no such associated type in `AsyncFn*`: {:?}", goal.predicate.def_id())
|
||||||
};
|
};
|
||||||
ty::ProjectionPredicate { projection_term, term }
|
ty::ProjectionPredicate { projection_term, term }
|
||||||
},
|
},
|
||||||
|
|
|
@ -1680,14 +1680,8 @@ fn confirm_closure_candidate<'cx, 'tcx>(
|
||||||
args.coroutine_captures_by_ref_ty(),
|
args.coroutine_captures_by_ref_ty(),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
let async_fn_kind_trait_def_id =
|
let upvars_projection_def_id =
|
||||||
tcx.require_lang_item(LangItem::AsyncFnKindHelper, None);
|
tcx.require_lang_item(LangItem::AsyncFnKindUpvars, None);
|
||||||
let upvars_projection_def_id = tcx
|
|
||||||
.associated_items(async_fn_kind_trait_def_id)
|
|
||||||
.filter_by_name_unhygienic(sym::Upvars)
|
|
||||||
.next()
|
|
||||||
.unwrap()
|
|
||||||
.def_id;
|
|
||||||
let tupled_upvars_ty = Ty::new_projection(
|
let tupled_upvars_ty = Ty::new_projection(
|
||||||
tcx,
|
tcx,
|
||||||
upvars_projection_def_id,
|
upvars_projection_def_id,
|
||||||
|
@ -1816,14 +1810,8 @@ fn confirm_async_closure_candidate<'cx, 'tcx>(
|
||||||
args.coroutine_captures_by_ref_ty(),
|
args.coroutine_captures_by_ref_ty(),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
let async_fn_kind_trait_def_id =
|
let upvars_projection_def_id =
|
||||||
tcx.require_lang_item(LangItem::AsyncFnKindHelper, None);
|
tcx.require_lang_item(LangItem::AsyncFnKindUpvars, None);
|
||||||
let upvars_projection_def_id = tcx
|
|
||||||
.associated_items(async_fn_kind_trait_def_id)
|
|
||||||
.filter_by_name_unhygienic(sym::Upvars)
|
|
||||||
.next()
|
|
||||||
.unwrap()
|
|
||||||
.def_id;
|
|
||||||
// When we don't know the closure kind (and therefore also the closure's upvars,
|
// When we don't know the closure kind (and therefore also the closure's upvars,
|
||||||
// which are computed at the same time), we must delay the computation of the
|
// which are computed at the same time), we must delay the computation of the
|
||||||
// generator's upvars. We do this using the `AsyncFnKindHelper`, which as a trait
|
// generator's upvars. We do this using the `AsyncFnKindHelper`, which as a trait
|
||||||
|
@ -1880,13 +1868,7 @@ fn confirm_async_closure_candidate<'cx, 'tcx>(
|
||||||
let term = match item_name {
|
let term = match item_name {
|
||||||
sym::CallOnceFuture | sym::CallRefFuture => sig.output(),
|
sym::CallOnceFuture | sym::CallRefFuture => sig.output(),
|
||||||
sym::Output => {
|
sym::Output => {
|
||||||
let future_trait_def_id = tcx.require_lang_item(LangItem::Future, None);
|
let future_output_def_id = tcx.require_lang_item(LangItem::FutureOutput, None);
|
||||||
let future_output_def_id = tcx
|
|
||||||
.associated_items(future_trait_def_id)
|
|
||||||
.filter_by_name_unhygienic(sym::Output)
|
|
||||||
.next()
|
|
||||||
.unwrap()
|
|
||||||
.def_id;
|
|
||||||
Ty::new_projection(tcx, future_output_def_id, [sig.output()])
|
Ty::new_projection(tcx, future_output_def_id, [sig.output()])
|
||||||
}
|
}
|
||||||
name => bug!("no such associated type: {name}"),
|
name => bug!("no such associated type: {name}"),
|
||||||
|
@ -1919,13 +1901,7 @@ fn confirm_async_closure_candidate<'cx, 'tcx>(
|
||||||
let term = match item_name {
|
let term = match item_name {
|
||||||
sym::CallOnceFuture | sym::CallRefFuture => sig.output(),
|
sym::CallOnceFuture | sym::CallRefFuture => sig.output(),
|
||||||
sym::Output => {
|
sym::Output => {
|
||||||
let future_trait_def_id = tcx.require_lang_item(LangItem::Future, None);
|
let future_output_def_id = tcx.require_lang_item(LangItem::FutureOutput, None);
|
||||||
let future_output_def_id = tcx
|
|
||||||
.associated_items(future_trait_def_id)
|
|
||||||
.filter_by_name_unhygienic(sym::Output)
|
|
||||||
.next()
|
|
||||||
.unwrap()
|
|
||||||
.def_id;
|
|
||||||
Ty::new_projection(tcx, future_output_def_id, [sig.output()])
|
Ty::new_projection(tcx, future_output_def_id, [sig.output()])
|
||||||
}
|
}
|
||||||
name => bug!("no such associated type: {name}"),
|
name => bug!("no such associated type: {name}"),
|
||||||
|
|
|
@ -35,7 +35,7 @@ use crate::task::{Context, Poll};
|
||||||
pub trait Future {
|
pub trait Future {
|
||||||
/// The type of value produced on completion.
|
/// The type of value produced on completion.
|
||||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||||
#[rustc_diagnostic_item = "FutureOutput"]
|
#[cfg_attr(not(bootstrap), lang = "future_output")]
|
||||||
type Output;
|
type Output;
|
||||||
|
|
||||||
/// Attempt to resolve the future to a final value, registering
|
/// Attempt to resolve the future to a final value, registering
|
||||||
|
|
|
@ -26,6 +26,7 @@ pub trait AsyncFn<Args: Tuple>: AsyncFnMut<Args> {
|
||||||
pub trait AsyncFnMut<Args: Tuple>: AsyncFnOnce<Args> {
|
pub trait AsyncFnMut<Args: Tuple>: AsyncFnOnce<Args> {
|
||||||
/// Future returned by [`AsyncFnMut::async_call_mut`] and [`AsyncFn::async_call`].
|
/// Future returned by [`AsyncFnMut::async_call_mut`] and [`AsyncFn::async_call`].
|
||||||
#[unstable(feature = "async_fn_traits", issue = "none")]
|
#[unstable(feature = "async_fn_traits", issue = "none")]
|
||||||
|
#[cfg_attr(not(bootstrap), lang = "call_ref_future")]
|
||||||
type CallRefFuture<'a>: Future<Output = Self::Output>
|
type CallRefFuture<'a>: Future<Output = Self::Output>
|
||||||
where
|
where
|
||||||
Self: 'a;
|
Self: 'a;
|
||||||
|
@ -46,10 +47,12 @@ pub trait AsyncFnMut<Args: Tuple>: AsyncFnOnce<Args> {
|
||||||
pub trait AsyncFnOnce<Args: Tuple> {
|
pub trait AsyncFnOnce<Args: Tuple> {
|
||||||
/// Future returned by [`AsyncFnOnce::async_call_once`].
|
/// Future returned by [`AsyncFnOnce::async_call_once`].
|
||||||
#[unstable(feature = "async_fn_traits", issue = "none")]
|
#[unstable(feature = "async_fn_traits", issue = "none")]
|
||||||
|
#[cfg_attr(not(bootstrap), lang = "call_once_future")]
|
||||||
type CallOnceFuture: Future<Output = Self::Output>;
|
type CallOnceFuture: Future<Output = Self::Output>;
|
||||||
|
|
||||||
/// Output type of the called closure's future.
|
/// Output type of the called closure's future.
|
||||||
#[unstable(feature = "async_fn_traits", issue = "none")]
|
#[unstable(feature = "async_fn_traits", issue = "none")]
|
||||||
|
#[cfg_attr(not(bootstrap), lang = "async_fn_once_output")]
|
||||||
type Output;
|
type Output;
|
||||||
|
|
||||||
/// Call the [`AsyncFnOnce`], returning a future which may move out of the called closure.
|
/// Call the [`AsyncFnOnce`], returning a future which may move out of the called closure.
|
||||||
|
@ -143,6 +146,7 @@ mod internal_implementation_detail {
|
||||||
// `for<'env> fn() -> (&'env T, ...)`. This allows us to represent the binder
|
// `for<'env> fn() -> (&'env T, ...)`. This allows us to represent the binder
|
||||||
// of the closure's self-capture, and these upvar types will be instantiated with
|
// of the closure's self-capture, and these upvar types will be instantiated with
|
||||||
// the `'closure_env` region provided to the associated type.
|
// the `'closure_env` region provided to the associated type.
|
||||||
|
#[cfg_attr(not(bootstrap), lang = "async_fn_kind_upvars")]
|
||||||
type Upvars<'closure_env, Inputs, Upvars, BorrowedUpvarsAsFnPtr>;
|
type Upvars<'closure_env, Inputs, Upvars, BorrowedUpvarsAsFnPtr>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue