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