@@ -4,6 +4,7 @@ use smallvec::smallvec;
44
55use crate :: data_structures:: HashSet ;
66use crate :: inherent:: * ;
7+ use crate :: lang_items:: TraitSolverLangItem ;
78use crate :: outlives:: { Component , push_outlives_components} ;
89use crate :: { self as ty, Interner , Upcast as _} ;
910
@@ -89,6 +90,70 @@ impl<I: Interner, O: Elaboratable<I>> Elaborator<I, O> {
8990 return ;
9091 }
9192
93+ // HACK(effects): The following code is required to get implied bounds for effects associated
94+ // types to work with super traits.
95+ //
96+ // Suppose `data` is a trait predicate with the form `<T as Tr>::Fx: EffectsCompat<somebool>`
97+ // and we know that `trait Tr: ~const SuperTr`, we need to elaborate this predicate into
98+ // `<T as SuperTr>::Fx: EffectsCompat<somebool>`.
99+ //
100+ // Since the semantics for elaborating bounds about effects is equivalent to elaborating
101+ // bounds about super traits (elaborate `T: Tr` into `T: SuperTr`), we place effects elaboration
102+ // next to super trait elaboration.
103+ if cx. is_lang_item ( data. def_id ( ) , TraitSolverLangItem :: EffectsCompat )
104+ && matches ! ( self . mode, Filter :: All )
105+ {
106+ // first, ensure that the predicate we've got looks like a `<T as Tr>::Fx: EffectsCompat<somebool>`.
107+ if let ty:: Alias ( ty:: AliasTyKind :: Projection , alias_ty) = data. self_ty ( ) . kind ( )
108+ {
109+ // look for effects-level bounds that look like `<Self as Tr>::Fx: TyCompat<<Self as SuperTr>::Fx>`
110+ // on the trait, which is proof to us that `Tr: ~const SuperTr`. We're looking for bounds on the
111+ // associated trait, so we use `explicit_implied_predicates_of` since it gives us more than just
112+ // `Self: SuperTr` bounds.
113+ let bounds = cx. explicit_implied_predicates_of ( cx. parent ( alias_ty. def_id ) ) ;
114+
115+ // instantiate the implied bounds, so we get `<T as Tr>::Fx` and not `<Self as Tr>::Fx`.
116+ let elaborated = bounds. iter_instantiated ( cx, alias_ty. args ) . filter_map (
117+ |( clause, _) | {
118+ let ty:: ClauseKind :: Trait ( tycompat_bound) =
119+ clause. kind ( ) . skip_binder ( )
120+ else {
121+ return None ;
122+ } ;
123+ if !cx. is_lang_item (
124+ tycompat_bound. def_id ( ) ,
125+ TraitSolverLangItem :: EffectsTyCompat ,
126+ ) {
127+ return None ;
128+ }
129+
130+ // extract `<T as SuperTr>::Fx` from the `TyCompat` bound.
131+ let supertrait_effects_ty =
132+ tycompat_bound. trait_ref . args . type_at ( 1 ) ;
133+ let ty:: Alias ( ty:: AliasTyKind :: Projection , supertrait_alias_ty) =
134+ supertrait_effects_ty. kind ( )
135+ else {
136+ return None ;
137+ } ;
138+
139+ // The self types (`T`) must be equal for `<T as Tr>::Fx` and `<T as SuperTr>::Fx`.
140+ if supertrait_alias_ty. self_ty ( ) != alias_ty. self_ty ( ) {
141+ return None ;
142+ } ;
143+
144+ // replace the self type in the original bound `<T as Tr>::Fx: EffectsCompat<somebool>`
145+ // to the effects type of the super trait. (`<T as SuperTr>::Fx`)
146+ let elaborated_bound = data. with_self_ty ( cx, supertrait_effects_ty) ;
147+ Some (
148+ elaboratable
149+ . child ( bound_clause. rebind ( elaborated_bound) . upcast ( cx) ) ,
150+ )
151+ } ,
152+ ) ;
153+ self . extend_deduped ( elaborated) ;
154+ }
155+ }
156+
92157 let map_to_child_clause =
93158 |( index, ( clause, span) ) : ( usize , ( I :: Clause , I :: Span ) ) | {
94159 elaboratable. child_with_derived_cause (
0 commit comments