summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_trait_selection/src/solve/assembly
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-19 09:26:03 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-19 09:26:03 +0000
commit9918693037dce8aa4bb6f08741b6812923486c18 (patch)
tree21d2b40bec7e6a7ea664acee056eb3d08e15a1cf /compiler/rustc_trait_selection/src/solve/assembly
parentReleasing progress-linux version 1.75.0+dfsg1-5~progress7.99u1. (diff)
downloadrustc-9918693037dce8aa4bb6f08741b6812923486c18.tar.xz
rustc-9918693037dce8aa4bb6f08741b6812923486c18.zip
Merging upstream version 1.76.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_trait_selection/src/solve/assembly')
-rw-r--r--compiler/rustc_trait_selection/src/solve/assembly/mod.rs94
-rw-r--r--compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs10
2 files changed, 57 insertions, 47 deletions
diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
index 27d2bdead..81a766f24 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
@@ -1,6 +1,7 @@
//! Code shared by trait and projection goals for candidate assembly.
use super::{EvalCtxt, SolverMode};
+use crate::solve::GoalSource;
use crate::traits::coherence;
use rustc_hir::def_id::DefId;
use rustc_infer::traits::query::NoSolution;
@@ -37,8 +38,6 @@ 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;
@@ -64,7 +63,9 @@ pub(super) trait GoalKind<'tcx>:
requirements: impl IntoIterator<Item = Goal<'tcx, ty::Predicate<'tcx>>>,
) -> QueryResult<'tcx> {
Self::probe_and_match_goal_against_assumption(ecx, goal, assumption, |ecx| {
- ecx.add_goals(requirements);
+ // FIXME(-Znext-solver=coinductive): check whether this should be
+ // `GoalSource::ImplWhereBound` for any caller.
+ ecx.add_goals(GoalSource::Misc, requirements);
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
})
}
@@ -96,12 +97,16 @@ pub(super) trait GoalKind<'tcx>:
let ty::Dynamic(bounds, _, _) = *goal.predicate.self_ty().kind() else {
bug!("expected object type in `consider_object_bound_candidate`");
};
- ecx.add_goals(structural_traits::predicates_for_object_candidate(
- &ecx,
- goal.param_env,
- goal.predicate.trait_ref(tcx),
- bounds,
- ));
+ // FIXME(-Znext-solver=coinductive): Should this be `GoalSource::ImplWhereBound`?
+ ecx.add_goals(
+ GoalSource::Misc,
+ structural_traits::predicates_for_object_candidate(
+ ecx,
+ goal.param_env,
+ goal.predicate.trait_ref(tcx),
+ bounds,
+ ),
+ );
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
})
}
@@ -110,7 +115,7 @@ pub(super) trait GoalKind<'tcx>:
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
impl_def_id: DefId,
- ) -> QueryResult<'tcx>;
+ ) -> Result<Candidate<'tcx>, NoSolution>;
/// If the predicate contained an error, we want to avoid emitting unnecessary trait
/// errors but still want to emit errors for other trait goals. We have some special
@@ -209,6 +214,11 @@ pub(super) trait GoalKind<'tcx>:
goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx>;
+ fn consider_builtin_async_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.
@@ -263,7 +273,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
) -> Vec<Candidate<'tcx>> {
debug_assert_eq!(goal, self.resolve_vars_if_possible(goal));
if let Some(ambig) = self.assemble_self_ty_infer_ambiguity_response(goal) {
- return ambig;
+ return vec![ambig];
}
let mut candidates = self.assemble_candidates_via_self_ty(goal, 0);
@@ -288,15 +298,20 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
fn assemble_self_ty_infer_ambiguity_response<G: GoalKind<'tcx>>(
&mut self,
goal: Goal<'tcx, G>,
- ) -> Option<Vec<Candidate<'tcx>>> {
- goal.predicate.self_ty().is_ty_var().then(|| {
- vec![Candidate {
- source: CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
- result: self
- .evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
- .unwrap(),
- }]
- })
+ ) -> Option<Candidate<'tcx>> {
+ if goal.predicate.self_ty().is_ty_var() {
+ debug!("adding self_ty_infer_ambiguity_response");
+ let source = CandidateSource::BuiltinImpl(BuiltinImplSource::Misc);
+ let result = self
+ .evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
+ .unwrap();
+ let mut dummy_probe = self.inspect.new_probe();
+ dummy_probe.probe_kind(ProbeKind::TraitCandidate { source, result: Ok(result) });
+ self.inspect.finish_probe(dummy_probe);
+ Some(Candidate { source, result })
+ } else {
+ None
+ }
}
/// Assemble candidates which apply to the self type. This only looks at candidate which
@@ -310,7 +325,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
) -> Vec<Candidate<'tcx>> {
debug_assert_eq!(goal, self.resolve_vars_if_possible(goal));
if let Some(ambig) = self.assemble_self_ty_infer_ambiguity_response(goal) {
- return ambig;
+ return vec![ambig];
}
let mut candidates = Vec::new();
@@ -349,16 +364,14 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
num_steps: usize,
) {
let tcx = self.tcx();
- let &ty::Alias(_, projection_ty) = goal.predicate.self_ty().kind() else { return };
+ let &ty::Alias(_, alias) = goal.predicate.self_ty().kind() else { return };
candidates.extend(self.probe(|_| ProbeKind::NormalizedSelfTyAssembly).enter(|ecx| {
- if num_steps < ecx.local_overflow_limit() {
+ if tcx.recursion_limit().value_within_limit(num_steps) {
let normalized_ty = ecx.next_ty_infer();
- let normalizes_to_goal = goal.with(
- tcx,
- ty::ProjectionPredicate { projection_ty, term: normalized_ty.into() },
- );
- ecx.add_goal(normalizes_to_goal);
+ let normalizes_to_goal =
+ goal.with(tcx, ty::NormalizesTo { alias, term: normalized_ty.into() });
+ ecx.add_goal(GoalSource::Misc, normalizes_to_goal);
if let Err(NoSolution) = ecx.try_evaluate_added_goals() {
debug!("self type normalization failed");
return vec![];
@@ -395,8 +408,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
if let Some(impls_for_type) = trait_impls.non_blanket_impls().get(&simp) {
for &impl_def_id in impls_for_type {
match G::consider_impl_candidate(self, goal, impl_def_id) {
- Ok(result) => candidates
- .push(Candidate { source: CandidateSource::Impl(impl_def_id), result }),
+ Ok(candidate) => candidates.push(candidate),
Err(NoSolution) => (),
}
}
@@ -488,6 +500,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
}
}
+ #[instrument(level = "debug", skip_all)]
fn assemble_unsize_to_dyn_candidate<G: GoalKind<'tcx>>(
&mut self,
goal: Goal<'tcx, G>,
@@ -505,6 +518,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
}
}
+ #[instrument(level = "debug", skip_all)]
fn assemble_blanket_impl_candidates<G: GoalKind<'tcx>>(
&mut self,
goal: Goal<'tcx, G>,
@@ -514,8 +528,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
let trait_impls = tcx.trait_impls_of(goal.predicate.trait_def_id(tcx));
for &impl_def_id in trait_impls.blanket_impls() {
match G::consider_impl_candidate(self, goal, impl_def_id) {
- Ok(result) => candidates
- .push(Candidate { source: CandidateSource::Impl(impl_def_id), result }),
+ Ok(candidate) => candidates.push(candidate),
Err(NoSolution) => (),
}
}
@@ -564,6 +577,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
G::consider_builtin_future_candidate(self, goal)
} else if lang_items.iterator_trait() == Some(trait_def_id) {
G::consider_builtin_iterator_candidate(self, goal)
+ } else if lang_items.async_iterator_trait() == Some(trait_def_id) {
+ G::consider_builtin_async_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) {
@@ -864,23 +879,18 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
let result = self.probe_misc_candidate("coherence unknowable").enter(|ecx| {
let trait_ref = goal.predicate.trait_ref(tcx);
-
#[derive(Debug)]
- enum FailureKind {
- Overflow,
- NoSolution(NoSolution),
- }
+ struct Overflow;
let lazily_normalize_ty = |ty| match ecx.try_normalize_ty(goal.param_env, ty) {
- Ok(Some(ty)) => Ok(ty),
- Ok(None) => Err(FailureKind::Overflow),
- Err(e) => Err(FailureKind::NoSolution(e)),
+ Some(ty) => Ok(ty),
+ None => Err(Overflow),
};
match coherence::trait_ref_is_knowable(tcx, trait_ref, lazily_normalize_ty) {
- Err(FailureKind::Overflow) => {
+ Err(Overflow) => {
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::OVERFLOW)
}
- Err(FailureKind::NoSolution(NoSolution)) | Ok(Ok(())) => Err(NoSolution),
+ Ok(Ok(())) => Err(NoSolution),
Ok(Err(_)) => {
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
}
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 839968b25..f442e2a08 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
@@ -50,14 +50,14 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>(
ty::Array(element_ty, _) | ty::Slice(element_ty) => Ok(vec![element_ty]),
- ty::Tuple(ref tys) => {
+ ty::Tuple(tys) => {
// (T1, ..., Tn) -- meets any bound that all of T1...Tn meet
Ok(tys.iter().collect())
}
- ty::Closure(_, ref args) => Ok(vec![args.as_closure().tupled_upvars_ty()]),
+ ty::Closure(_, args) => Ok(vec![args.as_closure().tupled_upvars_ty()]),
- ty::Coroutine(_, ref args, _) => {
+ ty::Coroutine(_, args, _) => {
let coroutine_args = args.as_coroutine();
Ok(vec![coroutine_args.tupled_upvars_ty(), coroutine_args.witness()])
}
@@ -91,13 +91,13 @@ pub(in crate::solve) fn replace_erased_lifetimes_with_bound_vars<'tcx>(
tcx: TyCtxt<'tcx>,
ty: Ty<'tcx>,
) -> ty::Binder<'tcx, Ty<'tcx>> {
- debug_assert!(!ty.has_late_bound_regions());
+ debug_assert!(!ty.has_bound_regions());
let mut counter = 0;
let ty = tcx.fold_regions(ty, |r, current_depth| match r.kind() {
ty::ReErased => {
let br = ty::BoundRegion { var: ty::BoundVar::from_u32(counter), kind: ty::BrAnon };
counter += 1;
- ty::Region::new_late_bound(tcx, current_depth, br)
+ ty::Region::new_bound(tcx, current_depth, br)
}
// All free regions should be erased here.
r => bug!("unexpected region: {r:?}"),