@@ -11,6 +11,8 @@ use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness};
11
11
use super :: { Normalized , Obligation , ObligationCause , PredicateObligation , SelectionContext } ;
12
12
pub use rustc_infer:: traits:: util:: * ;
13
13
14
+ use std:: iter;
15
+
14
16
///////////////////////////////////////////////////////////////////////////
15
17
// `TraitAliasExpander` iterator
16
18
///////////////////////////////////////////////////////////////////////////
@@ -357,6 +359,59 @@ pub fn impl_item_is_final(tcx: TyCtxt<'_>, assoc_item: &ty::AssocItem) -> bool {
357
359
assoc_item. defaultness . is_final ( ) && tcx. impl_defaultness ( assoc_item. container . id ( ) ) . is_final ( )
358
360
}
359
361
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
+
360
415
pub enum TupleArgumentsFlag {
361
416
Yes ,
362
417
No ,
0 commit comments