@@ -90,6 +90,28 @@ impl<'tcx> Lower<PolyDomainGoal<'tcx>> for ty::Predicate<'tcx> {
90
90
}
91
91
}
92
92
93
+ /// Transforms an existing goal into a FromEnv goal.
94
+ ///
95
+ /// Used for lowered where clauses (see rustc guide).
96
+ trait IntoFromEnvGoal {
97
+ fn into_from_env_goal ( self ) -> Self ;
98
+ }
99
+
100
+ impl < ' tcx > IntoFromEnvGoal for DomainGoal < ' tcx > {
101
+ fn into_from_env_goal ( self ) -> DomainGoal < ' tcx > {
102
+ use self :: DomainGoal :: * ;
103
+ match self {
104
+ Holds ( wc_atom) => FromEnv ( wc_atom) ,
105
+ WellFormed ( ..) |
106
+ FromEnv ( ..) |
107
+ WellFormedTy ( ..) |
108
+ FromEnvTy ( ..) |
109
+ RegionOutlives ( ..) |
110
+ TypeOutlives ( ..) => self ,
111
+ }
112
+ }
113
+ }
114
+
93
115
crate fn program_clauses_for < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > , def_id : DefId )
94
116
-> Lrc < Vec < Clause < ' tcx > > >
95
117
{
@@ -107,9 +129,9 @@ crate fn program_clauses_for<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefI
107
129
fn program_clauses_for_trait < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > , def_id : DefId )
108
130
-> Lrc < Vec < Clause < ' tcx > > >
109
131
{
110
- // Rule Implemented-From-Env (see rustc guide)
111
- //
112
132
// `trait Trait<P1..Pn> where WC { .. } // P0 == Self`
133
+
134
+ // Rule Implemented-From-Env (see rustc guide)
113
135
//
114
136
// ```
115
137
// forall<Self, P1..Pn> {
@@ -130,11 +152,50 @@ fn program_clauses_for_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefI
130
152
let impl_trait = DomainGoal :: Holds ( WhereClauseAtom :: Implemented ( trait_pred) ) ;
131
153
132
154
// `Implemented(Self: Trait<P1..Pn>) :- FromEnv(Self: Trait<P1..Pn>)`
133
- let clause = ProgramClause {
155
+ let implemented_from_env = ProgramClause {
134
156
goal : impl_trait,
135
157
hypotheses : vec ! [ from_env] ,
136
158
} ;
137
- Lrc :: new ( vec ! [ Clause :: ForAll ( ty:: Binder :: dummy( clause) ) ] )
159
+ let mut clauses = vec ! [
160
+ Clause :: ForAll ( ty:: Binder :: dummy( implemented_from_env) )
161
+ ] ;
162
+
163
+ // Rule Implied-Bound-From-Trait
164
+ //
165
+ // For each where clause WC:
166
+ // ```
167
+ // forall<Self, P1..Pn> {
168
+ // FromEnv(WC) :- FromEnv(Self: Trait<P1..Pn)
169
+ // }
170
+ // ```
171
+
172
+ // `FromEnv(WC) :- FromEnv(Self: Trait<P1..Pn>)`, for each where clause WC
173
+ // FIXME: Remove the [1..] slice; this is a hack because the query
174
+ // predicates_of currently includes the trait itself (`Self: Trait<P1..Pn>`).
175
+ let where_clauses = & tcx. predicates_of ( def_id) . predicates ;
176
+ let implied_bound_clauses =
177
+ where_clauses[ 1 ..] . into_iter ( )
178
+ . map ( |wc| implied_bound_from_trait ( trait_pred, wc) ) ;
179
+ clauses. extend ( implied_bound_clauses) ;
180
+
181
+ Lrc :: new ( clauses)
182
+ }
183
+
184
+ /// For a given `where_clause`, returns a clause `FromEnv(WC) :- FromEnv(Self: Trait<P1..Pn>)`.
185
+ fn implied_bound_from_trait < ' tcx > (
186
+ trait_pred : ty:: TraitPredicate < ' tcx > ,
187
+ where_clause : & ty:: Predicate < ' tcx > ,
188
+ ) -> Clause < ' tcx > {
189
+ // `FromEnv(Self: Trait<P1..Pn>)`
190
+ let impl_trait = DomainGoal :: FromEnv ( WhereClauseAtom :: Implemented ( trait_pred) ) ;
191
+
192
+ // `FromEnv(WC) :- FromEnv(Self: Trait<P1..Pn>)`
193
+ Clause :: ForAll (
194
+ where_clause. lower ( ) . map_bound ( |goal| ProgramClause {
195
+ goal : goal. into_from_env_goal ( ) ,
196
+ hypotheses : vec ! [ impl_trait. into( ) ] ,
197
+ } )
198
+ )
138
199
}
139
200
140
201
fn program_clauses_for_impl < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > , def_id : DefId )
0 commit comments