summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_trait_selection/src/solve
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-07 05:48:48 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-07 05:48:48 +0000
commitef24de24a82fe681581cc130f342363c47c0969a (patch)
tree0d494f7e1a38b95c92426f58fe6eaa877303a86c /compiler/rustc_trait_selection/src/solve
parentReleasing progress-linux version 1.74.1+dfsg1-1~progress7.99u1. (diff)
downloadrustc-ef24de24a82fe681581cc130f342363c47c0969a.tar.xz
rustc-ef24de24a82fe681581cc130f342363c47c0969a.zip
Merging upstream version 1.75.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_trait_selection/src/solve')
-rw-r--r--compiler/rustc_trait_selection/src/solve/assembly/mod.rs42
-rw-r--r--compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs34
-rw-r--r--compiler/rustc_trait_selection/src/solve/canonicalize.rs16
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs (renamed from compiler/rustc_trait_selection/src/solve/eval_ctxt.rs)16
-rw-r--r--compiler/rustc_trait_selection/src/solve/inspect/analyse.rs12
-rw-r--r--compiler/rustc_trait_selection/src/solve/inspect/build.rs121
-rw-r--r--compiler/rustc_trait_selection/src/solve/mod.rs7
-rw-r--r--compiler/rustc_trait_selection/src/solve/normalize.rs2
-rw-r--r--compiler/rustc_trait_selection/src/solve/project_goals/inherent_projection.rs (renamed from compiler/rustc_trait_selection/src/solve/inherent_projection.rs)0
-rw-r--r--compiler/rustc_trait_selection/src/solve/project_goals/mod.rs (renamed from compiler/rustc_trait_selection/src/solve/project_goals.rs)101
-rw-r--r--compiler/rustc_trait_selection/src/solve/project_goals/opaques.rs (renamed from compiler/rustc_trait_selection/src/solve/opaques.rs)2
-rw-r--r--compiler/rustc_trait_selection/src/solve/project_goals/weak_types.rs (renamed from compiler/rustc_trait_selection/src/solve/weak_types.rs)0
-rw-r--r--compiler/rustc_trait_selection/src/solve/search_graph.rs (renamed from compiler/rustc_trait_selection/src/solve/search_graph/mod.rs)38
-rw-r--r--compiler/rustc_trait_selection/src/solve/trait_goals.rs94
14 files changed, 291 insertions, 194 deletions
diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
index 23d2c0c4e..27d2bdead 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
@@ -37,6 +37,8 @@ pub(super) trait GoalKind<'tcx>:
fn trait_ref(self, tcx: TyCtxt<'tcx>) -> ty::TraitRef<'tcx>;
+ fn polarity(self) -> ty::ImplPolarity;
+
fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self;
fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId;
@@ -191,18 +193,26 @@ pub(super) trait GoalKind<'tcx>:
goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx>;
- /// A generator (that comes from an `async` desugaring) is known to implement
- /// `Future<Output = O>`, where `O` is given by the generator's return type
+ /// A coroutine (that comes from an `async` desugaring) is known to implement
+ /// `Future<Output = O>`, where `O` is given by the coroutine's return type
/// that was computed during type-checking.
fn consider_builtin_future_candidate(
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx>;
- /// A generator (that doesn't come from an `async` desugaring) is known to
- /// implement `Generator<R, Yield = Y, Return = O>`, given the resume, yield,
- /// and return types of the generator computed during type-checking.
- fn consider_builtin_generator_candidate(
+ /// A coroutine (that comes from a `gen` desugaring) is known to implement
+ /// `Iterator<Item = O>`, where `O` is given by the generator's yield type
+ /// that was computed during type-checking.
+ fn consider_builtin_iterator_candidate(
+ ecx: &mut EvalCtxt<'_, 'tcx>,
+ goal: Goal<'tcx, Self>,
+ ) -> QueryResult<'tcx>;
+
+ /// A coroutine (that doesn't come from an `async` or `gen` desugaring) is known to
+ /// implement `Coroutine<R, Yield = Y, Return = O>`, given the resume, yield,
+ /// and return types of the coroutine computed during type-checking.
+ fn consider_builtin_coroutine_candidate(
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx>;
@@ -410,7 +420,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
| ty::FnPtr(_)
| ty::Dynamic(_, _, _)
| ty::Closure(_, _)
- | ty::Generator(_, _, _)
+ | ty::Coroutine(_, _, _)
| ty::Never
| ty::Tuple(_) => {
let simp =
@@ -467,9 +477,9 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
ty::Alias(_, _) | ty::Placeholder(..) | ty::Error(_) => (),
// FIXME: These should ideally not exist as a self type. It would be nice for
- // the builtin auto trait impls of generators to instead directly recurse
+ // the builtin auto trait impls of coroutines to instead directly recurse
// into the witness.
- ty::GeneratorWitness(..) => (),
+ ty::CoroutineWitness(..) => (),
// These variants should not exist as a self type.
ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
@@ -552,8 +562,10 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
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 if lang_items.iterator_trait() == Some(trait_def_id) {
+ G::consider_builtin_iterator_candidate(self, goal)
+ } else if lang_items.coroutine_trait() == Some(trait_def_id) {
+ G::consider_builtin_coroutine_candidate(self, goal)
} else if lang_items.discriminant_kind_trait() == Some(trait_def_id) {
G::consider_builtin_discriminant_kind_candidate(self, goal)
} else if lang_items.destruct_trait() == Some(trait_def_id) {
@@ -620,8 +632,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
| ty::FnPtr(_)
| ty::Dynamic(..)
| ty::Closure(..)
- | ty::Generator(..)
- | ty::GeneratorWitness(..)
+ | ty::Coroutine(..)
+ | ty::CoroutineWitness(..)
| ty::Never
| ty::Tuple(_)
| ty::Param(_)
@@ -776,8 +788,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
| ty::FnPtr(_)
| ty::Alias(..)
| ty::Closure(..)
- | ty::Generator(..)
- | ty::GeneratorWitness(..)
+ | ty::Coroutine(..)
+ | ty::CoroutineWitness(..)
| ty::Never
| ty::Tuple(_)
| ty::Param(_)
diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
index 16f288045..839968b25 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
@@ -12,7 +12,7 @@ use crate::solve::EvalCtxt;
// Calculates the constituent types of a type for `auto trait` purposes.
//
-// For types with an "existential" binder, i.e. generator witnesses, we also
+// For types with an "existential" binder, i.e. coroutine witnesses, we also
// instantiate the binder with placeholders eagerly.
#[instrument(level = "debug", skip(ecx), ret)]
pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>(
@@ -57,14 +57,14 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>(
ty::Closure(_, ref args) => Ok(vec![args.as_closure().tupled_upvars_ty()]),
- ty::Generator(_, ref args, _) => {
- let generator_args = args.as_generator();
- Ok(vec![generator_args.tupled_upvars_ty(), generator_args.witness()])
+ ty::Coroutine(_, ref args, _) => {
+ let coroutine_args = args.as_coroutine();
+ Ok(vec![coroutine_args.tupled_upvars_ty(), coroutine_args.witness()])
}
- ty::GeneratorWitness(def_id, args) => Ok(ecx
+ ty::CoroutineWitness(def_id, args) => Ok(ecx
.tcx()
- .generator_hidden_types(def_id)
+ .coroutine_hidden_types(def_id)
.map(|bty| {
ecx.instantiate_binder_with_placeholders(replace_erased_lifetimes_with_bound_vars(
tcx,
@@ -124,8 +124,8 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<'tcx>(
| ty::RawPtr(..)
| ty::Char
| ty::Ref(..)
- | ty::Generator(..)
- | ty::GeneratorWitness(..)
+ | ty::Coroutine(..)
+ | ty::CoroutineWitness(..)
| ty::Array(..)
| ty::Closure(..)
| ty::Never
@@ -177,7 +177,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>(
ty::Dynamic(..)
| ty::Str
| ty::Slice(_)
- | ty::Generator(_, _, Movability::Static)
+ | ty::Coroutine(_, _, Movability::Static)
| ty::Foreign(..)
| ty::Ref(_, _, Mutability::Mut)
| ty::Adt(_, _)
@@ -194,18 +194,18 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>(
ty::Closure(_, args) => Ok(vec![args.as_closure().tupled_upvars_ty()]),
- ty::Generator(_, args, Movability::Movable) => {
- if ecx.tcx().features().generator_clone {
- let generator = args.as_generator();
- Ok(vec![generator.tupled_upvars_ty(), generator.witness()])
+ ty::Coroutine(_, args, Movability::Movable) => {
+ if ecx.tcx().features().coroutine_clone {
+ let coroutine = args.as_coroutine();
+ Ok(vec![coroutine.tupled_upvars_ty(), coroutine.witness()])
} else {
Err(NoSolution)
}
}
- ty::GeneratorWitness(def_id, args) => Ok(ecx
+ ty::CoroutineWitness(def_id, args) => Ok(ecx
.tcx()
- .generator_hidden_types(def_id)
+ .coroutine_hidden_types(def_id)
.map(|bty| {
ecx.instantiate_binder_with_placeholders(replace_erased_lifetimes_with_bound_vars(
ecx.tcx(),
@@ -278,8 +278,8 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<'tcx>(
| ty::RawPtr(_)
| ty::Ref(_, _, _)
| ty::Dynamic(_, _, _)
- | ty::Generator(_, _, _)
- | ty::GeneratorWitness(..)
+ | ty::Coroutine(_, _, _)
+ | ty::CoroutineWitness(..)
| ty::Never
| ty::Tuple(_)
| ty::Alias(_, _)
diff --git a/compiler/rustc_trait_selection/src/solve/canonicalize.rs b/compiler/rustc_trait_selection/src/solve/canonicalize.rs
index aa92b924e..377ae1b4e 100644
--- a/compiler/rustc_trait_selection/src/solve/canonicalize.rs
+++ b/compiler/rustc_trait_selection/src/solve/canonicalize.rs
@@ -224,12 +224,20 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> {
let kind = match *r {
ty::ReLateBound(..) => return r,
- ty::ReStatic => match self.canonicalize_mode {
+ // We may encounter `ReStatic` in item signatures or the hidden type
+ // of an opaque. `ReErased` should only be encountered in the hidden
+ // type of an opaque for regions that are ignored for the purposes of
+ // captures.
+ //
+ // FIXME: We should investigate the perf implications of not uniquifying
+ // `ReErased`. We may be able to short-circuit registering region
+ // obligations if we encounter a `ReErased` on one side, for example.
+ ty::ReStatic | ty::ReErased => match self.canonicalize_mode {
CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT),
CanonicalizeMode::Response { .. } => return r,
},
- ty::ReErased | ty::ReFree(_) | ty::ReEarlyBound(_) => match self.canonicalize_mode {
+ ty::ReFree(_) | ty::ReEarlyBound(_) => match self.canonicalize_mode {
CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT),
CanonicalizeMode::Response { .. } => bug!("unexpected region in response: {r:?}"),
},
@@ -329,8 +337,8 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> {
| ty::FnPtr(_)
| ty::Dynamic(_, _, _)
| ty::Closure(_, _)
- | ty::Generator(_, _, _)
- | ty::GeneratorWitness(..)
+ | ty::Coroutine(_, _, _)
+ | ty::CoroutineWitness(..)
| ty::Never
| ty::Tuple(_)
| ty::Alias(_, _)
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs
index 066129d8e..70235b710 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs
@@ -119,25 +119,11 @@ impl NestedGoals<'_> {
#[derive(PartialEq, Eq, Debug, Hash, HashStable, Clone, Copy)]
pub enum GenerateProofTree {
- Yes(UseGlobalCache),
+ Yes,
IfEnabled,
Never,
}
-#[derive(PartialEq, Eq, Debug, Hash, HashStable, Clone, Copy)]
-pub enum UseGlobalCache {
- Yes,
- No,
-}
-impl UseGlobalCache {
- pub fn from_bool(use_cache: bool) -> Self {
- match use_cache {
- true => UseGlobalCache::Yes,
- false => UseGlobalCache::No,
- }
- }
-}
-
pub trait InferCtxtEvalExt<'tcx> {
/// Evaluates a goal from **outside** of the trait solver.
///
diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
index 15c8d9e5b..69bfdd468 100644
--- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
+++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
@@ -17,7 +17,7 @@ use rustc_middle::traits::solve::{Certainty, Goal};
use rustc_middle::ty;
use crate::solve::inspect::ProofTreeBuilder;
-use crate::solve::{GenerateProofTree, InferCtxtEvalExt, UseGlobalCache};
+use crate::solve::{GenerateProofTree, InferCtxtEvalExt};
pub struct InspectGoal<'a, 'tcx> {
infcx: &'a InferCtxt<'tcx>,
@@ -82,8 +82,7 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
}
for &goal in &instantiated_goals {
- let (_, proof_tree) =
- infcx.evaluate_root_goal(goal, GenerateProofTree::Yes(UseGlobalCache::No));
+ let (_, proof_tree) = infcx.evaluate_root_goal(goal, GenerateProofTree::Yes);
let proof_tree = proof_tree.unwrap();
visitor.visit_goal(&InspectGoal::new(
infcx,
@@ -169,11 +168,11 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
let mut candidates = vec![];
let last_eval_step = match self.evaluation.evaluation.kind {
inspect::CanonicalGoalEvaluationKind::Overflow
- | inspect::CanonicalGoalEvaluationKind::CacheHit(_) => {
+ | inspect::CanonicalGoalEvaluationKind::CycleInStack => {
warn!("unexpected root evaluation: {:?}", self.evaluation);
return vec![];
}
- inspect::CanonicalGoalEvaluationKind::Uncached { ref revisions } => {
+ inspect::CanonicalGoalEvaluationKind::Evaluation { ref revisions } => {
if let Some(last) = revisions.last() {
last
} else {
@@ -227,8 +226,7 @@ impl<'tcx> ProofTreeInferCtxtExt<'tcx> for InferCtxt<'tcx> {
goal: Goal<'tcx, ty::Predicate<'tcx>>,
visitor: &mut V,
) -> ControlFlow<V::BreakTy> {
- let (_, proof_tree) =
- self.evaluate_root_goal(goal, GenerateProofTree::Yes(UseGlobalCache::No));
+ let (_, proof_tree) = self.evaluate_root_goal(goal, GenerateProofTree::Yes);
let proof_tree = proof_tree.unwrap();
visitor.visit_goal(&InspectGoal::new(self, 0, &proof_tree))
}
diff --git a/compiler/rustc_trait_selection/src/solve/inspect/build.rs b/compiler/rustc_trait_selection/src/solve/inspect/build.rs
index 2eba98b02..088455b38 100644
--- a/compiler/rustc_trait_selection/src/solve/inspect/build.rs
+++ b/compiler/rustc_trait_selection/src/solve/inspect/build.rs
@@ -3,6 +3,8 @@
//! This code is *a bit* of a mess and can hopefully be
//! mostly ignored. For a general overview of how it works,
//! see the comment on [ProofTreeBuilder].
+use std::mem;
+
use rustc_middle::traits::query::NoSolution;
use rustc_middle::traits::solve::{
CanonicalInput, Certainty, Goal, IsNormalizesToHack, QueryInput, QueryResult,
@@ -10,7 +12,6 @@ use rustc_middle::traits::solve::{
use rustc_middle::ty::{self, TyCtxt};
use rustc_session::config::DumpSolverProofTree;
-use crate::solve::eval_ctxt::UseGlobalCache;
use crate::solve::{self, inspect, EvalCtxt, GenerateProofTree};
/// The core data structure when building proof trees.
@@ -34,12 +35,7 @@ use crate::solve::{self, inspect, EvalCtxt, GenerateProofTree};
/// is called to recursively convert the whole structure to a
/// finished proof tree.
pub(in crate::solve) struct ProofTreeBuilder<'tcx> {
- state: Option<Box<BuilderData<'tcx>>>,
-}
-
-struct BuilderData<'tcx> {
- tree: DebugSolver<'tcx>,
- use_global_cache: UseGlobalCache,
+ state: Option<Box<DebugSolver<'tcx>>>,
}
/// The current state of the proof tree builder, at most places
@@ -118,36 +114,46 @@ pub(in crate::solve) enum WipGoalEvaluationKind<'tcx> {
Nested { is_normalizes_to_hack: IsNormalizesToHack },
}
-#[derive(Eq, PartialEq, Debug)]
-pub(in crate::solve) enum WipCanonicalGoalEvaluationKind {
+#[derive(Eq, PartialEq)]
+pub(in crate::solve) enum WipCanonicalGoalEvaluationKind<'tcx> {
Overflow,
- CacheHit(inspect::CacheHit),
+ CycleInStack,
+ Interned { revisions: &'tcx [inspect::GoalEvaluationStep<'tcx>] },
+}
+
+impl std::fmt::Debug for WipCanonicalGoalEvaluationKind<'_> {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ match self {
+ Self::Overflow => write!(f, "Overflow"),
+ Self::CycleInStack => write!(f, "CycleInStack"),
+ Self::Interned { revisions: _ } => f.debug_struct("Interned").finish_non_exhaustive(),
+ }
+ }
}
#[derive(Eq, PartialEq, Debug)]
struct WipCanonicalGoalEvaluation<'tcx> {
goal: CanonicalInput<'tcx>,
- kind: Option<WipCanonicalGoalEvaluationKind>,
+ kind: Option<WipCanonicalGoalEvaluationKind<'tcx>>,
+ /// Only used for uncached goals. After we finished evaluating
+ /// the goal, this is interned and moved into `kind`.
revisions: Vec<WipGoalEvaluationStep<'tcx>>,
result: Option<QueryResult<'tcx>>,
}
impl<'tcx> WipCanonicalGoalEvaluation<'tcx> {
fn finalize(self) -> inspect::CanonicalGoalEvaluation<'tcx> {
- let kind = match self.kind {
- Some(WipCanonicalGoalEvaluationKind::Overflow) => {
+ assert!(self.revisions.is_empty());
+ let kind = match self.kind.unwrap() {
+ WipCanonicalGoalEvaluationKind::Overflow => {
inspect::CanonicalGoalEvaluationKind::Overflow
}
- Some(WipCanonicalGoalEvaluationKind::CacheHit(hit)) => {
- inspect::CanonicalGoalEvaluationKind::CacheHit(hit)
+ WipCanonicalGoalEvaluationKind::CycleInStack => {
+ inspect::CanonicalGoalEvaluationKind::CycleInStack
+ }
+ WipCanonicalGoalEvaluationKind::Interned { revisions } => {
+ inspect::CanonicalGoalEvaluationKind::Evaluation { revisions }
}
- None => inspect::CanonicalGoalEvaluationKind::Uncached {
- revisions: self
- .revisions
- .into_iter()
- .map(WipGoalEvaluationStep::finalize)
- .collect(),
- },
};
inspect::CanonicalGoalEvaluation { goal: self.goal, kind, result: self.result.unwrap() }
@@ -226,33 +232,20 @@ impl<'tcx> WipProbeStep<'tcx> {
}
impl<'tcx> ProofTreeBuilder<'tcx> {
- fn new(
- state: impl Into<DebugSolver<'tcx>>,
- use_global_cache: UseGlobalCache,
- ) -> ProofTreeBuilder<'tcx> {
- ProofTreeBuilder {
- state: Some(Box::new(BuilderData { tree: state.into(), use_global_cache })),
- }
+ fn new(state: impl Into<DebugSolver<'tcx>>) -> ProofTreeBuilder<'tcx> {
+ ProofTreeBuilder { state: Some(Box::new(state.into())) }
}
fn nested<T: Into<DebugSolver<'tcx>>>(&self, state: impl FnOnce() -> T) -> Self {
- match &self.state {
- Some(prev_state) => Self {
- state: Some(Box::new(BuilderData {
- tree: state().into(),
- use_global_cache: prev_state.use_global_cache,
- })),
- },
- None => Self { state: None },
- }
+ ProofTreeBuilder { state: self.state.as_ref().map(|_| Box::new(state().into())) }
}
fn as_mut(&mut self) -> Option<&mut DebugSolver<'tcx>> {
- self.state.as_mut().map(|boxed| &mut boxed.tree)
+ self.state.as_deref_mut()
}
pub fn finalize(self) -> Option<inspect::GoalEvaluation<'tcx>> {
- match self.state?.tree {
+ match *self.state? {
DebugSolver::GoalEvaluation(wip_goal_evaluation) => {
Some(wip_goal_evaluation.finalize())
}
@@ -260,13 +253,6 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
}
}
- pub fn use_global_cache(&self) -> bool {
- self.state
- .as_ref()
- .map(|state| matches!(state.use_global_cache, UseGlobalCache::Yes))
- .unwrap_or(true)
- }
-
pub fn new_maybe_root(
tcx: TyCtxt<'tcx>,
generate_proof_tree: GenerateProofTree,
@@ -276,10 +262,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
GenerateProofTree::IfEnabled => {
let opts = &tcx.sess.opts.unstable_opts;
match opts.dump_solver_proof_tree {
- DumpSolverProofTree::Always => {
- let use_cache = opts.dump_solver_proof_tree_use_cache.unwrap_or(true);
- ProofTreeBuilder::new_root(UseGlobalCache::from_bool(use_cache))
- }
+ DumpSolverProofTree::Always => ProofTreeBuilder::new_root(),
// `OnError` is handled by reevaluating goals in error
// reporting with `GenerateProofTree::Yes`.
DumpSolverProofTree::OnError | DumpSolverProofTree::Never => {
@@ -287,12 +270,12 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
}
}
}
- GenerateProofTree::Yes(use_cache) => ProofTreeBuilder::new_root(use_cache),
+ GenerateProofTree::Yes => ProofTreeBuilder::new_root(),
}
}
- pub fn new_root(use_global_cache: UseGlobalCache) -> ProofTreeBuilder<'tcx> {
- ProofTreeBuilder::new(DebugSolver::Root, use_global_cache)
+ pub fn new_root() -> ProofTreeBuilder<'tcx> {
+ ProofTreeBuilder::new(DebugSolver::Root)
}
pub fn new_noop() -> ProofTreeBuilder<'tcx> {
@@ -336,9 +319,27 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
})
}
+ pub fn finalize_evaluation(
+ &mut self,
+ tcx: TyCtxt<'tcx>,
+ ) -> Option<&'tcx [inspect::GoalEvaluationStep<'tcx>]> {
+ self.as_mut().map(|this| match this {
+ DebugSolver::CanonicalGoalEvaluation(evaluation) => {
+ let revisions = mem::take(&mut evaluation.revisions)
+ .into_iter()
+ .map(WipGoalEvaluationStep::finalize);
+ let revisions = &*tcx.arena.alloc_from_iter(revisions);
+ let kind = WipCanonicalGoalEvaluationKind::Interned { revisions };
+ assert_eq!(evaluation.kind.replace(kind), None);
+ revisions
+ }
+ _ => unreachable!(),
+ })
+ }
+
pub fn canonical_goal_evaluation(&mut self, canonical_goal_evaluation: ProofTreeBuilder<'tcx>) {
if let Some(this) = self.as_mut() {
- match (this, canonical_goal_evaluation.state.unwrap().tree) {
+ match (this, *canonical_goal_evaluation.state.unwrap()) {
(
DebugSolver::GoalEvaluation(goal_evaluation),
DebugSolver::CanonicalGoalEvaluation(canonical_goal_evaluation),
@@ -348,7 +349,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
}
}
- pub fn goal_evaluation_kind(&mut self, kind: WipCanonicalGoalEvaluationKind) {
+ pub fn goal_evaluation_kind(&mut self, kind: WipCanonicalGoalEvaluationKind<'tcx>) {
if let Some(this) = self.as_mut() {
match this {
DebugSolver::CanonicalGoalEvaluation(canonical_goal_evaluation) => {
@@ -372,7 +373,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
}
pub fn goal_evaluation(&mut self, goal_evaluation: ProofTreeBuilder<'tcx>) {
if let Some(this) = self.as_mut() {
- match (this, goal_evaluation.state.unwrap().tree) {
+ match (this, *goal_evaluation.state.unwrap()) {
(
DebugSolver::AddedGoalsEvaluation(WipAddedGoalsEvaluation {
evaluations, ..
@@ -396,7 +397,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
}
pub fn goal_evaluation_step(&mut self, goal_evaluation_step: ProofTreeBuilder<'tcx>) {
if let Some(this) = self.as_mut() {
- match (this, goal_evaluation_step.state.unwrap().tree) {
+ match (this, *goal_evaluation_step.state.unwrap()) {
(
DebugSolver::CanonicalGoalEvaluation(canonical_goal_evaluations),
DebugSolver::GoalEvaluationStep(goal_evaluation_step),
@@ -444,7 +445,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
pub fn finish_probe(&mut self, probe: ProofTreeBuilder<'tcx>) {
if let Some(this) = self.as_mut() {
- match (this, probe.state.unwrap().tree) {
+ match (this, *probe.state.unwrap()) {
(
DebugSolver::Probe(WipProbe { steps, .. })
| DebugSolver::GoalEvaluationStep(WipGoalEvaluationStep {
@@ -486,7 +487,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
pub fn added_goals_evaluation(&mut self, added_goals_evaluation: ProofTreeBuilder<'tcx>) {
if let Some(this) = self.as_mut() {
- match (this, added_goals_evaluation.state.unwrap().tree) {
+ match (this, *added_goals_evaluation.state.unwrap()) {
(
DebugSolver::GoalEvaluationStep(WipGoalEvaluationStep {
evaluation: WipProbe { steps, .. },
diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs
index 77a3b5e12..dba5369fa 100644
--- a/compiler/rustc_trait_selection/src/solve/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/mod.rs
@@ -32,18 +32,13 @@ mod assembly;
mod canonicalize;
mod eval_ctxt;
mod fulfill;
-mod inherent_projection;
pub mod inspect;
mod normalize;
-mod opaques;
mod project_goals;
mod search_graph;
mod trait_goals;
-mod weak_types;
-pub use eval_ctxt::{
- EvalCtxt, GenerateProofTree, InferCtxtEvalExt, InferCtxtSelectExt, UseGlobalCache,
-};
+pub use eval_ctxt::{EvalCtxt, GenerateProofTree, InferCtxtEvalExt, InferCtxtSelectExt};
pub use fulfill::FulfillmentCtxt;
pub(crate) use normalize::{deeply_normalize, deeply_normalize_with_skipped_universes};
diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs
index 872f0c879..b0a348985 100644
--- a/compiler/rustc_trait_selection/src/solve/normalize.rs
+++ b/compiler/rustc_trait_selection/src/solve/normalize.rs
@@ -129,7 +129,7 @@ impl<'tcx> NormalizationFolder<'_, 'tcx> {
self.at.cause.clone(),
self.at.param_env,
ty::ProjectionPredicate {
- projection_ty: tcx.mk_alias_ty(uv.def, uv.args),
+ projection_ty: AliasTy::new(tcx, uv.def, uv.args),
term: new_infer_ct.into(),
},
);
diff --git a/compiler/rustc_trait_selection/src/solve/inherent_projection.rs b/compiler/rustc_trait_selection/src/solve/project_goals/inherent_projection.rs
index 28fe59b7f..28fe59b7f 100644
--- a/compiler/rustc_trait_selection/src/solve/inherent_projection.rs
+++ b/compiler/rustc_trait_selection/src/solve/project_goals/inherent_projection.rs
diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals/mod.rs
index 0f9d36342..240141065 100644
--- a/compiler/rustc_trait_selection/src/solve/project_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/project_goals/mod.rs
@@ -18,6 +18,10 @@ use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::ty::{ToPredicate, TypeVisitableExt};
use rustc_span::{sym, ErrorGuaranteed, DUMMY_SP};
+mod inherent_projection;
+mod opaques;
+mod weak_types;
+
impl<'tcx> EvalCtxt<'_, 'tcx> {
#[instrument(level = "debug", skip(self), ret)]
pub(super) fn compute_projection_goal(
@@ -97,6 +101,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
self.projection_ty.trait_ref(tcx)
}
+ fn polarity(self) -> ty::ImplPolarity {
+ ty::ImplPolarity::Positive
+ }
+
fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
self.with_self_ty(tcx, self_ty)
}
@@ -346,14 +354,16 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
ty::TraitRef::from_lang_item(tcx, LangItem::Sized, DUMMY_SP, [output])
});
- let pred = ty::Clause::from_projection_clause(
- tcx,
- tupled_inputs_and_output.map_bound(|(inputs, output)| ty::ProjectionPredicate {
- projection_ty: tcx
- .mk_alias_ty(goal.predicate.def_id(), [goal.predicate.self_ty(), inputs]),
+ let pred = tupled_inputs_and_output
+ .map_bound(|(inputs, output)| ty::ProjectionPredicate {
+ projection_ty: ty::AliasTy::new(
+ tcx,
+ goal.predicate.def_id(),
+ [goal.predicate.self_ty(), inputs],
+ ),
term: output.into(),
- }),
- );
+ })
+ .to_predicate(tcx);
// A built-in `Fn` impl only holds if the output is sized.
// (FIXME: technically we only need to check this if the type is a fn ptr...)
@@ -386,8 +396,8 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
| ty::FnPtr(..)
| ty::Closure(..)
| ty::Infer(ty::IntVar(..) | ty::FloatVar(..))
- | ty::Generator(..)
- | ty::GeneratorWitness(..)
+ | ty::Coroutine(..)
+ | ty::CoroutineWitness(..)
| ty::Never
| ty::Foreign(..) => tcx.types.unit,
@@ -453,70 +463,103 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx> {
let self_ty = goal.predicate.self_ty();
- let ty::Generator(def_id, args, _) = *self_ty.kind() else {
+ let ty::Coroutine(def_id, args, _) = *self_ty.kind() else {
return Err(NoSolution);
};
- // Generators are not futures unless they come from `async` desugaring
+ // Coroutines are not futures unless they come from `async` desugaring
let tcx = ecx.tcx();
- if !tcx.generator_is_async(def_id) {
+ if !tcx.coroutine_is_async(def_id) {
return Err(NoSolution);
}
- let term = args.as_generator().return_ty().into();
+ let term = args.as_coroutine().return_ty().into();
Self::consider_implied_clause(
ecx,
goal,
ty::ProjectionPredicate {
- projection_ty: ecx.tcx().mk_alias_ty(goal.predicate.def_id(), [self_ty]),
+ projection_ty: ty::AliasTy::new(ecx.tcx(), goal.predicate.def_id(), [self_ty]),
term,
}
.to_predicate(tcx),
// Technically, we need to check that the future type is Sized,
+ // but that's already proven by the coroutine being WF.
+ [],
+ )
+ }
+
+ fn consider_builtin_iterator_candidate(
+ ecx: &mut EvalCtxt<'_, 'tcx>,
+ goal: Goal<'tcx, Self>,
+ ) -> QueryResult<'tcx> {
+ let self_ty = goal.predicate.self_ty();
+ let ty::Coroutine(def_id, args, _) = *self_ty.kind() else {
+ return Err(NoSolution);
+ };
+
+ // Coroutines are not Iterators unless they come from `gen` desugaring
+ let tcx = ecx.tcx();
+ if !tcx.coroutine_is_gen(def_id) {
+ return Err(NoSolution);
+ }
+
+ let term = args.as_coroutine().yield_ty().into();
+
+ Self::consider_implied_clause(
+ ecx,
+ goal,
+ ty::ProjectionPredicate {
+ projection_ty: ty::AliasTy::new(ecx.tcx(), goal.predicate.def_id(), [self_ty]),
+ term,
+ }
+ .to_predicate(tcx),
+ // Technically, we need to check that the iterator type is Sized,
// but that's already proven by the generator being WF.
[],
)
}
- fn consider_builtin_generator_candidate(
+ fn consider_builtin_coroutine_candidate(
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx> {
let self_ty = goal.predicate.self_ty();
- let ty::Generator(def_id, args, _) = *self_ty.kind() else {
+ let ty::Coroutine(def_id, args, _) = *self_ty.kind() else {
return Err(NoSolution);
};
- // `async`-desugared generators do not implement the generator trait
+ // `async`-desugared coroutines do not implement the coroutine trait
let tcx = ecx.tcx();
- if tcx.generator_is_async(def_id) {
+ if !tcx.is_general_coroutine(def_id) {
return Err(NoSolution);
}
- let generator = args.as_generator();
+ let coroutine = args.as_coroutine();
let name = tcx.associated_item(goal.predicate.def_id()).name;
let term = if name == sym::Return {
- generator.return_ty().into()
+ coroutine.return_ty().into()
} else if name == sym::Yield {
- generator.yield_ty().into()
+ coroutine.yield_ty().into()
} else {
- bug!("unexpected associated item `<{self_ty} as Generator>::{name}`")
+ bug!("unexpected associated item `<{self_ty} as Coroutine>::{name}`")
};
Self::consider_implied_clause(
ecx,
goal,
ty::ProjectionPredicate {
- projection_ty: ecx
- .tcx()
- .mk_alias_ty(goal.predicate.def_id(), [self_ty, generator.resume_ty()]),
+ projection_ty: ty::AliasTy::new(
+ ecx.tcx(),
+ goal.predicate.def_id(),
+ [self_ty, coroutine.resume_ty()],
+ ),
term,
}
.to_predicate(tcx),
- // Technically, we need to check that the future type is Sized,
- // but that's already proven by the generator being WF.
+ // Technically, we need to check that the coroutine type is Sized,
+ // but that's already proven by the coroutine being WF.
[],
)
}
@@ -553,8 +596,8 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
| ty::FnPtr(..)
| ty::Closure(..)
| ty::Infer(ty::IntVar(..) | ty::FloatVar(..))
- | ty::Generator(..)
- | ty::GeneratorWitness(..)
+ | ty::Coroutine(..)
+ | ty::CoroutineWitness(..)
| ty::Never
| ty::Foreign(..)
| ty::Adt(_, _)
diff --git a/compiler/rustc_trait_selection/src/solve/opaques.rs b/compiler/rustc_trait_selection/src/solve/project_goals/opaques.rs
index f08adc020..ebd129f32 100644
--- a/compiler/rustc_trait_selection/src/solve/opaques.rs
+++ b/compiler/rustc_trait_selection/src/solve/project_goals/opaques.rs
@@ -7,7 +7,7 @@ use rustc_middle::traits::Reveal;
use rustc_middle::ty;
use rustc_middle::ty::util::NotUniqueParam;
-use super::{EvalCtxt, SolverMode};
+use crate::solve::{EvalCtxt, SolverMode};
impl<'tcx> EvalCtxt<'_, 'tcx> {
pub(super) fn normalize_opaque_type(
diff --git a/compiler/rustc_trait_selection/src/solve/weak_types.rs b/compiler/rustc_trait_selection/src/solve/project_goals/weak_types.rs
index 54de32cf6..54de32cf6 100644
--- a/compiler/rustc_trait_selection/src/solve/weak_types.rs
+++ b/compiler/rustc_trait_selection/src/solve/project_goals/weak_types.rs
diff --git a/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs b/compiler/rustc_trait_selection/src/solve/search_graph.rs
index 33513f6bd..7ffa1d7d3 100644
--- a/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/search_graph.rs
@@ -6,7 +6,6 @@ use rustc_data_structures::fx::FxHashSet;
use rustc_index::Idx;
use rustc_index::IndexVec;
use rustc_middle::dep_graph::dep_kinds;
-use rustc_middle::traits::solve::inspect::CacheHit;
use rustc_middle::traits::solve::CacheData;
use rustc_middle::traits::solve::{CanonicalInput, Certainty, EvaluationCache, QueryResult};
use rustc_middle::ty::TyCtxt;
@@ -191,8 +190,8 @@ impl<'tcx> SearchGraph<'tcx> {
};
// Try to fetch the goal from the global cache.
- if inspect.use_global_cache() {
- if let Some(CacheData { result, reached_depth, encountered_overflow }) =
+ 'global: {
+ let Some(CacheData { result, proof_tree, reached_depth, encountered_overflow }) =
self.global_cache(tcx).get(
tcx,
input,
@@ -201,13 +200,26 @@ impl<'tcx> SearchGraph<'tcx> {
},
available_depth,
)
- {
- inspect.goal_evaluation_kind(inspect::WipCanonicalGoalEvaluationKind::CacheHit(
- CacheHit::Global,
- ));
- self.on_cache_hit(reached_depth, encountered_overflow);
- return result;
+ else {
+ break 'global;
+ };
+
+ // If we're building a proof tree and the current cache entry does not
+ // contain a proof tree, we do not use the entry but instead recompute
+ // the goal. We simply overwrite the existing entry once we're done,
+ // caching the proof tree.
+ if !inspect.is_noop() {
+ if let Some(revisions) = proof_tree {
+ inspect.goal_evaluation_kind(
+ inspect::WipCanonicalGoalEvaluationKind::Interned { revisions },
+ );
+ } else {
+ break 'global;
+ }
}
+
+ self.on_cache_hit(reached_depth, encountered_overflow);
+ return result;
}
// Check whether we're in a cycle.
@@ -238,9 +250,7 @@ impl<'tcx> SearchGraph<'tcx> {
// Finally we can return either the provisional response for that goal if we have a
// coinductive cycle or an ambiguous result if the cycle is inductive.
Entry::Occupied(entry) => {
- inspect.goal_evaluation_kind(inspect::WipCanonicalGoalEvaluationKind::CacheHit(
- CacheHit::Provisional,
- ));
+ inspect.goal_evaluation_kind(inspect::WipCanonicalGoalEvaluationKind::CycleInStack);
let stack_depth = *entry.get();
debug!("encountered cycle with depth {stack_depth:?}");
@@ -329,6 +339,8 @@ impl<'tcx> SearchGraph<'tcx> {
(current_entry, result)
});
+ let proof_tree = inspect.finalize_evaluation(tcx);
+
// We're now done with this goal. In case this goal is involved in a larger cycle
// do not remove it from the provisional cache and update its provisional result.
// We only add the root of cycles to the global cache.
@@ -346,7 +358,9 @@ impl<'tcx> SearchGraph<'tcx> {
// more details.
let reached_depth = final_entry.reached_depth.as_usize() - self.stack.len();
self.global_cache(tcx).insert(
+ tcx,
input,
+ proof_tree,
reached_depth,
final_entry.encountered_overflow,
final_entry.cycle_participants,
diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
index 8055c63b9..a0e2ad6e2 100644
--- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
@@ -22,6 +22,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
self.trait_ref
}
+ fn polarity(self) -> ty::ImplPolarity {
+ self.polarity
+ }
+
fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
self.with_self_ty(tcx, self_ty)
}
@@ -136,12 +140,13 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
// `assemble_candidates_after_normalizing_self_ty`, and we'd
// just be registering an identical candidate here.
//
- // Returning `Err(NoSolution)` here is ok in `SolverMode::Coherence`
- // since we'll always be registering an ambiguous candidate in
+ // We always return `Err(NoSolution)` here in `SolverMode::Coherence`
+ // since we'll always register an ambiguous candidate in
// `assemble_candidates_after_normalizing_self_ty` due to normalizing
// the TAIT.
if let ty::Alias(ty::Opaque, opaque_ty) = goal.predicate.self_ty().kind() {
if matches!(goal.param_env.reveal(), Reveal::All)
+ || matches!(ecx.solver_mode(), SolverMode::Coherence)
|| opaque_ty
.def_id
.as_local()
@@ -237,14 +242,25 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx> {
- if goal.predicate.polarity != ty::ImplPolarity::Positive {
- return Err(NoSolution);
- }
-
- if let ty::FnPtr(..) = goal.predicate.self_ty().kind() {
- ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
- } else {
- Err(NoSolution)
+ let self_ty = goal.predicate.self_ty();
+ match goal.predicate.polarity {
+ ty::ImplPolarity::Positive => {
+ if self_ty.is_fn_ptr() {
+ ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
+ } else {
+ Err(NoSolution)
+ }
+ }
+ ty::ImplPolarity::Negative => {
+ // If a type is rigid and not a fn ptr, then we know for certain
+ // that it does *not* implement `FnPtr`.
+ if !self_ty.is_fn_ptr() && self_ty.is_known_rigid() {
+ ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
+ } else {
+ Err(NoSolution)
+ }
+ }
+ ty::ImplPolarity::Reservation => bug!(),
}
}
@@ -318,23 +334,47 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
return Err(NoSolution);
}
- let ty::Generator(def_id, _, _) = *goal.predicate.self_ty().kind() else {
+ let ty::Coroutine(def_id, _, _) = *goal.predicate.self_ty().kind() else {
return Err(NoSolution);
};
- // Generators are not futures unless they come from `async` desugaring
+ // Coroutines are not futures unless they come from `async` desugaring
let tcx = ecx.tcx();
- if !tcx.generator_is_async(def_id) {
+ if !tcx.coroutine_is_async(def_id) {
return Err(NoSolution);
}
- // Async generator unconditionally implement `Future`
+ // Async coroutine unconditionally implement `Future`
// Technically, we need to check that the future output type is Sized,
- // but that's already proven by the generator being WF.
+ // but that's already proven by the coroutine being WF.
+ ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
+ }
+
+ fn consider_builtin_iterator_candidate(
+ ecx: &mut EvalCtxt<'_, 'tcx>,
+ goal: Goal<'tcx, Self>,
+ ) -> QueryResult<'tcx> {
+ if goal.predicate.polarity != ty::ImplPolarity::Positive {
+ return Err(NoSolution);
+ }
+
+ let ty::Coroutine(def_id, _, _) = *goal.predicate.self_ty().kind() else {
+ return Err(NoSolution);
+ };
+
+ // Coroutines are not iterators unless they come from `gen` desugaring
+ let tcx = ecx.tcx();
+ if !tcx.coroutine_is_gen(def_id) {
+ return Err(NoSolution);
+ }
+
+ // Gen coroutines unconditionally implement `Iterator`
+ // Technically, we need to check that the iterator output type is Sized,
+ // but that's already proven by the coroutines being WF.
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
}
- fn consider_builtin_generator_candidate(
+ fn consider_builtin_coroutine_candidate(
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx> {
@@ -343,24 +383,24 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
}
let self_ty = goal.predicate.self_ty();
- let ty::Generator(def_id, args, _) = *self_ty.kind() else {
+ let ty::Coroutine(def_id, args, _) = *self_ty.kind() else {
return Err(NoSolution);
};
- // `async`-desugared generators do not implement the generator trait
+ // `async`-desugared coroutines do not implement the coroutine trait
let tcx = ecx.tcx();
- if tcx.generator_is_async(def_id) {
+ if !tcx.is_general_coroutine(def_id) {
return Err(NoSolution);
}
- let generator = args.as_generator();
+ let coroutine = args.as_coroutine();
Self::consider_implied_clause(
ecx,
goal,
- ty::TraitRef::new(tcx, goal.predicate.def_id(), [self_ty, generator.resume_ty()])
+ ty::TraitRef::new(tcx, goal.predicate.def_id(), [self_ty, coroutine.resume_ty()])
.to_predicate(tcx),
- // Technically, we need to check that the generator types are Sized,
- // but that's already proven by the generator being WF.
+ // Technically, we need to check that the coroutine types are Sized,
+ // but that's already proven by the coroutine being WF.
[],
)
}
@@ -843,10 +883,10 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
ty::Infer(_) | ty::Bound(_, _) => bug!("unexpected type `{self_ty}`"),
- // Generators have one special built-in candidate, `Unpin`, which
+ // Coroutines have one special built-in candidate, `Unpin`, which
// takes precedence over the structural auto trait candidate being
// assembled.
- ty::Generator(_, _, movability)
+ ty::Coroutine(_, _, movability)
if Some(goal.predicate.def_id()) == self.tcx().lang_items().unpin_trait() =>
{
match movability {
@@ -878,8 +918,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
| ty::FnDef(_, _)
| ty::FnPtr(_)
| ty::Closure(_, _)
- | ty::Generator(_, _, _)
- | ty::GeneratorWitness(..)
+ | ty::Coroutine(_, _, _)
+ | ty::CoroutineWitness(..)
| ty::Never
| ty::Tuple(_)
| ty::Adt(_, _)