Rollup merge of #116261 - lcnr:wf-only-clause, r=davidtwco

a small wf and clause cleanup

- remove `Clause::from_projection_clause`, instead use `ToPredicate`
- change `predicate_obligations` to directly take a `Clause`
- remove some unnecessary `&`
- use clause in `min_specialization` checks where easily applicable
This commit is contained in:
Matthias Krüger 2023-10-03 16:24:15 +02:00 committed by GitHub
commit 8efbc2cbae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 81 additions and 101 deletions

View File

@ -16,6 +16,7 @@ use rustc_infer::traits::util;
use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::fold::BottomUpFolder; use rustc_middle::ty::fold::BottomUpFolder;
use rustc_middle::ty::util::ExplicitSelf; use rustc_middle::ty::util::ExplicitSelf;
use rustc_middle::ty::ToPredicate;
use rustc_middle::ty::{ use rustc_middle::ty::{
self, GenericArgs, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, self, GenericArgs, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
}; };
@ -2279,16 +2280,16 @@ pub(super) fn check_type_bounds<'tcx>(
// //
// impl<T> X for T where T: X { type Y = <T as X>::Y; } // impl<T> X for T where T: X { type Y = <T as X>::Y; }
} }
_ => predicates.push(ty::Clause::from_projection_clause( _ => predicates.push(
tcx,
ty::Binder::bind_with_vars( ty::Binder::bind_with_vars(
ty::ProjectionPredicate { ty::ProjectionPredicate {
projection_ty: tcx.mk_alias_ty(trait_ty.def_id, rebased_args), projection_ty: tcx.mk_alias_ty(trait_ty.def_id, rebased_args),
term: normalize_impl_ty.into(), term: normalize_impl_ty.into(),
}, },
bound_vars, bound_vars,
)
.to_predicate(tcx),
), ),
)),
}; };
ty::ParamEnv::new(tcx.mk_clauses(&predicates), Reveal::UserFacing) ty::ParamEnv::new(tcx.mk_clauses(&predicates), Reveal::UserFacing)
}; };

View File

@ -1130,11 +1130,11 @@ fn check_associated_type_bounds(wfcx: &WfCheckingCtxt<'_, '_>, item: ty::AssocIt
let wf_obligations = let wf_obligations =
bounds.instantiate_identity_iter_copied().flat_map(|(bound, bound_span)| { bounds.instantiate_identity_iter_copied().flat_map(|(bound, bound_span)| {
let normalized_bound = wfcx.normalize(span, None, bound); let normalized_bound = wfcx.normalize(span, None, bound);
traits::wf::predicate_obligations( traits::wf::clause_obligations(
wfcx.infcx, wfcx.infcx,
wfcx.param_env, wfcx.param_env,
wfcx.body_def_id, wfcx.body_def_id,
normalized_bound.as_predicate(), normalized_bound,
bound_span, bound_span,
) )
}); });
@ -1234,7 +1234,7 @@ fn check_impl<'tcx>(
wfcx.infcx, wfcx.infcx,
wfcx.param_env, wfcx.param_env,
wfcx.body_def_id, wfcx.body_def_id,
&trait_pred, trait_pred,
ast_trait_ref.path.span, ast_trait_ref.path.span,
item, item,
); );
@ -1443,13 +1443,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
debug!(?predicates.predicates); debug!(?predicates.predicates);
assert_eq!(predicates.predicates.len(), predicates.spans.len()); assert_eq!(predicates.predicates.len(), predicates.spans.len());
let wf_obligations = predicates.into_iter().flat_map(|(p, sp)| { let wf_obligations = predicates.into_iter().flat_map(|(p, sp)| {
traits::wf::predicate_obligations( traits::wf::clause_obligations(infcx, wfcx.param_env, wfcx.body_def_id, p, sp)
infcx,
wfcx.param_env,
wfcx.body_def_id,
p.as_predicate(),
sp,
)
}); });
let obligations: Vec<_> = wf_obligations.chain(default_obligations).collect(); let obligations: Vec<_> = wf_obligations.chain(default_obligations).collect();
wfcx.register_obligations(obligations); wfcx.register_obligations(obligations);

View File

