Move some code from rustc_typeck to rustc_trait_selection

This commit is contained in:
Matthew Jasper 2020-06-28 20:29:08 +01:00
parent d4d9e7f67f
commit 0a76584dcc
2 changed files with 56 additions and 0 deletions

View File

@ -59,6 +59,7 @@ pub use self::specialize::specialization_graph::FutureCompatOverlapErrorKind;
pub use self::specialize::{specialization_graph, translate_substs, OverlapError};
pub use self::structural_match::search_for_structural_match_violation;
pub use self::structural_match::NonStructuralMatchTy;
pub use self::util::subst_assoc_item_bound;
pub use self::util::{elaborate_predicates, elaborate_trait_ref, elaborate_trait_refs};
pub use self::util::{expand_trait_aliases, TraitAliasExpander};
pub use self::util::{

View File

@ -11,6 +11,8 @@ use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness};
use super::{Normalized, Obligation, ObligationCause, PredicateObligation, SelectionContext};
pub use rustc_infer::traits::util::*;
use std::iter;
///////////////////////////////////////////////////////////////////////////
// `TraitAliasExpander` iterator
///////////////////////////////////////////////////////////////////////////
@ -357,6 +359,59 @@ pub fn impl_item_is_final(tcx: TyCtxt<'_>, assoc_item: &ty::AssocItem) -> bool {
assoc_item.defaultness.is_final() && tcx.impl_defaultness(assoc_item.container.id()).is_final()
}
/// Map a bound from an associated item to apply to some other type.
/// For example, given the following trait
///
/// trait X<A> { type Y<'a>: PartialEq<A> }
///
/// Say that we know that `<() as X<B>>::Y<'c> = i32` and we need to check that
/// the `PartialEq` bound applies. This function would return
/// `i32: PartialEq<B>`.
pub fn subst_assoc_item_bound<'tcx>(
tcx: TyCtxt<'tcx>,
bound: ty::Predicate<'tcx>,
normalized_projection_ty: Ty<'tcx>,
assoc_item_substs: &[GenericArg<'tcx>],
) -> ty::Predicate<'tcx> {
let translate_predicate_substs = move |predicate_substs: SubstsRef<'tcx>| {
tcx.mk_substs(
iter::once(normalized_projection_ty.into())
.chain(predicate_substs[1..].iter().map(|s| s.subst(tcx, assoc_item_substs))),
)
};
match bound.kind() {
ty::PredicateKind::Trait(poly_tr, c) => poly_tr
.map_bound(|tr| {
let trait_substs = translate_predicate_substs(tr.trait_ref.substs);
ty::TraitRef { def_id: tr.def_id(), substs: trait_substs }
})
.with_constness(*c)
.to_predicate(tcx),
ty::PredicateKind::Projection(poly_projection) => poly_projection
.map_bound(|projection| {
let projection_substs = translate_predicate_substs(projection.projection_ty.substs);
ty::ProjectionPredicate {
projection_ty: ty::ProjectionTy {
substs: projection_substs,
item_def_id: projection.projection_ty.item_def_id,
},
ty: projection.ty.subst(tcx, assoc_item_substs),
}
})
.to_predicate(tcx),
ty::PredicateKind::TypeOutlives(poly_outlives) => poly_outlives
.map_bound(|outlives| {
ty::OutlivesPredicate(
normalized_projection_ty,
outlives.1.subst(tcx, assoc_item_substs),
)
})
.to_predicate(tcx),
_ => bug!("unexepected projection bound: `{:?}`", bound),
}
}
pub enum TupleArgumentsFlag {
Yes,
No,