Skip to content
4 changes: 4 additions & 0 deletions compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1252,6 +1252,10 @@ impl<'tcx> InstantiatedPredicates<'tcx> {
pub fn is_empty(&self) -> bool {
self.predicates.is_empty()
}

pub fn into_iter(self) -> impl Iterator<Item = (ty::Predicate<'tcx>, Span)> {
std::iter::zip(self.predicates, self.spans)
}
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable, Lift)]
Expand Down
107 changes: 106 additions & 1 deletion compiler/rustc_trait_selection/src/solve/assembly.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! Code shared by trait and projection goals for candidate assembly.

use crate::traits::TupleArgumentsFlag;

use super::infcx_ext::InferCtxtExt;
use super::{
fixme_instantiate_canonical_query_response, CanonicalGoal, CanonicalResponse, Certainty,
Expand Down Expand Up @@ -44,6 +46,45 @@ pub(super) trait GoalKind<'tcx>: TypeFoldable<'tcx> + Copy {
goal: Goal<'tcx, Self>,
impl_def_id: DefId,
);

fn consider_trait_alias_candidate(
acx: &mut AssemblyCtxt<'_, 'tcx, Self>,
goal: Goal<'tcx, Self>,
);

fn consider_alias_bound_candidates(
acx: &mut AssemblyCtxt<'_, 'tcx, Self>,
goal: Goal<'tcx, Self>,
alias_ty: ty::AliasTy<'tcx>,
);

fn consider_object_bound_candidates(
acx: &mut AssemblyCtxt<'_, 'tcx, Self>,
goal: Goal<'tcx, Self>,
object_bounds: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
);

fn consider_param_env_candidates(
acx: &mut AssemblyCtxt<'_, 'tcx, Self>,
goal: Goal<'tcx, Self>,
);

fn consider_auto_trait_candidate(
acx: &mut AssemblyCtxt<'_, 'tcx, Self>,
goal: Goal<'tcx, Self>,
);

fn consider_fn_candidate(
acx: &mut AssemblyCtxt<'_, 'tcx, Self>,
goal: Goal<'tcx, Self>,
bound_sig: ty::PolyFnSig<'tcx>,
tuple_arguments: TupleArgumentsFlag,
);

fn consider_builtin_trait_candidates(
acx: &mut AssemblyCtxt<'_, 'tcx, Self>,
goal: Goal<'tcx, Self>,
);
}

/// An abstraction which correctly deals with the canonical results for candidates.
Expand All @@ -69,6 +110,18 @@ impl<'a, 'tcx, G: GoalKind<'tcx>> AssemblyCtxt<'a, 'tcx, G> {

acx.assemble_impl_candidates(goal);

acx.assemble_bound_candidates(goal);

acx.assemble_param_env_candidates(goal);

acx.assemble_auto_trait_candidates(goal);

acx.assemble_trait_alias_candidates(goal);

acx.assemble_fn_like_candidates(goal);

G::consider_builtin_trait_candidates(&mut acx, goal);

acx.candidates
}

Expand Down Expand Up @@ -111,7 +164,10 @@ impl<'a, 'tcx, G: GoalKind<'tcx>> AssemblyCtxt<'a, 'tcx, G> {

// NOTE: Alternatively we could call `evaluate_goal` here and only have a `Normalized` candidate.
// This doesn't work as long as we use `CandidateSource` in both winnowing and to resolve associated items.
let goal = goal.with(tcx, goal.predicate.with_self_ty(tcx, normalized_ty));
let goal = goal.with(
tcx,
goal.predicate.with_self_ty(tcx, self.infcx.shallow_resolve(normalized_ty)),
);
let mut orig_values = OriginalQueryValues::default();
let goal = self.infcx.canonicalize_query(goal, &mut orig_values);
let normalized_candidates =
Expand Down Expand Up @@ -147,4 +203,53 @@ impl<'a, 'tcx, G: GoalKind<'tcx>> AssemblyCtxt<'a, 'tcx, G> {
|impl_def_id| G::consider_impl_candidate(self, goal, impl_def_id),
);
}