@ -376,9 +376,9 @@ fn check_predicates<'tcx>(
let always_applicable_traits = impl1_predicates let always_applicable_traits = impl1_predicates
.iter() .iter()
.copied() .copied()
.filter(|(clause, _span)| { .filter(|&(clause, _span)| {
matches!( matches!(
trait_predicate_kind(tcx, clause.as_predicate()), trait_specialization_kind(tcx, clause),
Some(TraitSpecializationKind::AlwaysApplicable) Some(TraitSpecializationKind::AlwaysApplicable)
) )
}) })
@ -402,7 +402,7 @@ fn check_predicates<'tcx>(
.iter() .iter()
.any(|pred2| trait_predicates_eq(tcx, clause.as_predicate(), *pred2, span)) .any(|pred2| trait_predicates_eq(tcx, clause.as_predicate(), *pred2, span))
{ {
check_specialization_on(tcx, clause.as_predicate(), span) check_specialization_on(tcx, clause, span)
} }
} }
} }
@ -441,19 +441,16 @@ fn trait_predicates_eq<'tcx>(
} }
#[instrument(level = "debug", skip(tcx))] #[instrument(level = "debug", skip(tcx))]
fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tcx>, span: Span) { fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, clause: ty::Clause<'tcx>, span: Span) {
match predicate.kind().skip_binder() { match clause.kind().skip_binder() {
// Global predicates are either always true or always false, so we // Global predicates are either always true or always false, so we
// are fine to specialize on. // are fine to specialize on.
_ if predicate.is_global() => (), _ if clause.is_global() => (),
// We allow specializing on explicitly marked traits with no associated // We allow specializing on explicitly marked traits with no associated
// items. // items.
ty::PredicateKind::Clause(ty::ClauseKind::Trait(ty::TraitPredicate { ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity: _ }) => {
trait_ref,
polarity: _,
})) => {
if !matches!( if !matches!(
trait_predicate_kind(tcx, predicate), trait_specialization_kind(tcx, clause),
Some(TraitSpecializationKind::Marker) Some(TraitSpecializationKind::Marker)
) { ) {
tcx.sess tcx.sess
@ -467,10 +464,7 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc
.emit(); .emit();
} }
} }
ty::PredicateKind::Clause(ty::ClauseKind::Projection(ty::ProjectionPredicate { ty::ClauseKind::Projection(ty::ProjectionPredicate { projection_ty, term }) => {
projection_ty,
term,
})) => {
tcx.sess tcx.sess
.struct_span_err( .struct_span_err(
span, span,
@ -478,7 +472,7 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc
) )
.emit(); .emit();
} }
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..)) => { ty::ClauseKind::ConstArgHasType(..) => {
// FIXME(min_specialization), FIXME(const_generics): // FIXME(min_specialization), FIXME(const_generics):
// It probably isn't right to allow _every_ `ConstArgHasType` but I am somewhat unsure // It probably isn't right to allow _every_ `ConstArgHasType` but I am somewhat unsure
// about the actual rules that would be sound. Can't just always error here because otherwise // about the actual rules that would be sound. Can't just always error here because otherwise
@ -490,33 +484,25 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc
} }
_ => { _ => {
tcx.sess tcx.sess
.struct_span_err(span, format!("cannot specialize on predicate `{predicate}`")) .struct_span_err(span, format!("cannot specialize on predicate `{clause}`"))
.emit(); .emit();
} }
} }
} }
fn trait_predicate_kind<'tcx>( fn trait_specialization_kind<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
predicate: ty::Predicate<'tcx>, clause: ty::Clause<'tcx>,
) -> Option<TraitSpecializationKind> { ) -> Option<TraitSpecializationKind> {
match predicate.kind().skip_binder() { match clause.kind().skip_binder() {
ty::PredicateKind::Clause(ty::ClauseKind::Trait(ty::TraitPredicate { ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity: _ }) => {
trait_ref, Some(tcx.trait_def(trait_ref.def_id).specialization_kind)
polarity: _, }
})) => Some(tcx.trait_def(trait_ref.def_id).specialization_kind), ty::ClauseKind::RegionOutlives(_)
ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(_)) | ty::ClauseKind::TypeOutlives(_)
| ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(_)) | ty::ClauseKind::Projection(_)
| ty::PredicateKind::Clause(ty::ClauseKind::Projection(_)) | ty::ClauseKind::ConstArgHasType(..)
| ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..)) | ty::ClauseKind::WellFormed(_)
| ty::PredicateKind::AliasRelate(..) | ty::ClauseKind::ConstEvaluatable(..) => None,
| ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_))
| ty::PredicateKind::Subtype(_)
| ty::PredicateKind::Coerce(_)
| ty::PredicateKind::ObjectSafe(_)
| ty::PredicateKind::ClosureKind(..)
| ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))
| ty::PredicateKind::ConstEquate(..)
| ty::PredicateKind::Ambiguous => None,
} }
} }

