@@ -116,10 +116,20 @@ crate fn program_clauses_for<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefI
116116 -> Lrc < Vec < Clause < ' tcx > > >
117117{
118118 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+ } ,
123133
124134 // FIXME: other constructions e.g. traits, associated types...
125135 _ => Lrc :: new ( vec ! [ ] ) ,
@@ -229,6 +239,53 @@ fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId
229239 Lrc :: new ( vec ! [ Clause :: ForAll ( ty:: Binder :: dummy( clause) ) ] )
230240}
231241
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+
232289pub fn dump_program_clauses < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ) {
233290 if !tcx. features ( ) . rustc_attrs {
234291 return ;
0 commit comments