@@ -496,9 +496,51 @@ pub fn program_clauses_for_associated_type_def<'a, 'tcx>(
496496 } ;
497497 let from_env_clause = Clause :: ForAll ( ty:: Binder :: bind ( from_env_clause) ) ;
498498
499+ // Rule ProjectionEq-Normalize
500+ //
501+ // ProjectionEq can succeed by normalizing:
502+ // ```
503+ // forall<Self, P1..Pn, Pn+1..Pm, U> {
504+ // ProjectionEq(<Self as Trait<P1..Pn>>::AssocType<Pn+1..Pm> = U) :-
505+ // Normalize(<Self as Trait<P1..Pn>>::AssocType<Pn+1..Pm> -> U)
506+ // }
507+ // ```
508+
509+ let offset = tcx. generics_of ( trait_id) . params
510+ . iter ( )
511+ . map ( |p| p. index )
512+ . max ( )
513+ . unwrap_or ( 0 ) ;
514+ // Add a new type param after the existing ones (`U` in the comment above).
515+ let ty_var = ty:: Bound (
516+ ty:: BoundTy :: new ( ty:: INNERMOST , ty:: BoundVar :: from_u32 ( offset + 1 ) )
517+ ) ;
518+
519+ // `ProjectionEq(<Self as Trait<P1..Pn>>::AssocType<Pn+1..Pm> = U)`
520+ let projection = ty:: ProjectionPredicate {
521+ projection_ty,
522+ ty : tcx. mk_ty ( ty_var) ,
523+ } ;
524+
525+ // `Normalize(<A0 as Trait<A1..An>>::AssocType<Pn+1..Pm> -> U)`
526+ let hypothesis = tcx. mk_goal (
527+ DomainGoal :: Normalize ( projection) . into_goal ( )
528+ ) ;
529+
530+ // ProjectionEq(<Self as Trait<P1..Pn>>::AssocType<Pn+1..Pm> = U) :-
531+ // Normalize(<Self as Trait<P1..Pn>>::AssocType<Pn+1..Pm> -> U)
532+ let normalize_clause = ProgramClause {
533+ goal : DomainGoal :: Holds ( WhereClause :: ProjectionEq ( projection) ) ,
534+ hypotheses : tcx. mk_goals ( iter:: once ( hypothesis) ) ,
535+ category : ProgramClauseCategory :: Other ,
536+ } ;
537+ let normalize_clause = Clause :: ForAll ( ty:: Binder :: bind ( normalize_clause) ) ;
538+
499539 let clauses = iter:: once ( projection_eq_clause)
500540 . chain ( iter:: once ( wf_clause) )
501- . chain ( iter:: once ( from_env_clause) ) ;
541+ . chain ( iter:: once ( from_env_clause) )
542+ . chain ( iter:: once ( normalize_clause) ) ;
543+
502544 tcx. mk_clauses ( clauses)
503545}
504546
0 commit comments