View File

@ -578,11 +578,6 @@ impl rustc_errors::IntoDiagnosticArg for Clause<'_> {
pub struct Clause<'tcx>(Interned<'tcx, WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>); pub struct Clause<'tcx>(Interned<'tcx, WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>);
impl<'tcx> Clause<'tcx> { impl<'tcx> Clause<'tcx> {
pub fn from_projection_clause(tcx: TyCtxt<'tcx>, pred: PolyProjectionPredicate<'tcx>) -> Self {
let pred: Predicate<'tcx> = pred.to_predicate(tcx);
pred.expect_clause()
}
pub fn as_predicate(self) -> Predicate<'tcx> { pub fn as_predicate(self) -> Predicate<'tcx> {
Predicate(self.0) Predicate(self.0)
} }
@ -1296,12 +1291,25 @@ impl<'tcx> ToPredicate<'tcx, PolyTraitPredicate<'tcx>> for Binder<'tcx, TraitRef
} }
} }
impl<'tcx> ToPredicate<'tcx> for TraitPredicate<'tcx> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
PredicateKind::Clause(ClauseKind::Trait(self)).to_predicate(tcx)
}
}
impl<'tcx> ToPredicate<'tcx> for PolyTraitPredicate<'tcx> { impl<'tcx> ToPredicate<'tcx> for PolyTraitPredicate<'tcx> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
self.map_bound(|p| PredicateKind::Clause(ClauseKind::Trait(p))).to_predicate(tcx) self.map_bound(|p| PredicateKind::Clause(ClauseKind::Trait(p))).to_predicate(tcx)
} }
} }
impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for TraitPredicate<'tcx> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
let p: Predicate<'tcx> = self.to_predicate(tcx);
p.expect_clause()
}
}
impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for PolyTraitPredicate<'tcx> { impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for PolyTraitPredicate<'tcx> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
let p: Predicate<'tcx> = self.to_predicate(tcx); let p: Predicate<'tcx> = self.to_predicate(tcx);
@ -1340,9 +1348,10 @@ impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for ProjectionPredicate<'tcx> {
} }
} }
impl<'tcx> ToPredicate<'tcx> for TraitPredicate<'tcx> { impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for PolyProjectionPredicate<'tcx> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
PredicateKind::Clause(ClauseKind::Trait(self)).to_predicate(tcx) let p: Predicate<'tcx> = self.to_predicate(tcx);
p.expect_clause()
} }
} }

View File

@ -725,7 +725,7 @@ impl<'tcx> PolyExistentialPredicate<'tcx> {
self.rebind(tr).with_self_ty(tcx, self_ty).to_predicate(tcx) self.rebind(tr).with_self_ty(tcx, self_ty).to_predicate(tcx)
} }
ExistentialPredicate::Projection(p) => { ExistentialPredicate::Projection(p) => {
ty::Clause::from_projection_clause(tcx, self.rebind(p.with_self_ty(tcx, self_ty))) self.rebind(p.with_self_ty(tcx, self_ty)).to_predicate(tcx)
} }
ExistentialPredicate::AutoTrait(did) => { ExistentialPredicate::AutoTrait(did) => {
let generics = tcx.generics_of(did); let generics = tcx.generics_of(did);

View File

@ -346,14 +346,13 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
ty::TraitRef::from_lang_item(tcx, LangItem::Sized, DUMMY_SP, [output]) ty::TraitRef::from_lang_item(tcx, LangItem::Sized, DUMMY_SP, [output])
}); });
let pred = ty::Clause::from_projection_clause( let pred = tupled_inputs_and_output
tcx, .map_bound(|(inputs, output)| ty::ProjectionPredicate {
tupled_inputs_and_output.map_bound(|(inputs, output)| ty::ProjectionPredicate {
projection_ty: tcx projection_ty: tcx
.mk_alias_ty(goal.predicate.def_id(), [goal.predicate.self_ty(), inputs]), .mk_alias_ty(goal.predicate.def_id(), [goal.predicate.self_ty(), inputs]),
term: output.into(), term: output.into(),
}), })
); .to_predicate(tcx);
// A built-in `Fn` impl only holds if the output is sized. // 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...) // (FIXME: technically we only need to check this if the type is a fn ptr...)

View File

