@@ -90,6 +90,28 @@ impl<'tcx> Lower<PolyDomainGoal<'tcx>> for ty::Predicate<'tcx> {
9090 }
9191}
9292
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+
93115crate fn program_clauses_for < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > , def_id : DefId )
94116 -> Lrc < Vec < Clause < ' tcx > > >
95117{
@@ -107,9 +129,9 @@ crate fn program_clauses_for<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefI
107129fn program_clauses_for_trait < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > , def_id : DefId )
108130 -> Lrc < Vec < Clause < ' tcx > > >
109131{
110- // Rule Implemented-From-Env (see rustc guide)
111- //
112132 // `trait Trait<P1..Pn> where WC { .. } // P0 == Self`
133+
134+ // Rule Implemented-From-Env (see rustc guide)
113135 //
114136 // ```
115137 // forall<Self, P1..Pn> {
@@ -130,11 +152,50 @@ fn program_clauses_for_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefI
130152 let impl_trait = DomainGoal :: Holds ( WhereClauseAtom :: Implemented ( trait_pred) ) ;
131153
132154 // `Implemented(Self: Trait<P1..Pn>) :- FromEnv(Self: Trait<P1..Pn>)`
133- let clause = ProgramClause {
155+ let implemented_from_env = ProgramClause {
134156 goal : impl_trait,
135157 hypotheses : vec ! [ from_env] ,
136158 } ;
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+ )
138199}
139200
140201fn program_clauses_for_impl < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > , def_id : DefId )
0 commit comments