Skip to content

Commit 0a76584

Browse files
committed
Move some code from rustc_typeck to rustc_trait_selection
1 parent d4d9e7f commit 0a76584

File tree

2 files changed

+56
-0
lines changed

2 files changed

+56
-0
lines changed

compiler/rustc_trait_selection/src/traits/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ pub use self::specialize::specialization_graph::FutureCompatOverlapErrorKind;
5959
pub use self::specialize::{specialization_graph, translate_substs, OverlapError};
6060
pub use self::structural_match::search_for_structural_match_violation;
6161
pub use self::structural_match::NonStructuralMatchTy;
62+
pub use self::util::subst_assoc_item_bound;
6263
pub use self::util::{elaborate_predicates, elaborate_trait_ref, elaborate_trait_refs};
6364
pub use self::util::{expand_trait_aliases, TraitAliasExpander};
6465
pub use self::util::{

compiler/rustc_trait_selection/src/traits/util.rs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness};
1111
use super::{Normalized, Obligation, ObligationCause, PredicateObligation, SelectionContext};
1212
pub use rustc_infer::traits::util::*;
1313

14+
use std::iter;
15+
1416
///////////////////////////////////////////////////////////////////////////
1517
// `TraitAliasExpander` iterator
1618
///////////////////////////////////////////////////////////////////////////
@@ -357,6 +359,59 @@ pub fn impl_item_is_final(tcx: TyCtxt<'_>, assoc_item: &ty::AssocItem) -> bool {
357359
assoc_item.defaultness.is_final() && tcx.impl_defaultness(assoc_item.container.id()).is_final()
358360
}
359361

362+
/// Map a bound from an associated item to apply to some other type.
363+
/// For example, given the following trait
364+
///
365+
/// trait X<A> { type Y<'a>: PartialEq<A> }
366+
///
367+
/// Say that we know that `<() as X<B>>::Y<'c> = i32` and we need to check that
368+
/// the `PartialEq` bound applies. This function would return
369+
/// `i32: PartialEq<B>`.
370+
pub fn subst_assoc_item_bound<'tcx>(
371+
tcx: TyCtxt<'tcx>,
372+
bound: ty::Predicate<'tcx>,
373+
normalized_projection_ty: Ty<'tcx>,
374+
assoc_item_substs: &[GenericArg<'tcx>],
375+
) -> ty::Predicate<'tcx> {
376+
let translate_predicate_substs = move |predicate_substs: SubstsRef<'tcx>| {
377+
tcx.mk_substs(
378+
iter::once(normalized_projection_ty.into())
379+
.chain(predicate_substs[1..].iter().map(|s| s.subst(tcx, assoc_item_substs))),
380+
)
381+
};
382+
383+
match bound.kind() {
384+
ty::PredicateKind::Trait(poly_tr, c) => poly_tr
385+
.map_bound(|tr| {
386+
let trait_substs = translate_predicate_substs(tr.trait_ref.substs);
387+
ty::TraitRef { def_id: tr.def_id(), substs: trait_substs }
388+
})
389+
.with_constness(*c)
390+
.to_predicate(tcx),
391+
ty::PredicateKind::Projection(poly_projection) => poly_projection
392+
.map_bound(|projection| {
393+
let projection_substs = translate_predicate_substs(projection.projection_ty.substs);
394+
ty::ProjectionPredicate {
395+
projection_ty: ty::ProjectionTy {
396+
substs: projection_substs,
397+
item_def_id: projection.projection_ty.item_def_id,
398+
},
399+
ty: projection.ty.subst(tcx, assoc_item_substs),
400+
}
401+
})
402+
.to_predicate(tcx),
403+
ty::PredicateKind::TypeOutlives(poly_outlives) => poly_outlives
404+
.map_bound(|outlives| {
405+
ty::OutlivesPredicate(
406+
normalized_projection_ty,
407+
outlives.1.subst(tcx, assoc_item_substs),
408+
)
409+
})
410+
.to_predicate(tcx),
411+
_ => bug!("unexepected projection bound: `{:?}`", bound),
412+
}
413+
}
414+
360415
pub enum TupleArgumentsFlag {
361416
Yes,
362417
No,

0 commit comments

Comments
 (0)