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