@@ -106,6 +106,7 @@ impl<'tcx> IntoFromEnvGoal for DomainGoal<'tcx> {
106
106
FromEnv ( ..) |
107
107
WellFormedTy ( ..) |
108
108
FromEnvTy ( ..) |
109
+ Normalize ( ..) |
109
110
RegionOutlives ( ..) |
110
111
TypeOutlives ( ..) => self ,
111
112
}
@@ -116,10 +117,20 @@ crate fn program_clauses_for<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefI
116
117
-> Lrc < Vec < Clause < ' tcx > > >
117
118
{
118
119
let node_id = tcx. hir . as_local_node_id ( def_id) . unwrap ( ) ;
119
- let item = tcx. hir . expect_item ( node_id) ;
120
- match item. node {
121
- hir:: ItemTrait ( ..) => program_clauses_for_trait ( tcx, def_id) ,
122
- hir:: ItemImpl ( ..) => program_clauses_for_impl ( tcx, def_id) ,
120
+ let node = tcx. hir . find ( node_id) . unwrap ( ) ;
121
+ match node {
122
+ hir:: map:: Node :: NodeItem ( item) => match item. node {
123
+ hir:: ItemTrait ( ..) => program_clauses_for_trait ( tcx, def_id) ,
124
+ hir:: ItemImpl ( ..) => program_clauses_for_impl ( tcx, def_id) ,
125
+ _ => Lrc :: new ( vec ! [ ] ) ,
126
+ }
127
+ hir:: map:: Node :: NodeImplItem ( item) => {
128
+ if let hir:: ImplItemKind :: Type ( ..) = item. node {
129
+ program_clauses_for_associated_type_value ( tcx, def_id)
130
+ } else {
131
+ Lrc :: new ( vec ! [ ] )
132
+ }
133
+ } ,
123
134
124
135
// FIXME: other constructions e.g. traits, associated types...
125
136
_ => Lrc :: new ( vec ! [ ] ) ,
@@ -229,6 +240,56 @@ fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId
229
240
Lrc :: new ( vec ! [ Clause :: ForAll ( ty:: Binder :: dummy( clause) ) ] )
230
241
}
231
242
243
+ pub fn program_clauses_for_associated_type_value < ' a , ' tcx > (
244
+ tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
245
+ item_id : DefId ,
246
+ ) -> Lrc < Vec < Clause < ' tcx > > > {
247
+ // Rule Normalize-From-Impl (see rustc guide)
248
+ //
249
+ // ```impl<P0..Pn> Trait<A1..An> for A0
250
+ // {
251
+ // type AssocType<Pn+1..Pm> where WC = T;
252
+ // }```
253
+ //
254
+ // ```
255
+ // forall<P0..Pm> {
256
+ // forall<Pn+1..Pm> {
257
+ // Normalize(<A0 as Trait<A1..An>>::AssocType<Pn+1..Pm> -> T) :-
258
+ // Implemented(A0: Trait<A1..An>) && WC
259
+ // }
260
+ // }
261
+ // ```
262
+
263
+ let item = tcx. associated_item ( item_id) ;
264
+ debug_assert_eq ! ( item. kind, ty:: AssociatedKind :: Type ) ;
265
+ let impl_id = if let ty:: AssociatedItemContainer :: ImplContainer ( impl_id) = item. container {
266
+ impl_id
267
+ } else {
268
+ bug ! ( )
269
+ } ;
270
+ // `A0 as Trait<A1..An>`
271
+ let trait_ref = tcx. impl_trait_ref ( impl_id) . unwrap ( ) ;
272
+ // `T`
273
+ let ty = tcx. type_of ( item_id) ;
274
+ // `Implemented(A0: Trait<A1..An>)`
275
+ let trait_implemented = ty:: Binder :: dummy ( ty:: TraitPredicate { trait_ref } . lower ( ) ) ;
276
+ // `WC`
277
+ let item_where_clauses = tcx. predicates_of ( item_id) . predicates . lower ( ) ;
278
+ // `Implemented(A0: Trait<A1..An>) && WC`
279
+ let mut where_clauses = vec ! [ trait_implemented] ;
280
+ where_clauses. extend ( item_where_clauses) ;
281
+ // `<A0 as Trait<A1..An>>::AssocType<Pn+1..Pm>`
282
+ let projection_ty = ty:: ProjectionTy :: from_ref_and_name ( tcx, trait_ref, item. name ) ;
283
+ // `Normalize(<A0 as Trait<A1..An>>::AssocType<Pn+1..Pm> -> T)`
284
+ let normalize_goal = DomainGoal :: Normalize ( ty:: ProjectionPredicate { projection_ty, ty } ) ;
285
+ // `Normalize(... -> T) :- ...`
286
+ let clause = ProgramClause {
287
+ goal : normalize_goal,
288
+ hypotheses : where_clauses. into_iter ( ) . map ( |wc| wc. into ( ) ) . collect ( ) ,
289
+ } ;
290
+ Lrc :: new ( vec ! [ Clause :: ForAll ( ty:: Binder :: dummy( clause) ) ] )
291
+ }
292
+
232
293
pub fn dump_program_clauses < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ) {
233
294
if !tcx. features ( ) . rustc_attrs {
234
295
return ;
0 commit comments