Skip to content

Commit 126a0e2

Browse files
committed
Auto merge of #52153 - csmoe:projeq_normal, r=scalexm
chalk lowering rule: ProjectionEq-Normalize cc #49177 r? @scalexm
2 parents f1d6183 + e853d6c commit 126a0e2

File tree

2 files changed

+44
-1
lines changed

2 files changed

+44
-1
lines changed

src/librustc_traits/lowering/mod.rs

+43-1
Original file line numberDiff line numberDiff line change
@@ -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

src/test/ui/chalkify/lower_trait.stderr

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ error: program clause dump
1515
LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
1616
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1717
|
18+
= note: forall<Self, S, T, ^3> { ProjectionEq(<Self as Foo<S, T>>::Assoc == ^3) :- Normalize(<Self as Foo<S, T>>::Assoc -> ^3). }
1819
= note: forall<Self, S, T> { FromEnv(Self: Foo<S, T>) :- FromEnv(Unnormalized(<Self as Foo<S, T>>::Assoc)). }
1920
= note: forall<Self, S, T> { ProjectionEq(<Self as Foo<S, T>>::Assoc == Unnormalized(<Self as Foo<S, T>>::Assoc)). }
2021
= note: forall<Self, S, T> { WellFormed(Unnormalized(<Self as Foo<S, T>>::Assoc)) :- Implemented(Self: Foo<S, T>). }

0 commit comments

Comments
 (0)