diff options
Diffstat (limited to 'compiler')
4 files changed, 127 insertions, 1 deletions
diff --git a/compiler/rustc_trait_selection/src/solve/assembly.rs b/compiler/rustc_trait_selection/src/solve/assembly.rs index 0b642fcba28..baff0f8630e 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly.rs @@ -138,6 +138,16 @@ pub(super) trait GoalKind<'tcx>: TypeFoldable<'tcx> + Copy + Eq { ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx>; + + fn consider_builtin_future_candidate( + ecx: &mut EvalCtxt<'_, 'tcx>, + goal: Goal<'tcx, Self>, + ) -> QueryResult<'tcx>; + + fn consider_builtin_generator_candidate( + ecx: &mut EvalCtxt<'_, 'tcx>, + goal: Goal<'tcx, Self>, + ) -> QueryResult<'tcx>; } impl<'tcx> EvalCtxt<'_, 'tcx> { @@ -266,6 +276,10 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { G::consider_builtin_tuple_candidate(self, goal) } else if lang_items.pointee_trait() == Some(trait_def_id) { G::consider_builtin_pointee_candidate(self, goal) + } else if lang_items.future_trait() == Some(trait_def_id) { + G::consider_builtin_future_candidate(self, goal) + } else if lang_items.gen_trait() == Some(trait_def_id) { + G::consider_builtin_generator_candidate(self, goal) } else { Err(NoSolution) }; diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs index e5072d8e2d1..4a9b95af4a2 100644 --- a/compiler/rustc_trait_selection/src/solve/project_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs @@ -16,7 +16,7 @@ use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{ProjectionPredicate, TypeSuperVisitable, TypeVisitor}; use rustc_middle::ty::{ToPredicate, TypeVisitable}; -use rustc_span::DUMMY_SP; +use rustc_span::{sym, DUMMY_SP}; use std::iter; use std::ops::ControlFlow; @@ -482,6 +482,73 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> { ecx.evaluate_all_and_make_canonical_response(nested_goals) }) } + + fn consider_builtin_future_candidate( + ecx: &mut EvalCtxt<'_, 'tcx>, + goal: Goal<'tcx, Self>, + ) -> QueryResult<'tcx> { + let self_ty = goal.predicate.self_ty(); + let ty::Generator(def_id, substs, _) = *self_ty.kind() else { + return Err(NoSolution); + }; + + // Generators are not futures unless they come from `async` desugaring + let tcx = ecx.tcx(); + if !tcx.generator_is_async(def_id) { + return Err(NoSolution); + } + + let term = substs.as_generator().return_ty().into(); + + Self::consider_assumption( + ecx, + goal, + ty::Binder::dummy(ty::ProjectionPredicate { + projection_ty: ecx.tcx().mk_alias_ty(goal.predicate.def_id(), [self_ty]), + term, + }) + .to_predicate(tcx), + ) + } + + fn consider_builtin_generator_candidate( + ecx: &mut EvalCtxt<'_, 'tcx>, + goal: Goal<'tcx, Self>, + ) -> QueryResult<'tcx> { + let self_ty = goal.predicate.self_ty(); + let ty::Generator(def_id, substs, _) = *self_ty.kind() else { + return Err(NoSolution); + }; + + // `async`-desugared generators do not implement the generator trait + let tcx = ecx.tcx(); + if tcx.generator_is_async(def_id) { + return Err(NoSolution); + } + + let generator = substs.as_generator(); + + let name = tcx.associated_item(goal.predicate.def_id()).name; + let term = if name == sym::Return { + generator.return_ty().into() + } else if name == sym::Yield { + generator.yield_ty().into() + } else { + bug!("unexpected associated item `<{self_ty} as Generator>::{name}`") + }; + + Self::consider_assumption( + ecx, + goal, + ty::Binder::dummy(ty::ProjectionPredicate { + projection_ty: ecx + .tcx() + .mk_alias_ty(goal.predicate.def_id(), [self_ty, generator.resume_ty()]), + term, + }) + .to_predicate(tcx), + ) + } } /// This behavior is also implemented in `rustc_ty_utils` and in the old `project` code. diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index 67bd2495665..d74857dc4b4 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -192,6 +192,50 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ) -> QueryResult<'tcx> { ecx.make_canonical_response(Certainty::Yes) } + + fn consider_builtin_future_candidate( + ecx: &mut EvalCtxt<'_, 'tcx>, + goal: Goal<'tcx, Self>, + ) -> QueryResult<'tcx> { + let ty::Generator(def_id, _, _) = *goal.predicate.self_ty().kind() else { + return Err(NoSolution); + }; + + // Generators are not futures unless they come from `async` desugaring + let tcx = ecx.tcx(); + if !tcx.generator_is_async(def_id) { + return Err(NoSolution); + } + + // Async generator unconditionally implement `Future` + ecx.make_canonical_response(Certainty::Yes) + } + + fn consider_builtin_generator_candidate( + ecx: &mut EvalCtxt<'_, 'tcx>, + goal: Goal<'tcx, Self>, + ) -> QueryResult<'tcx> { + let self_ty = goal.predicate.self_ty(); + let ty::Generator(def_id, substs, _) = *self_ty.kind() else { + return Err(NoSolution); + }; + + // `async`-desugared generators do not implement the generator trait + let tcx = ecx.tcx(); + if tcx.generator_is_async(def_id) { + return Err(NoSolution); + } + + let generator = substs.as_generator(); + Self::consider_assumption( + ecx, + goal, + ty::Binder::dummy( + tcx.mk_trait_ref(goal.predicate.def_id(), [self_ty, generator.resume_ty()]), + ) + .to_predicate(tcx), + ) + } } impl<'tcx> EvalCtxt<'_, 'tcx> { diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs index a11cd13cb08..162953180c7 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs @@ -173,6 +173,7 @@ pub(super) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>( } } +// Returns a binder of the tupled inputs types and output type from a builtin callable type. pub(crate) fn extract_tupled_inputs_and_output_from_callable<'tcx>( tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>, |