fn assemble_bound_candidates(&mut self, goal: Goal<'tcx, G>) {
match *goal.predicate.self_ty().kind() {
ty::Alias(_, alias_ty) => G::consider_alias_bound_candidates(self, goal, alias_ty),
ty::Dynamic(predicates, _, _) => {
G::consider_object_bound_candidates(self, goal, predicates)
}
_ => {}
}
}

fn assemble_param_env_candidates(&mut self, goal: Goal<'tcx, G>) {
G::consider_param_env_candidates(self, goal);
}

fn assemble_auto_trait_candidates(&mut self, goal: Goal<'tcx, G>) {
if self.cx.tcx.trait_is_auto(goal.predicate.trait_def_id(self.cx.tcx)) {
G::consider_auto_trait_candidate(self, goal);
}
}

fn assemble_trait_alias_candidates(&mut self, goal: Goal<'tcx, G>) {
if self.cx.tcx.is_trait_alias(goal.predicate.trait_def_id(self.cx.tcx)) {
G::consider_trait_alias_candidate(self, goal);
}
}

fn assemble_fn_like_candidates(&mut self, goal: Goal<'tcx, G>) {
let tcx = self.cx.tcx;
let trait_def_id = goal.predicate.trait_def_id(tcx);
if let Some(goal_kind) = tcx.fn_trait_kind_from_def_id(trait_def_id) {
match *goal.predicate.self_ty().kind() {
ty::FnDef(def_id, substs) => {
G::consider_fn_candidate(self, goal, tcx.bound_fn_sig(def_id).subst(tcx, substs), TupleArgumentsFlag::Yes)
}
ty::FnPtr(sig) => {
G::consider_fn_candidate(self, goal, sig, TupleArgumentsFlag::Yes)
}
ty::Closure(_, substs) => {
if let Some(kind) = self.infcx.closure_kind(substs)
&& kind.extends(goal_kind)
{
G::consider_fn_candidate(self, goal, substs.as_closure().sig(), TupleArgumentsFlag::No)
}
}
_ => {}
}
}
}
}
53 changes: 53 additions & 0 deletions compiler/rustc_trait_selection/src/solve/project_goals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,59 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
acx.try_insert_candidate(CandidateSource::Impl(impl_def_id), certainty);
})
}

fn consider_trait_alias_candidate(
_acx: &mut AssemblyCtxt<'_, 'tcx, Self>,
_goal: Goal<'tcx, Self>,
) {
// Trait aliases never have (their own) associated types
}

fn consider_alias_bound_candidates(
_acx: &mut AssemblyCtxt<'_, 'tcx, Self>,
_goal: Goal<'tcx, ProjectionPredicate<'tcx>>,
_alias_ty: ty::AliasTy<'tcx>,
) {
todo!()
}

fn consider_object_bound_candidates(
_acx: &mut AssemblyCtxt<'_, 'tcx, Self>,
_goal: Goal<'tcx, Self>,
_object_bounds: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
) {
todo!()
}

fn consider_param_env_candidates(
_acx: &mut AssemblyCtxt<'_, 'tcx, Self>,
_goal: Goal<'tcx, Self>,
) {
todo!()
}

fn consider_auto_trait_candidate(
_acx: &mut AssemblyCtxt<'_, 'tcx, Self>,
_goal: Goal<'tcx, Self>,
) {
// Auto traits never have associated types
}

fn consider_fn_candidate(
_acx: &mut AssemblyCtxt<'_, 'tcx, Self>,
_goal: Goal<'tcx, Self>,
_bound_sig: ty::PolyFnSig<'tcx>,
_tuple_arguments: crate::traits::TupleArgumentsFlag,
) {
todo!()
}

fn consider_builtin_trait_candidates(
_acx: &mut AssemblyCtxt<'_, 'tcx, Self>,
_goal: Goal<'tcx, Self>,
) {
todo!();
}
}

/// This behavior is also implemented in `rustc_ty_utils` and in the old `project` code.
Expand Down
Loading