Skip to content

Split SelectionContext::select into fns that take a binder and don't #113308

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

Merged
merged 4 commits into from
Jul 7, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 6 additions & 7 deletions compiler/rustc_const_eval/src/transform/check_consts/check.rs
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceC
use rustc_middle::mir::*;
use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
use rustc_middle::ty::{self, adjustment::PointerCast, Instance, InstanceDef, Ty, TyCtxt};
use rustc_middle::ty::{Binder, TraitRef, TypeVisitableExt};
use rustc_middle::ty::{TraitRef, TypeVisitableExt};
use rustc_mir_dataflow::{self, Analysis};
use rustc_span::{sym, Span, Symbol};
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
@@ -755,10 +755,9 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
}

let trait_ref = TraitRef::from_method(tcx, trait_id, substs);
let poly_trait_pred =
Binder::dummy(trait_ref).with_constness(ty::BoundConstness::ConstIfConst);
let trait_ref = trait_ref.with_constness(ty::BoundConstness::ConstIfConst);
let obligation =
Obligation::new(tcx, ObligationCause::dummy(), param_env, poly_trait_pred);
Obligation::new(tcx, ObligationCause::dummy(), param_env, trait_ref);

let implsrc = {
let infcx = tcx.infer_ctxt().build();
@@ -776,11 +775,11 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
}
// Closure: Fn{Once|Mut}
Ok(Some(ImplSource::Builtin(_)))
if poly_trait_pred.self_ty().skip_binder().is_closure()
if trait_ref.self_ty().is_closure()
&& tcx.fn_trait_kind_from_def_id(trait_id).is_some() =>
{
let ty::Closure(closure_def_id, substs) =
*poly_trait_pred.self_ty().no_bound_vars().unwrap().kind()
*trait_ref.self_ty().kind()
else {
unreachable!()
};
@@ -840,7 +839,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
tcx,
ObligationCause::dummy_with_span(*fn_span),
param_env,
poly_trait_pred,
trait_ref,
);

