Skip to content

Commit 96ff827

Browse files
committed
Add chalk rules related to associated type defs
* Rule ProjectionEq-Skolemize * Rule WellFormed-AssocTy * Rule Implied-Trait-From-AssocTy
1 parent 663002f commit 96ff827

File tree

3 files changed

+106
-19
lines changed

3 files changed

+106
-19
lines changed

src/librustc_traits/lowering.rs

+85-8
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,7 @@ fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId
362362
.map(|wc| tcx.mk_goal(GoalKind::from_poly_domain_goal(wc, tcx))),
363363
),
364364
};
365-
tcx.intern_clauses(&[Clause::ForAll(ty::Binder::dummy(clause))])
365+
tcx.mk_clauses(iter::once(Clause::ForAll(ty::Binder::dummy(clause))))
366366
}
367367

368368
pub fn program_clauses_for_type_def<'a, 'tcx>(
@@ -430,10 +430,86 @@ pub fn program_clauses_for_type_def<'a, 'tcx>(
430430
}
431431

432432
pub fn program_clauses_for_associated_type_def<'a, 'tcx>(
433-
_tcx: TyCtxt<'a, 'tcx, 'tcx>,
434-
_item_id: DefId,
433+
tcx: TyCtxt<'a, 'tcx, 'tcx>,
434+
item_id: DefId,
435435
) -> Clauses<'tcx> {
436-
unimplemented!()
436+
// Rule ProjectionEq-Skolemize
437+
//
438+
// ```
439+
// trait Trait<P1..Pn> {
440+
// type AssocType<Pn+1..Pm>;
441+
// }
442+
// ```
443+
//
444+
// `ProjectionEq` can succeed by skolemizing, see "associated type"
445+
// chapter for more:
446+
// ```
447+
// forall<Self, P1..Pn, Pn+1..Pm> {
448+
// ProjectionEq(
449+
// <Self as Trait<P1..Pn>>::AssocType<Pn+1..Pm> =
450+
// (Trait::AssocType)<Self, P1..Pn, Pn+1..Pm>
451+
// )
452+
// }
453+
// ```
454+
455+
let item = tcx.associated_item(item_id);
456+
debug_assert_eq!(item.kind, ty::AssociatedKind::Type);
457+
let trait_id = match item.container {
458+
ty::AssociatedItemContainer::TraitContainer(trait_id) => trait_id,
459+
_ => bug!("not an trait container"),
460+
};
461+
let trait_ref = ty::TraitRef::identity(tcx, trait_id);
462+
463+
let projection_ty = ty::ProjectionTy::from_ref_and_name(tcx, trait_ref, item.ident);
464+
let placeholder_ty = tcx.mk_ty(ty::UnnormalizedProjection(projection_ty));
465+
let projection_eq = WhereClause::ProjectionEq(ty::ProjectionPredicate {
466+
projection_ty,
467+
ty: placeholder_ty,
468+
});
469+
470+
let projection_eq_clause = ProgramClause {
471+
goal: DomainGoal::Holds(projection_eq),
472+
hypotheses: &ty::List::empty(),
473+
};
474+
475+
// Rule WellFormed-AssocTy
476+
// ```
477+
// forall<Self, P1..Pn, Pn+1..Pm> {
478+
// WellFormed((Trait::AssocType)<Self, P1..Pn, Pn+1..Pm>)
479+
// :- Implemented(Self: Trait<P1..Pn>)
480+
// }
481+
// ```
482+
483+
let trait_predicate = ty::TraitPredicate { trait_ref };
484+
let hypothesis = tcx.mk_goal(
485+
DomainGoal::Holds(WhereClause::Implemented(trait_predicate)).into_goal()
486+
);
487+
let wf_clause = ProgramClause {
488+
goal: DomainGoal::WellFormed(WellFormed::Ty(placeholder_ty)),
489+
hypotheses: tcx.mk_goals(iter::once(hypothesis)),
490+
};
491+
492+
// Rule Implied-Trait-From-AssocTy
493+
// ```
494+
// forall<Self, P1..Pn, Pn+1..Pm> {
495+
// FromEnv(Self: Trait<P1..Pn>)
496+
// :- FromEnv((Trait::AssocType)<Self, P1..Pn, Pn+1..Pm>)
497+
// }
498+
// ```
499+
500+
let hypothesis = tcx.mk_goal(
501+
DomainGoal::FromEnv(FromEnv::Ty(placeholder_ty)).into_goal()
502+
);
503+
let from_env_clause = ProgramClause {
504+
goal: DomainGoal::FromEnv(FromEnv::Trait(trait_predicate)),
505+
hypotheses: tcx.mk_goals(iter::once(hypothesis)),
506+
};
507+
508+
let clauses = iter::once(projection_eq_clause)
509+
.chain(iter::once(wf_clause))
510+
.chain(iter::once(from_env_clause));
511+
let clauses = clauses.map(|clause| Clause::ForAll(ty::Binder::dummy(clause)));
512+
tcx.mk_clauses(clauses)
437513
}
438514

