Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement a few trait goal candidates for the new solver #106384

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