// improve diagnostics by showing what failed. Our requirements are stricter this time
10 changes: 3 additions & 7 deletions compiler/rustc_const_eval/src/transform/check_consts/ops.rs
Original file line number Diff line number Diff line change
@@ -10,8 +10,8 @@ use rustc_infer::traits::{ImplSource, Obligation, ObligationCause};
use rustc_middle::mir::{self, CallSource};
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
use rustc_middle::ty::TraitRef;
use rustc_middle::ty::{suggest_constraining_type_param, Adt, Closure, FnDef, FnPtr, Param, Ty};
use rustc_middle::ty::{Binder, TraitRef};
use rustc_middle::util::{call_kind, CallDesugaringKind, CallKind};
use rustc_session::parse::feature_err;
use rustc_span::symbol::sym;
@@ -137,12 +137,8 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
}
}
Adt(..) => {
let obligation = Obligation::new(
tcx,
ObligationCause::dummy(),
param_env,
Binder::dummy(trait_ref),
);
let obligation =
Obligation::new(tcx, ObligationCause::dummy(), param_env, trait_ref);

let infcx = tcx.infer_ctxt().build();
let mut selcx = SelectionContext::new(&infcx);
11 changes: 5 additions & 6 deletions compiler/rustc_hir_typeck/src/coercion.rs
Original file line number Diff line number Diff line change
@@ -632,9 +632,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
while !queue.is_empty() {
let obligation = queue.remove(0);
debug!("coerce_unsized resolve step: {:?}", obligation);
let bound_predicate = obligation.predicate.kind();
let trait_pred = match bound_predicate.skip_binder() {
ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred))
let trait_pred = match obligation.predicate.kind().no_bound_vars() {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could technically affect inference, but CoerceUnsized is an unstable trait and I don't know of a stdlib impl that emits bound predicates :^)

Some(ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)))
if traits.contains(&trait_pred.def_id()) =>
{
if unsize_did == trait_pred.def_id() {
@@ -652,7 +651,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
has_unsized_tuple_coercion = true;
}
}
bound_predicate.rebind(trait_pred)
trait_pred
}
_ => {
coercion.obligations.push(obligation);
@@ -664,8 +663,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
Ok(None) => {
if trait_pred.def_id() == unsize_did {
let trait_pred = self.resolve_vars_if_possible(trait_pred);
let self_ty = trait_pred.skip_binder().self_ty();
let unsize_ty = trait_pred.skip_binder().trait_ref.substs[1].expect_ty();
let self_ty = trait_pred.self_ty();
let unsize_ty = trait_pred.trait_ref.substs[1].expect_ty();
debug!("coerce_unsized: ambiguous unsize case for {:?}", trait_pred);
match (self_ty.kind(), unsize_ty.kind()) {
(&ty::Infer(ty::TyVar(v)), ty::Dynamic(..))
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
Original file line number Diff line number Diff line change
@@ -1982,7 +1982,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.tcx,
traits::ObligationCause::dummy(),
self.param_env,
ty::Binder::dummy(trait_ref),
trait_ref,
);
match SelectionContext::new(&self).select(&obligation) {
Ok(Some(traits::ImplSource::UserDefined(impl_source))) => {
3 changes: 1 addition & 2 deletions compiler/rustc_hir_typeck/src/method/probe.rs
Original file line number Diff line number Diff line change
@@ -1441,8 +1441,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
trait_ref: ty::TraitRef<'tcx>,
) -> traits::SelectionResult<'tcx, traits::Selection<'tcx>> {
let cause = traits::ObligationCause::misc(self.span, self.body_id);
let predicate = ty::Binder::dummy(trait_ref);
let obligation = traits::Obligation::new(self.tcx, cause, self.param_env, predicate);
let obligation = traits::Obligation::new(self.tcx, cause, self.param_env, trait_ref);
traits::SelectionContext::new(self).select(&obligation)
}

7 changes: 4 additions & 3 deletions compiler/rustc_infer/src/traits/mod.rs
Original file line number Diff line number Diff line change
@@ -62,7 +62,8 @@ impl<'tcx, P> From<Obligation<'tcx, P>> for solve::Goal<'tcx, P> {
}

pub type PredicateObligation<'tcx> = Obligation<'tcx, ty::Predicate<'tcx>>;
pub type TraitObligation<'tcx> = Obligation<'tcx, ty::PolyTraitPredicate<'tcx>>;
pub type TraitObligation<'tcx> = Obligation<'tcx, ty::TraitPredicate<'tcx>>;
pub type PolyTraitObligation<'tcx> = Obligation<'tcx, ty::PolyTraitPredicate<'tcx>>;

impl<'tcx> PredicateObligation<'tcx> {
/// Flips the polarity of the inner predicate.
@@ -86,7 +87,7 @@ impl<'tcx> PredicateObligation<'tcx> {
}
}

impl<'tcx> TraitObligation<'tcx> {
impl<'tcx> PolyTraitObligation<'tcx> {
/// Returns `true` if the trait predicate is considered `const` in its ParamEnv.
pub fn is_const(&self) -> bool {
matches!(
@@ -193,7 +194,7 @@ impl<'tcx> FulfillmentError<'tcx> {
}
}

impl<'tcx> TraitObligation<'tcx> {
impl<'tcx> PolyTraitObligation<'tcx> {
pub fn polarity(&self) -> ty::ImplPolarity {
self.predicate.skip_binder().polarity
}
4 changes: 2 additions & 2 deletions compiler/rustc_middle/src/query/keys.rs
Original file line number Diff line number Diff line change
@@ -318,11 +318,11 @@ impl<'tcx> Key for (LocalDefId, DefId, SubstsRef<'tcx>) {
}
}

impl<'tcx> Key for (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>) {
impl<'tcx> Key for (ty::ParamEnv<'tcx>, ty::TraitRef<'tcx>) {
type CacheSelector = DefaultCacheSelector<Self>;

fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
tcx.def_span(self.1.def_id())
tcx.def_span(self.1.def_id)
}
}

2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
@@ -1278,7 +1278,7 @@ rustc_queries! {
}

query codegen_select_candidate(
key: (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>)
key: (ty::ParamEnv<'tcx>, ty::TraitRef<'tcx>)
) -> Result<&'tcx ImplSource<'tcx, ()>, CodegenObligationError> {
cache_on_disk_if { true }
desc { |tcx| "computing candidate for `{}`", key.1 }
7 changes: 7 additions & 0 deletions compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
@@ -1306,6 +1306,13 @@ impl<'tcx> ToPredicate<'tcx> for TraitRef<'tcx> {
}
}

impl<'tcx> ToPredicate<'tcx, TraitPredicate<'tcx>> for TraitRef<'tcx> {
#[inline(always)]
fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> TraitPredicate<'tcx> {
self.without_const()
}
}

impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for TraitRef<'tcx> {
#[inline(always)]
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
4 changes: 2 additions & 2 deletions compiler/rustc_monomorphize/src/lib.rs
Original file line number Diff line number Diff line change
@@ -31,12 +31,12 @@ fn custom_coerce_unsize_info<'tcx>(
source_ty: Ty<'tcx>,
target_ty: Ty<'tcx>,
) -> CustomCoerceUnsized {
let trait_ref = ty::Binder::dummy(ty::TraitRef::from_lang_item(
let trait_ref = ty::TraitRef::from_lang_item(
tcx.tcx,
LangItem::CoerceUnsized,
tcx.span,
[source_ty, target_ty],
));
);

match tcx.codegen_select_candidate((ty::ParamEnv::reveal_all(), trait_ref)) {
Ok(traits::ImplSource::UserDefined(traits::ImplSourceUserDefinedData {
6 changes: 3 additions & 3 deletions compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@ use rustc_hir::def_id::DefId;
use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk};
use rustc_infer::traits::util::supertraits;
use rustc_infer::traits::{
Obligation, PredicateObligation, Selection, SelectionResult, TraitObligation,
Obligation, PolyTraitObligation, PredicateObligation, Selection, SelectionResult,
};
use rustc_middle::traits::solve::{CanonicalInput, Certainty, Goal};
use rustc_middle::traits::{
@@ -23,14 +23,14 @@ use crate::traits::vtable::{count_own_vtable_entries, prepare_vtable_segments, V
pub trait InferCtxtSelectExt<'tcx> {
fn select_in_new_trait_solver(
&self,
obligation: &TraitObligation<'tcx>,
obligation: &PolyTraitObligation<'tcx>,
) -> SelectionResult<'tcx, Selection<'tcx>>;
}

impl<'tcx> InferCtxtSelectExt<'tcx> for InferCtxt<'tcx> {
fn select_in_new_trait_solver(
&self,
obligation: &TraitObligation<'tcx>,
obligation: &PolyTraitObligation<'tcx>,
) -> SelectionResult<'tcx, Selection<'tcx>> {
assert!(self.next_trait_solver());

6 changes: 3 additions & 3 deletions compiler/rustc_trait_selection/src/traits/auto_trait.rs
Original file line number Diff line number Diff line change
@@ -95,15 +95,15 @@ impl<'tcx> AutoTraitFinder<'tcx> {
tcx,
ObligationCause::dummy(),
orig_env,
ty::Binder::dummy(ty::TraitPredicate {
ty::TraitPredicate {
trait_ref,
constness: ty::BoundConstness::NotConst,
polarity: if polarity {
ImplPolarity::Positive
} else {
ImplPolarity::Negative
},
}),
},
));
if let Ok(Some(ImplSource::UserDefined(_))) = result {
debug!(
@@ -292,7 +292,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
new_env,
pred,
));
let result = select.select(&obligation);
let result = select.poly_select(&obligation);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

feels like we may end up with with placeholders in the environment/output here, so it might be safer to check for no_bound_vars. Doesn't matter much, this keeps the current behavior and we're going to rewrite this code anyways


match result {
Ok(Some(ref impl_source)) => {
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use rustc_hir::def_id::DefId;
use rustc_infer::infer::{InferCtxt, LateBoundRegionConversionTime};
use rustc_infer::traits::util::elaborate;
use rustc_infer::traits::{Obligation, ObligationCause, TraitObligation};
use rustc_infer::traits::{Obligation, ObligationCause, PolyTraitObligation};
use rustc_middle::ty;
use rustc_span::{Span, DUMMY_SP};

@@ -14,7 +14,7 @@ pub enum Ambiguity {

pub fn recompute_applicable_impls<'tcx>(
infcx: &InferCtxt<'tcx>,
obligation: &TraitObligation<'tcx>,
obligation: &PolyTraitObligation<'tcx>,
) -> Vec<Ambiguity> {
let tcx = infcx.tcx;
let param_env = obligation.param_env;
6 changes: 3 additions & 3 deletions compiler/rustc_trait_selection/src/traits/fulfill.rs
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@ use rustc_data_structures::obligation_forest::{Error, ForestObligation, Outcome}
use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor};
use rustc_infer::infer::DefineOpaqueTypes;
use rustc_infer::traits::ProjectionCacheKey;
use rustc_infer::traits::{SelectionError, TraitEngine, TraitObligation};
use rustc_infer::traits::{PolyTraitObligation, SelectionError, TraitEngine};
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
use rustc_middle::ty::error::{ExpectedFound, TypeError};
@@ -667,7 +667,7 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> {
fn process_trait_obligation(
&mut self,
obligation: &PredicateObligation<'tcx>,
trait_obligation: TraitObligation<'tcx>,
trait_obligation: PolyTraitObligation<'tcx>,
stalled_on: &mut Vec<TyOrConstInferVar<'tcx>>,
) -> ProcessResult<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>> {
let infcx = self.selcx.infcx;
@@ -683,7 +683,7 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> {
}
}

match self.selcx.select(&trait_obligation) {
match self.selcx.poly_select(&trait_obligation) {
Ok(Some(impl_source)) => {
debug!("selecting trait at depth {} yielded Ok(Some)", obligation.recursion_depth);
ProcessResult::Changed(mk_pending(impl_source.nested_obligations()))
17 changes: 8 additions & 9 deletions compiler/rustc_trait_selection/src/traits/project.rs
Original file line number Diff line number Diff line change
@@ -1545,7 +1545,6 @@ fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>(
let trait_def_id = tcx.parent(trait_fn_def_id);
let trait_substs =
obligation.predicate.substs.truncate_to(tcx, tcx.generics_of(trait_def_id));
// FIXME(named-returns): Binders
let trait_predicate = ty::TraitRef::new(tcx, trait_def_id, trait_substs);

let _ = selcx.infcx.commit_if_ok(|_| {
@@ -1747,8 +1746,8 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(

// If we are resolving `<T as TraitRef<...>>::Item == Type`,
// start out by selecting the predicate `T as TraitRef<...>`:
let poly_trait_ref = ty::Binder::dummy(obligation.predicate.trait_ref(selcx.tcx()));
let trait_obligation = obligation.with(selcx.tcx(), poly_trait_ref);
let trait_ref = obligation.predicate.trait_ref(selcx.tcx());
let trait_obligation = obligation.with(selcx.tcx(), trait_ref);
let _ = selcx.infcx.commit_if_ok(|_| {
let impl_source = match selcx.select(&trait_obligation) {
Ok(Some(impl_source)) => impl_source,
@@ -1802,7 +1801,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
if obligation.param_env.reveal() == Reveal::All {
// NOTE(eddyb) inference variables can resolve to parameters, so
// assume `poly_trait_ref` isn't monomorphic, if it contains any.
let poly_trait_ref = selcx.infcx.resolve_vars_if_possible(poly_trait_ref);
let poly_trait_ref = selcx.infcx.resolve_vars_if_possible(trait_ref);
!poly_trait_ref.still_further_specializable()
} else {
debug!(
@@ -1821,11 +1820,11 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
let self_ty = selcx.infcx.shallow_resolve(obligation.predicate.self_ty());

let lang_items = selcx.tcx().lang_items();
if [lang_items.gen_trait(), lang_items.future_trait()].contains(&Some(poly_trait_ref.def_id()))
|| selcx.tcx().fn_trait_kind_from_def_id(poly_trait_ref.def_id()).is_some()
if [lang_items.gen_trait(), lang_items.future_trait()].contains(&Some(trait_ref.def_id))
|| selcx.tcx().fn_trait_kind_from_def_id(trait_ref.def_id).is_some()
{
true
} else if lang_items.discriminant_kind_trait() == Some(poly_trait_ref.def_id()) {
} else if lang_items.discriminant_kind_trait() == Some(trait_ref.def_id) {
match self_ty.kind() {
ty::Bool
| ty::Char
@@ -1860,7 +1859,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
| ty::Infer(..)
| ty::Error(_) => false,
}
} else if lang_items.pointee_trait() == Some(poly_trait_ref.def_id()) {
} else if lang_items.pointee_trait() == Some(trait_ref.def_id) {
let tail = selcx.tcx().struct_tail_with_normalize(
self_ty,
|ty| {
@@ -1935,7 +1934,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
}
}
} else {
bug!("unexpected builtin trait with associated type: {poly_trait_ref:?}")
bug!("unexpected builtin trait with associated type: {trait_ref:?}")
}
}
super::ImplSource::Param(..) => {
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ use hir::def_id::DefId;
use hir::LangItem;
use rustc_hir as hir;
use rustc_infer::traits::ObligationCause;
use rustc_infer::traits::{Obligation, SelectionError, TraitObligation};
use rustc_infer::traits::{Obligation, PolyTraitObligation, SelectionError};
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
use rustc_middle::ty::{self, Ty, TypeVisitableExt};

@@ -137,7 +137,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
#[instrument(level = "debug", skip(self, candidates))]
fn assemble_candidates_from_projected_tys(
&mut self,
obligation: &TraitObligation<'tcx>,
obligation: &PolyTraitObligation<'tcx>,
candidates: &mut SelectionCandidateSet<'tcx>,
) {
// Before we go into the whole placeholder thing, just
@@ -206,7 +206,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {

fn assemble_generator_candidates(
&mut self,
obligation: &TraitObligation<'tcx>,
obligation: &PolyTraitObligation<'tcx>,
candidates: &mut SelectionCandidateSet<'tcx>,
) {
// Okay to skip binder because the substs on generator types never
@@ -231,7 +231,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {

fn assemble_future_candidates(
&mut self,
obligation: &TraitObligation<'tcx>,
obligation: &PolyTraitObligation<'tcx>,
candidates: &mut SelectionCandidateSet<'tcx>,
) {
let self_ty = obligation.self_ty().skip_binder();
@@ -254,7 +254,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
/// unified during the confirmation step.
fn assemble_closure_candidates(
&mut self,
obligation: &TraitObligation<'tcx>,
obligation: &PolyTraitObligation<'tcx>,
candidates: &mut SelectionCandidateSet<'tcx>,
) {
let Some(kind) = self.tcx().fn_trait_kind_from_def_id(obligation.predicate.def_id()) else {
@@ -292,7 +292,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
/// Implements one of the `Fn()` family for a fn pointer.
fn assemble_fn_pointer_candidates(
&mut self,
obligation: &TraitObligation<'tcx>,
obligation: &PolyTraitObligation<'tcx>,
candidates: &mut SelectionCandidateSet<'tcx>,
) {
// We provide impl of all fn traits for fn pointers.
@@ -334,7 +334,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
#[instrument(level = "debug", skip(self, candidates))]
fn assemble_candidates_from_impls(
&mut self,
obligation: &TraitObligation<'tcx>,
obligation: &PolyTraitObligation<'tcx>,
candidates: &mut SelectionCandidateSet<'tcx>,
) {
// Essentially any user-written impl will match with an error type,
@@ -390,7 +390,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
fn reject_fn_ptr_impls(
&mut self,
impl_def_id: DefId,
obligation: &TraitObligation<'tcx>,
obligation: &PolyTraitObligation<'tcx>,
impl_self_ty: Ty<'tcx>,
) -> bool {
// Let `impl<T: FnPtr> Trait for Vec<T>` go through the normal rejection path.
@@ -475,7 +475,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {

fn assemble_candidates_from_auto_impls(
&mut self,
obligation: &TraitObligation<'tcx>,
obligation: &PolyTraitObligation<'tcx>,
candidates: &mut SelectionCandidateSet<'tcx>,
) {
// Okay to skip binder here because the tests we do below do not involve bound regions.
@@ -544,7 +544,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
/// Searches for impls that might apply to `obligation`.
fn assemble_candidates_from_object_ty(
&mut self,
obligation: &TraitObligation<'tcx>,
obligation: &PolyTraitObligation<'tcx>,
candidates: &mut SelectionCandidateSet<'tcx>,
) {
debug!(
@@ -668,7 +668,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
/// Searches for unsizing that might apply to `obligation`.
fn assemble_candidates_for_unsizing(
&mut self,
obligation: &TraitObligation<'tcx>,
obligation: &PolyTraitObligation<'tcx>,
candidates: &mut SelectionCandidateSet<'tcx>,
) {
// We currently never consider higher-ranked obligations e.g.
@@ -782,7 +782,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
#[instrument(level = "debug", skip(self, obligation, candidates))]
fn assemble_candidates_for_transmutability(
&mut self,
obligation: &TraitObligation<'tcx>,
obligation: &PolyTraitObligation<'tcx>,
candidates: &mut SelectionCandidateSet<'tcx>,
) {
if obligation.predicate.has_non_region_param() {
@@ -800,7 +800,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
#[instrument(level = "debug", skip(self, obligation, candidates))]
fn assemble_candidates_for_trait_alias(
&mut self,
obligation: &TraitObligation<'tcx>,
obligation: &PolyTraitObligation<'tcx>,
candidates: &mut SelectionCandidateSet<'tcx>,
) {
// Okay to skip binder here because the tests we do below do not involve bound regions.
@@ -837,7 +837,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {

fn assemble_const_destruct_candidates(
&mut self,
obligation: &TraitObligation<'tcx>,
obligation: &PolyTraitObligation<'tcx>,
candidates: &mut SelectionCandidateSet<'tcx>,
) {
// If the predicate is `~const Destruct` in a non-const environment, we don't actually need
@@ -924,7 +924,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {

fn assemble_candidate_for_tuple(
&mut self,
obligation: &TraitObligation<'tcx>,
obligation: &PolyTraitObligation<'tcx>,
candidates: &mut SelectionCandidateSet<'tcx>,
) {
let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
@@ -966,7 +966,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {

fn assemble_candidate_for_pointer_like(
&mut self,
obligation: &TraitObligation<'tcx>,
obligation: &PolyTraitObligation<'tcx>,
candidates: &mut SelectionCandidateSet<'tcx>,
) {
// The regions of a type don't affect the size of the type
@@ -991,7 +991,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {

fn assemble_candidates_for_fn_ptr_trait(
&mut self,
obligation: &TraitObligation<'tcx>,
obligation: &PolyTraitObligation<'tcx>,
candidates: &mut SelectionCandidateSet<'tcx>,
) {
let self_ty = self.infcx.shallow_resolve(obligation.self_ty());
42 changes: 21 additions & 21 deletions compiler/rustc_trait_selection/src/traits/select/confirmation.rs
Original file line number Diff line number Diff line change
@@ -27,8 +27,8 @@ use crate::traits::vtable::{
use crate::traits::{
BuiltinDerivedObligation, ImplDerivedObligation, ImplDerivedObligationCause, ImplSource,
ImplSourceObjectData, ImplSourceTraitUpcastingData, ImplSourceUserDefinedData, Normalized,
Obligation, ObligationCause, OutputTypeParameterMismatch, PredicateObligation, Selection,
SelectionError, TraitNotObjectSafe, TraitObligation, Unimplemented,
Obligation, ObligationCause, OutputTypeParameterMismatch, PolyTraitObligation,
PredicateObligation, Selection, SelectionError, TraitNotObjectSafe, Unimplemented,
};

use super::BuiltinImplConditions;
@@ -42,7 +42,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
#[instrument(level = "debug", skip(self))]
pub(super) fn confirm_candidate(
&mut self,
obligation: &TraitObligation<'tcx>,
obligation: &PolyTraitObligation<'tcx>,
candidate: SelectionCandidate<'tcx>,
) -> Result<Selection<'tcx>, SelectionError<'tcx>> {
let mut impl_src = match candidate {
@@ -148,7 +148,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {

fn confirm_projection_candidate(
&mut self,
obligation: &TraitObligation<'tcx>,
obligation: &PolyTraitObligation<'tcx>,
idx: usize,
) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
let tcx = self.tcx();
@@ -215,7 +215,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {

fn confirm_param_candidate(
&mut self,
obligation: &TraitObligation<'tcx>,
obligation: &PolyTraitObligation<'tcx>,
param: ty::PolyTraitRef<'tcx>,
) -> Vec<PredicateObligation<'tcx>> {
debug!(?obligation, ?param, "confirm_param_candidate");
@@ -238,7 +238,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {

fn confirm_builtin_candidate(
&mut self,
obligation: &TraitObligation<'tcx>,
obligation: &PolyTraitObligation<'tcx>,
has_nested: bool,
) -> Vec<PredicateObligation<'tcx>> {
debug!(?obligation, ?has_nested, "confirm_builtin_candidate");
@@ -279,13 +279,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
#[instrument(level = "debug", skip(self))]
fn confirm_transmutability_candidate(
&mut self,
obligation: &TraitObligation<'tcx>,
obligation: &PolyTraitObligation<'tcx>,
) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
use rustc_transmute::{Answer, Condition};
#[instrument(level = "debug", skip(tcx, obligation, predicate))]
fn flatten_answer_tree<'tcx>(
tcx: TyCtxt<'tcx>,
obligation: &TraitObligation<'tcx>,
obligation: &PolyTraitObligation<'tcx>,
predicate: TraitPredicate<'tcx>,
cond: Condition<rustc_transmute::layout::rustc::Ref<'tcx>>,
) -> Vec<PredicateObligation<'tcx>> {
@@ -375,7 +375,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
/// 2. For each where-clause `C` declared on `Foo`, `[Self => X] C` holds.
fn confirm_auto_impl_candidate(
&mut self,
obligation: &TraitObligation<'tcx>,
obligation: &PolyTraitObligation<'tcx>,
) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
debug!(?obligation, "confirm_auto_impl_candidate");

@@ -387,7 +387,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
/// See `confirm_auto_impl_candidate`.
fn vtable_auto_impl(
&mut self,
obligation: &TraitObligation<'tcx>,
obligation: &PolyTraitObligation<'tcx>,
trait_def_id: DefId,
nested: ty::Binder<'tcx, Vec<Ty<'tcx>>>,
) -> Vec<PredicateObligation<'tcx>> {
@@ -426,7 +426,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {

fn confirm_impl_candidate(
&mut self,
obligation: &TraitObligation<'tcx>,
obligation: &PolyTraitObligation<'tcx>,
impl_def_id: DefId,
) -> ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>> {
debug!(?obligation, ?impl_def_id, "confirm_impl_candidate");
@@ -481,7 +481,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {

fn confirm_object_candidate(
&mut self,
obligation: &TraitObligation<'tcx>,
obligation: &PolyTraitObligation<'tcx>,
index: usize,
) -> Result<ImplSourceObjectData<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
let tcx = self.tcx();
@@ -655,7 +655,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {

fn confirm_fn_pointer_candidate(
&mut self,
obligation: &TraitObligation<'tcx>,
obligation: &PolyTraitObligation<'tcx>,
is_const: bool,
) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
debug!(?obligation, "confirm_fn_pointer_candidate");
@@ -714,7 +714,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {

fn confirm_trait_alias_candidate(
&mut self,
obligation: &TraitObligation<'tcx>,
obligation: &PolyTraitObligation<'tcx>,
) -> Vec<PredicateObligation<'tcx>> {
debug!(?obligation, "confirm_trait_alias_candidate");

@@ -739,7 +739,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {

fn confirm_generator_candidate(
&mut self,
obligation: &TraitObligation<'tcx>,
obligation: &PolyTraitObligation<'tcx>,
) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
// Okay to skip binder because the substs on generator types never
// touch bound regions, they just capture the in-scope
@@ -778,7 +778,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {

fn confirm_future_candidate(
&mut self,
obligation: &TraitObligation<'tcx>,
obligation: &PolyTraitObligation<'tcx>,
) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
// Okay to skip binder because the substs on generator types never
// touch bound regions, they just capture the in-scope
@@ -809,7 +809,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
#[instrument(skip(self), level = "debug")]
fn confirm_closure_candidate(
&mut self,
obligation: &TraitObligation<'tcx>,
obligation: &PolyTraitObligation<'tcx>,
) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
let kind = self
.tcx()
@@ -865,7 +865,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
#[instrument(skip(self), level = "trace")]
fn confirm_poly_trait_refs(
&mut self,
obligation: &TraitObligation<'tcx>,
obligation: &PolyTraitObligation<'tcx>,
self_ty_trait_ref: ty::PolyTraitRef<'tcx>,
) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
let obligation_trait_ref = obligation.predicate.to_poly_trait_ref();
@@ -900,7 +900,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {

fn confirm_trait_upcasting_unsize_candidate(
&mut self,
obligation: &TraitObligation<'tcx>,
obligation: &PolyTraitObligation<'tcx>,
idx: usize,
) -> Result<ImplSourceTraitUpcastingData<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
let tcx = self.tcx();
@@ -1004,7 +1004,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {

fn confirm_builtin_unsize_candidate(
&mut self,
obligation: &TraitObligation<'tcx>,
obligation: &PolyTraitObligation<'tcx>,
) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
let tcx = self.tcx();

@@ -1213,7 +1213,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {

fn confirm_const_destruct_candidate(
&mut self,
obligation: &TraitObligation<'tcx>,
obligation: &PolyTraitObligation<'tcx>,
impl_def_id: Option<DefId>,
) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
// `~const Destruct` in a non-const environment is always trivially true, since our type is `Drop`
53 changes: 33 additions & 20 deletions compiler/rustc_trait_selection/src/traits/select/mod.rs
Original file line number Diff line number Diff line change
@@ -15,8 +15,8 @@ use super::util::closure_trait_ref_and_return_type;
use super::wf;
use super::{
ErrorReporting, ImplDerivedObligation, ImplDerivedObligationCause, Normalized, Obligation,
ObligationCause, ObligationCauseCode, Overflow, PredicateObligation, Selection, SelectionError,
SelectionResult, TraitObligation, TraitQueryMode,
ObligationCause, ObligationCauseCode, Overflow, PolyTraitObligation, PredicateObligation,
Selection, SelectionError, SelectionResult, TraitQueryMode,
};

use crate::infer::{InferCtxt, InferOk, TypeFreshener};
@@ -34,6 +34,7 @@ use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_infer::infer::DefineOpaqueTypes;
use rustc_infer::infer::LateBoundRegionConversionTime;
use rustc_infer::traits::TraitObligation;
use rustc_middle::dep_graph::{DepKind, DepNodeIndex};
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
@@ -122,7 +123,7 @@ pub struct SelectionContext<'cx, 'tcx> {

// A stack that walks back up the stack frame.
struct TraitObligationStack<'prev, 'tcx> {
obligation: &'prev TraitObligation<'tcx>,
obligation: &'prev PolyTraitObligation<'tcx>,

/// The trait predicate from `obligation` but "freshened" with the
/// selection-context's freshener. Used to check for recursion.
@@ -259,9 +260,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
/// Attempts to satisfy the obligation. If successful, this will affect the surrounding
/// type environment by performing unification.
#[instrument(level = "debug", skip(self), ret)]
pub fn select(
pub fn poly_select(
&mut self,
obligation: &TraitObligation<'tcx>,
obligation: &PolyTraitObligation<'tcx>,
) -> SelectionResult<'tcx, Selection<'tcx>> {
if self.infcx.next_trait_solver() {
return self.infcx.select_in_new_trait_solver(obligation);
@@ -293,9 +294,21 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
}

fn select_from_obligation(
pub fn select(
&mut self,
obligation: &TraitObligation<'tcx>,
) -> SelectionResult<'tcx, Selection<'tcx>> {
self.poly_select(&Obligation {
cause: obligation.cause.clone(),
param_env: obligation.param_env,
predicate: ty::Binder::dummy(obligation.predicate),
recursion_depth: obligation.recursion_depth,
})
}

fn select_from_obligation(
&mut self,
obligation: &PolyTraitObligation<'tcx>,
) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
debug_assert!(!obligation.predicate.has_escaping_bound_vars());

@@ -612,7 +625,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
obligation: PredicateObligation<'tcx>,
) -> Result<EvaluationResult, OverflowError> {
debug_assert!(!self.infcx.next_trait_solver());
// `previous_stack` stores a `TraitObligation`, while `obligation` is
// `previous_stack` stores a `PolyTraitObligation`, while `obligation` is
// a `PredicateObligation`. These are distinct types, so we can't
// use any `Option` combinator method that would force them to be
// the same.
@@ -973,7 +986,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
fn evaluate_trait_predicate_recursively<'o>(
&mut self,
previous_stack: TraitObligationStackList<'o, 'tcx>,
mut obligation: TraitObligation<'tcx>,
mut obligation: PolyTraitObligation<'tcx>,
) -> Result<EvaluationResult, OverflowError> {
if !self.is_intercrate()
&& obligation.is_global()
@@ -1379,7 +1392,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
fn filter_impls(
&mut self,
candidates: Vec<SelectionCandidate<'tcx>>,
obligation: &TraitObligation<'tcx>,
obligation: &PolyTraitObligation<'tcx>,
) -> Vec<SelectionCandidate<'tcx>> {
trace!("{candidates:#?}");
let tcx = self.tcx();
@@ -1442,7 +1455,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
fn filter_reservation_impls(
&mut self,
candidate: SelectionCandidate<'tcx>,
obligation: &TraitObligation<'tcx>,
obligation: &PolyTraitObligation<'tcx>,
) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
let tcx = self.tcx();
// Treat reservation impls as ambiguity.
@@ -1614,7 +1627,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
#[instrument(level = "debug", skip(self), ret)]
fn match_projection_obligation_against_definition_bounds(
&mut self,
obligation: &TraitObligation<'tcx>,
obligation: &PolyTraitObligation<'tcx>,
) -> smallvec::SmallVec<[(usize, ty::BoundConstness); 2]> {
let poly_trait_predicate = self.infcx.resolve_vars_if_possible(obligation.predicate);
let placeholder_trait_predicate =
@@ -1677,7 +1690,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
/// variables or placeholders, the normalized bound is returned.
fn match_normalize_trait_ref(
&mut self,
obligation: &TraitObligation<'tcx>,
obligation: &PolyTraitObligation<'tcx>,
trait_bound: ty::PolyTraitRef<'tcx>,
placeholder_trait_ref: ty::TraitRef<'tcx>,
) -> Result<Option<ty::PolyTraitRef<'tcx>>, ()> {
@@ -2078,7 +2091,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
impl<'tcx> SelectionContext<'_, 'tcx> {
fn sized_conditions(
&mut self,
obligation: &TraitObligation<'tcx>,
obligation: &PolyTraitObligation<'tcx>,
) -> BuiltinImplConditions<'tcx> {
use self::BuiltinImplConditions::{Ambiguous, None, Where};

@@ -2138,7 +2151,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {

fn copy_clone_conditions(
&mut self,
obligation: &TraitObligation<'tcx>,
obligation: &PolyTraitObligation<'tcx>,
) -> BuiltinImplConditions<'tcx> {
// NOTE: binder moved to (*)
let self_ty = self.infcx.shallow_resolve(obligation.predicate.skip_binder().self_ty());
@@ -2414,7 +2427,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
fn rematch_impl(
&mut self,
impl_def_id: DefId,
obligation: &TraitObligation<'tcx>,
obligation: &PolyTraitObligation<'tcx>,
) -> Normalized<'tcx, SubstsRef<'tcx>> {
let impl_trait_ref = self.tcx().impl_trait_ref(impl_def_id).unwrap();
match self.match_impl(impl_def_id, impl_trait_ref, obligation) {
@@ -2452,7 +2465,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
&mut self,
impl_def_id: DefId,
impl_trait_ref: EarlyBinder<ty::TraitRef<'tcx>>,
obligation: &TraitObligation<'tcx>,
obligation: &PolyTraitObligation<'tcx>,
) -> Result<Normalized<'tcx, SubstsRef<'tcx>>, ()> {
let placeholder_obligation =
self.infcx.instantiate_binder_with_placeholders(obligation.predicate);
@@ -2510,7 +2523,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
/// result from the normalization.
fn match_where_clause_trait_ref(
&mut self,
obligation: &TraitObligation<'tcx>,
obligation: &PolyTraitObligation<'tcx>,
where_clause_trait_ref: ty::PolyTraitRef<'tcx>,
) -> Result<Vec<PredicateObligation<'tcx>>, ()> {
self.match_poly_trait_ref(obligation, where_clause_trait_ref)
@@ -2521,7 +2534,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
#[instrument(skip(self), level = "debug")]
fn match_poly_trait_ref(
&mut self,
obligation: &TraitObligation<'tcx>,
obligation: &PolyTraitObligation<'tcx>,
poly_trait_ref: ty::PolyTraitRef<'tcx>,
) -> Result<Vec<PredicateObligation<'tcx>>, ()> {
self.infcx
@@ -2547,7 +2560,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
fn push_stack<'o>(
&mut self,
previous_stack: TraitObligationStackList<'o, 'tcx>,
obligation: &'o TraitObligation<'tcx>,
obligation: &'o PolyTraitObligation<'tcx>,
) -> TraitObligationStack<'o, 'tcx> {
let fresh_trait_pred = obligation.predicate.fold_with(&mut self.freshener);

@@ -2566,7 +2579,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
#[instrument(skip(self), level = "debug")]
fn closure_trait_ref_unnormalized(
&mut self,
obligation: &TraitObligation<'tcx>,
obligation: &PolyTraitObligation<'tcx>,
substs: SubstsRef<'tcx>,
) -> ty::PolyTraitRef<'tcx> {
let closure_sig = substs.as_closure().sig();
2 changes: 1 addition & 1 deletion compiler/rustc_trait_selection/src/traits/vtable.rs
Original file line number Diff line number Diff line change
@@ -362,7 +362,7 @@ pub(crate) fn vtable_trait_upcasting_coercion_new_vptr_slot<'tcx>(

let trait_ref = ty::TraitRef::new(tcx, unsize_trait_did, [source, target]);

match tcx.codegen_select_candidate((ty::ParamEnv::reveal_all(), ty::Binder::dummy(trait_ref))) {
match tcx.codegen_select_candidate((ty::ParamEnv::reveal_all(), trait_ref)) {
Ok(ImplSource::TraitUpcasting(implsrc_traitcasting)) => {
implsrc_traitcasting.vtable_vptr_slot
}
2 changes: 1 addition & 1 deletion compiler/rustc_traits/src/codegen.rs
Original file line number Diff line number Diff line change
@@ -22,7 +22,7 @@ use rustc_trait_selection::traits::{
/// This also expects that `trait_ref` is fully normalized.
pub fn codegen_select_candidate<'tcx>(
tcx: TyCtxt<'tcx>,
(param_env, trait_ref): (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>),
(param_env, trait_ref): (ty::ParamEnv<'tcx>, ty::TraitRef<'tcx>),
) -> Result<&'tcx ImplSource<'tcx, ()>, CodegenObligationError> {
// We expect the input to be fully normalized.
debug_assert_eq!(trait_ref, tcx.normalize_erasing_regions(param_env, trait_ref));
2 changes: 1 addition & 1 deletion compiler/rustc_ty_utils/src/instance.rs
Original file line number Diff line number Diff line change
@@ -80,7 +80,7 @@ fn resolve_associated_item<'tcx>(

let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs);

let vtbl = match tcx.codegen_select_candidate((param_env, ty::Binder::dummy(trait_ref))) {
let vtbl = match tcx.codegen_select_candidate((param_env, trait_ref)) {
Ok(vtbl) => vtbl,
Err(CodegenObligationError::Ambiguity) => {
let reported = tcx.sess.delay_span_bug(