439515
pub fn program_clauses_for_associated_type_value<'a, 'tcx>(
@@ -442,10 +518,11 @@ pub fn program_clauses_for_associated_type_value<'a, 'tcx>(
442518
) -> Clauses<'tcx> {
443519
// Rule Normalize-From-Impl (see rustc guide)
444520
//
445-
// ```impl<P0..Pn> Trait<A1..An> for A0
446-
// {
521+
// ```
522+
// impl<P0..Pn> Trait<A1..An> for A0 {
447523
// type AssocType<Pn+1..Pm> = T;
448-
// }```
524+
// }
525+
// ```
449526
//
450527
// FIXME: For the moment, we don't account for where clauses written on the associated
451528
// ty definition (i.e. in the trait def, as in `type AssocType<T> where T: Sized`).
@@ -492,7 +569,7 @@ pub fn program_clauses_for_associated_type_value<'a, 'tcx>(
492569
.map(|wc| tcx.mk_goal(GoalKind::from_poly_domain_goal(wc, tcx))),
493570
),
494571
};
495-
tcx.intern_clauses(&[Clause::ForAll(ty::Binder::dummy(clause))])
572+
tcx.mk_clauses(iter::once(Clause::ForAll(ty::Binder::dummy(clause))))
496573
}
497574

498575
pub fn dump_program_clauses<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {

src/test/ui/chalkify/lower_trait.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,12 @@
1010

1111
#![feature(rustc_attrs)]
1212

13+
trait Bar { }
14+
1315
#[rustc_dump_program_clauses] //~ ERROR program clause dump
14-
trait Foo<S, T, U> {
15-
fn s(_: S) -> S;
16-
fn t(_: T) -> T;
17-
fn u(_: U) -> U;
16+
trait Foo<S, T: ?Sized> {
17+
#[rustc_dump_program_clauses] //~ ERROR program clause dump
18+
type Assoc: Bar + ?Sized;
1819
}
1920

2021
fn main() {
+16-7
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,23 @@
11
error: program clause dump
2-
--> $DIR/lower_trait.rs:13:1
2+
--> $DIR/lower_trait.rs:15:1
33
|
44
LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66
|
7-
= note: FromEnv(S: std::marker::Sized) :- FromEnv(Self: Foo<S, T, U>).
8-
= note: FromEnv(T: std::marker::Sized) :- FromEnv(Self: Foo<S, T, U>).
9-
= note: FromEnv(U: std::marker::Sized) :- FromEnv(Self: Foo<S, T, U>).
10-
= note: Implemented(Self: Foo<S, T, U>) :- FromEnv(Self: Foo<S, T, U>).
11-
= note: WellFormed(Self: Foo<S, T, U>) :- Implemented(Self: Foo<S, T, U>), WellFormed(S: std::marker::Sized), WellFormed(T: std::marker::Sized), WellFormed(U: std::marker::Sized).
7+
= note: FromEnv(<Self as Foo<S, T>>::Assoc: Bar) :- FromEnv(Self: Foo<S, T>).
8+
= note: FromEnv(S: std::marker::Sized) :- FromEnv(Self: Foo<S, T>).
9+
= note: Implemented(Self: Foo<S, T>) :- FromEnv(Self: Foo<S, T>).
10+
= note: WellFormed(Self: Foo<S, T>) :- Implemented(Self: Foo<S, T>), WellFormed(S: std::marker::Sized), WellFormed(<Self as Foo<S, T>>::Assoc: Bar).
1211

13-
error: aborting due to previous error
12+
error: program clause dump
13+
--> $DIR/lower_trait.rs:17:5
14+
|
15+
LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
16+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
17+
|
18+
= note: FromEnv(Self: Foo<S, T>) :- FromEnv(Unnormalized(<Self as Foo<S, T>>::Assoc)).
19+
= note: ProjectionEq(<Self as Foo<S, T>>::Assoc == Unnormalized(<Self as Foo<S, T>>::Assoc)).
20+
= note: WellFormed(Unnormalized(<Self as Foo<S, T>>::Assoc)) :- Implemented(Self: Foo<S, T>).
21+
22+
error: aborting due to 2 previous errors
1423

0 commit comments

Comments
 (0)