@@ -4,6 +4,7 @@ use smallvec::smallvec;
4
4
5
5
use crate :: data_structures:: HashSet ;
6
6
use crate :: inherent:: * ;
7
+ use crate :: lang_items:: TraitSolverLangItem ;
7
8
use crate :: outlives:: { Component , push_outlives_components} ;
8
9
use crate :: { self as ty, Interner , Upcast as _} ;
9
10
@@ -89,6 +90,70 @@ impl<I: Interner, O: Elaboratable<I>> Elaborator<I, O> {
89
90
return ;
90
91
}
91
92
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
+
92
157
let map_to_child_clause =
93
158
|( index, ( clause, span) ) : ( usize , ( I :: Clause , I :: Span ) ) | {
94
159
elaboratable. child_with_derived_cause (
0 commit comments