@ -1644,7 +1644,7 @@ fn assemble_candidates_from_object_ty<'cx, 'tcx>(
let env_predicates = data let env_predicates = data
.projection_bounds() .projection_bounds()
.filter(|bound| bound.item_def_id() == obligation.predicate.def_id) .filter(|bound| bound.item_def_id() == obligation.predicate.def_id)
.map(|p| ty::Clause::from_projection_clause(tcx, p.with_self_ty(tcx, object_ty))); .map(|p| p.with_self_ty(tcx, object_ty).to_predicate(tcx));
assemble_candidates_from_predicates( assemble_candidates_from_predicates(
selcx, selcx,

View File

@ -105,13 +105,13 @@ pub fn unnormalized_obligations<'tcx>(
/// Returns the obligations that make this trait reference /// Returns the obligations that make this trait reference
/// well-formed. For example, if there is a trait `Set` defined like /// well-formed. For example, if there is a trait `Set` defined like
/// `trait Set<K:Eq>`, then the trait reference `Foo: Set<Bar>` is WF /// `trait Set<K: Eq>`, then the trait bound `Foo: Set<Bar>` is WF
/// if `Bar: Eq`. /// if `Bar: Eq`.
pub fn trait_obligations<'tcx>( pub fn trait_obligations<'tcx>(
infcx: &InferCtxt<'tcx>, infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
body_id: LocalDefId, body_id: LocalDefId,
trait_pred: &ty::TraitPredicate<'tcx>, trait_pred: ty::TraitPredicate<'tcx>,
span: Span, span: Span,
item: &'tcx hir::Item<'tcx>, item: &'tcx hir::Item<'tcx>,
) -> Vec<traits::PredicateObligation<'tcx>> { ) -> Vec<traits::PredicateObligation<'tcx>> {
@ -129,12 +129,17 @@ pub fn trait_obligations<'tcx>(
wf.normalize(infcx) wf.normalize(infcx)
} }
/// Returns the requirements for `clause` to be well-formed.
///
/// For example, if there is a trait `Set` defined like
/// `trait Set<K: Eq>`, then the trait bound `Foo: Set<Bar>` is WF
/// if `Bar: Eq`.
#[instrument(skip(infcx), ret)] #[instrument(skip(infcx), ret)]
pub fn predicate_obligations<'tcx>( pub fn clause_obligations<'tcx>(
infcx: &InferCtxt<'tcx>, infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
body_id: LocalDefId, body_id: LocalDefId,
predicate: ty::Predicate<'tcx>, clause: ty::Clause<'tcx>,
span: Span, span: Span,
) -> Vec<traits::PredicateObligation<'tcx>> { ) -> Vec<traits::PredicateObligation<'tcx>> {
let mut wf = WfPredicates { let mut wf = WfPredicates {
@ -148,45 +153,32 @@ pub fn predicate_obligations<'tcx>(
}; };
// It's ok to skip the binder here because wf code is prepared for it // It's ok to skip the binder here because wf code is prepared for it
match predicate.kind().skip_binder() { match clause.kind().skip_binder() {
ty::PredicateKind::Clause(ty::ClauseKind::Trait(t)) => { ty::ClauseKind::Trait(t) => {
wf.compute_trait_pred(&t, Elaborate::None); wf.compute_trait_pred(t, Elaborate::None);
} }
ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(..)) => {} ty::ClauseKind::RegionOutlives(..) => {}
ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate( ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, _reg)) => {
ty,
_reg,
))) => {
wf.compute(ty.into()); wf.compute(ty.into());
} }
ty::PredicateKind::Clause(ty::ClauseKind::Projection(t)) => { ty::ClauseKind::Projection(t) => {
wf.compute_projection(t.projection_ty); wf.compute_projection(t.projection_ty);
wf.compute(match t.term.unpack() { wf.compute(match t.term.unpack() {
ty::TermKind::Ty(ty) => ty.into(), ty::TermKind::Ty(ty) => ty.into(),
ty::TermKind::Const(c) => c.into(), ty::TermKind::Const(c) => c.into(),
}) })
} }
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => { ty::ClauseKind::ConstArgHasType(ct, ty) => {
wf.compute(ct.into()); wf.compute(ct.into());
wf.compute(ty.into()); wf.compute(ty.into());
} }
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => { ty::ClauseKind::WellFormed(arg) => {
wf.compute(arg); wf.compute(arg);
} }
ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(ct)) => { ty::ClauseKind::ConstEvaluatable(ct) => {
wf.compute(ct.into()); wf.compute(ct.into());
} }
ty::PredicateKind::ObjectSafe(_)
| ty::PredicateKind::ClosureKind(..)
| ty::PredicateKind::Subtype(..)
| ty::PredicateKind::Coerce(..)
| ty::PredicateKind::ConstEquate(..)
| ty::PredicateKind::Ambiguous
| ty::PredicateKind::AliasRelate(..) => {
bug!("We should only wf check where clauses, unexpected predicate: {predicate:?}")
}
} }
wf.normalize(infcx) wf.normalize(infcx)
@ -233,7 +225,7 @@ enum Elaborate {
fn extend_cause_with_original_assoc_item_obligation<'tcx>( fn extend_cause_with_original_assoc_item_obligation<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
trait_ref: &ty::TraitRef<'tcx>, trait_ref: ty::TraitRef<'tcx>,
item: Option<&hir::Item<'tcx>>, item: Option<&hir::Item<'tcx>>,
cause: &mut traits::ObligationCause<'tcx>, cause: &mut traits::ObligationCause<'tcx>,
pred: ty::Predicate<'tcx>, pred: ty::Predicate<'tcx>,
@ -336,9 +328,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
} }
/// Pushes the obligations required for `trait_ref` to be WF into `self.out`. /// Pushes the obligations required for `trait_ref` to be WF into `self.out`.
fn compute_trait_pred(&mut self, trait_pred: &ty::TraitPredicate<'tcx>, elaborate: Elaborate) { fn compute_trait_pred(&mut self, trait_pred: ty::TraitPredicate<'tcx>, elaborate: Elaborate) {
let tcx = self.tcx(); let tcx = self.tcx();
let trait_ref = &trait_pred.trait_ref; let trait_ref = trait_pred.trait_ref;
// Negative trait predicates don't require supertraits to hold, just // Negative trait predicates don't require supertraits to hold, just
// that their args are WF. // that their args are WF.
@ -411,7 +403,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
// Compute the obligations that are required for `trait_ref` to be WF, // Compute the obligations that are required for `trait_ref` to be WF,
// given that it is a *negative* trait predicate. // given that it is a *negative* trait predicate.
fn compute_negative_trait_pred(&mut self, trait_ref: &ty::TraitRef<'tcx>) { fn compute_negative_trait_pred(&mut self, trait_ref: ty::TraitRef<'tcx>) {
for arg in trait_ref.args { for arg in trait_ref.args {
self.compute(arg); self.compute(arg);
} }

View File

@ -3,9 +3,8 @@ use rustc_hir as hir;
use rustc_hir::def::DefKind; use rustc_hir::def::DefKind;
use rustc_index::bit_set::BitSet; use rustc_index::bit_set::BitSet;
use rustc_middle::query::Providers; use rustc_middle::query::Providers;
use rustc_middle::ty::{ use rustc_middle::ty::{self, EarlyBinder, Ty, TyCtxt, TypeVisitor};
self, EarlyBinder, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, use rustc_middle::ty::{ToPredicate, TypeSuperVisitable, TypeVisitable};
};
use rustc_span::def_id::{DefId, LocalDefId, CRATE_DEF_ID}; use rustc_span::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
use rustc_span::DUMMY_SP; use rustc_span::DUMMY_SP;
use rustc_trait_selection::traits; use rustc_trait_selection::traits;
@ -214,10 +213,10 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
// strategy, then just reinterpret the associated type like an opaque :^) // strategy, then just reinterpret the associated type like an opaque :^)
let default_ty = self.tcx.type_of(shifted_alias_ty.def_id).instantiate(self.tcx, shifted_alias_ty.args); let default_ty = self.tcx.type_of(shifted_alias_ty.def_id).instantiate(self.tcx, shifted_alias_ty.args);
self.predicates.push(ty::Clause::from_projection_clause(self.tcx, ty::Binder::bind_with_vars( self.predicates.push(ty::Binder::bind_with_vars(
ty::ProjectionPredicate { projection_ty: shifted_alias_ty, term: default_ty.into() }, ty::ProjectionPredicate { projection_ty: shifted_alias_ty, term: default_ty.into() },
self.bound_vars, self.bound_vars,
))); ).to_predicate(self.tcx));
// We walk the *un-shifted* alias ty, because we're tracking the de bruijn // We walk the *un-shifted* alias ty, because we're tracking the de bruijn
// binder depth, and if we were to walk `shifted_alias_ty` instead, we'd // binder depth, and if we were to walk `shifted_alias_ty` instead, we'd