1 use crate::clauses
::builder
::ClauseBuilder
;
3 use crate::split
::Split
;
4 use chalk_ir
::cast
::{Cast, Caster}
;
5 use chalk_ir
::interner
::Interner
;
8 use tracing
::instrument
;
10 /// Trait for lowering a given piece of rust-ir source (e.g., an impl
11 /// or struct definition) into its associated "program clauses" --
12 /// that is, into the lowered, logical rules that it defines.
13 pub trait ToProgramClauses
<I
: Interner
> {
14 fn to_program_clauses(&self, builder
: &mut ClauseBuilder
<'_
, I
>, environment
: &Environment
<I
>);
17 impl<I
: Interner
> ToProgramClauses
<I
> for ImplDatum
<I
> {
18 /// Given `impl<T: Clone> Clone for Vec<T> { ... }`, generate:
21 /// -- Rule Implemented-From-Impl
23 /// Implemented(Vec<T>: Clone) :- Implemented(T: Clone).
27 /// For a negative impl like `impl... !Clone for ...`, however, we
28 /// generate nothing -- this is just a way to *opt out* from the
29 /// default auto trait impls, it doesn't have any positive effect
31 fn to_program_clauses(
33 builder
: &mut ClauseBuilder
<'_
, I
>,
34 _environment
: &Environment
<I
>,
36 if self.is_positive() {
37 let binders
= self.binders
.clone();
45 builder
.push_clause(trait_ref
, where_clauses
);
52 impl<I
: Interner
> ToProgramClauses
<I
> for AssociatedTyValue
<I
> {
53 /// Given the following trait:
57 /// type IntoIter<'a>: 'a;
61 /// Then for the following impl:
63 /// impl<T> Iterable for Vec<T> where T: Clone {
64 /// type IntoIter<'a> = Iter<'a, T>;
71 /// -- Rule Normalize-From-Impl
73 /// Normalize(<Vec<T> as Iterable>::IntoIter<'a> -> Iter<'a, T>>) :-
74 /// Implemented(T: Clone), // (1)
75 /// Implemented(Iter<'a, T>: 'a). // (2)
78 fn to_program_clauses(
80 builder
: &mut ClauseBuilder
<'_
, I
>,
81 _environment
: &Environment
<I
>,
83 let impl_datum
= builder
.db
.impl_datum(self.impl_id
);
84 let associated_ty
= builder
.db
.associated_ty_data(self.associated_ty_id
);
86 builder
.push_binders(self.value
.clone(), |builder
, assoc_ty_value
| {
87 let all_parameters
= builder
.placeholders_in_scope().to_vec();
89 // Get the projection for this associated type:
91 // * `impl_params`: `[!T]`
92 // * `projection`: `<Vec<!T> as Iterable>::Iter<'!a>`
93 let (impl_params
, projection
) = builder
95 .impl_parameters_and_projection_from_associated_ty_value(&all_parameters
, self);
97 // Assemble the full list of conditions for projection to be valid.
98 // This comes in two parts, marked as (1) and (2) in doc above:
100 // 1. require that the where clauses from the impl apply
101 let interner
= builder
.db
.interner();
102 let impl_where_clauses
= impl_datum
104 .map_ref(|b
| &b
.where_clauses
)
106 .map(|wc
| wc
.cloned().substitute(interner
, impl_params
));
108 // 2. any where-clauses from the `type` declaration in the trait: the
109 // parameters must be substituted with those of the impl
110 let assoc_ty_where_clauses
= associated_ty
112 .map_ref(|b
| &b
.where_clauses
)
114 .map(|wc
| wc
.cloned().substitute(interner
, &projection
.substitution
));
116 // Create the final program clause:
119 // -- Rule Normalize-From-Impl
121 // Normalize(<Vec<T> as Iterable>::IntoIter<'a> -> Iter<'a, T>>) :-
122 // Implemented(T: Clone), // (1)
123 // Implemented(Iter<'a, T>: 'a). // (2)
128 alias
: AliasTy
::Projection(projection
.clone()),
129 ty
: assoc_ty_value
.ty
,
131 impl_where_clauses
.chain(assoc_ty_where_clauses
),
137 impl<I
: Interner
> ToProgramClauses
<I
> for OpaqueTyDatum
<I
> {
138 /// Given `opaque type T<U>: A + B = HiddenTy where U: C;`, we generate:
141 /// AliasEq(T<U> = HiddenTy) :- Reveal.
142 /// AliasEq(T<U> = !T<U>).
143 /// WF(T<U>) :- WF(U: C).
144 /// Implemented(!T<U>: A).
145 /// Implemented(!T<U>: B).
147 /// where `!T<..>` is the placeholder for the unnormalized type `T<..>`.
148 #[instrument(level = "debug", skip(builder))]
149 fn to_program_clauses(
151 builder
: &mut ClauseBuilder
<'_
, I
>,
152 _environment
: &Environment
<I
>,
154 builder
.push_binders(self.bound
.clone(), |builder
, opaque_ty_bound
| {
155 let interner
= builder
.interner();
156 let substitution
= builder
.substitution_in_scope();
157 let alias
= AliasTy
::Opaque(OpaqueTy
{
158 opaque_ty_id
: self.opaque_ty_id
,
159 substitution
: substitution
.clone(),
162 let alias_placeholder_ty
=
163 TyKind
::OpaqueType(self.opaque_ty_id
, substitution
).intern(interner
);
165 // AliasEq(T<..> = HiddenTy) :- Reveal.
169 alias
: alias
.clone(),
170 ty
: builder
.db
.hidden_opaque_type(self.opaque_ty_id
),
174 iter
::once(DomainGoal
::Reveal
),
177 // AliasEq(T<..> = !T<..>).
178 builder
.push_fact(DomainGoal
::Holds(
181 ty
: alias_placeholder_ty
.clone(),
186 // WF(!T<..>) :- WF(WC).
187 builder
.push_binders(opaque_ty_bound
.where_clauses
, |builder
, where_clauses
| {
189 WellFormed
::Ty(alias_placeholder_ty
.clone()),
192 .map(|wc
| wc
.into_well_formed_goal(interner
)),
196 let substitution
= Substitution
::from1(interner
, alias_placeholder_ty
);
197 for bound
in opaque_ty_bound
.bounds
{
198 let bound_with_placeholder_ty
= bound
.substitute(interner
, &substitution
);
199 builder
.push_binders(bound_with_placeholder_ty
, |builder
, bound
| match &bound
{
200 // For the implemented traits, we need to elaborate super traits and add where clauses from the trait
201 WhereClause
::Implemented(trait_ref
) => {
202 super::super_traits
::push_trait_super_clauses(
208 // FIXME: Associated item bindings are just taken as facts (?)
209 WhereClause
::AliasEq(_
) => builder
.push_fact(bound
),
210 WhereClause
::LifetimeOutlives(..) => {}
211 WhereClause
::TypeOutlives(..) => {}
218 /// Generates the "well-formed" program clauses for an applicative type
219 /// with the name `type_name`. For example, given a struct definition:
222 /// struct Foo<T: Eq> { }
225 /// we would generate the clause:
229 /// WF(Foo<T>) :- WF(T: Eq).
234 /// - builder -- the clause builder. We assume all the generic types from `Foo` are in scope
235 /// - type_name -- in our example above, the name `Foo`
236 /// - where_clauses -- the list of where clauses declared on the type (`T: Eq`, in our example)
237 fn well_formed_program_clauses
<'a
, I
, Wc
>(
238 builder
: &'a
mut ClauseBuilder
<'_
, I
>,
243 Wc
: Iterator
<Item
= &'a QuantifiedWhereClause
<I
>>,
245 let interner
= builder
.interner();
250 .map(|qwc
| qwc
.into_well_formed_goal(interner
)),
254 /// Generates the "fully visible" program clauses for an applicative type
255 /// with the name `type_name`. For example, given a struct definition:
258 /// struct Foo<T: Eq> { }
261 /// we would generate the clause:
265 /// IsFullyVisible(Foo<T>) :- IsFullyVisible(T).
271 /// - builder -- the clause builder. We assume all the generic types from `Foo` are in scope
272 /// - type_name -- in our example above, the name `Foo`
273 fn fully_visible_program_clauses
<I
>(
274 builder
: &mut ClauseBuilder
<'_
, I
>,
276 subst
: &Substitution
<I
>,
280 let interner
= builder
.interner();
282 DomainGoal
::IsFullyVisible(ty
),
284 .type_parameters(interner
)
285 .map(|typ
| DomainGoal
::IsFullyVisible(typ
).cast
::<Goal
<_
>>(interner
)),
289 /// Generates the "implied bounds" clauses for an applicative
290 /// type with the name `type_name`. For example, if `type_name`
291 /// represents a struct `S` that is declared like:
294 /// struct S<T> where T: Eq { }
297 /// then we would generate the rule:
300 /// FromEnv(T: Eq) :- FromEnv(S<T>)
305 /// - builder -- the clause builder. We assume all the generic types from `S` are in scope.
306 /// - type_name -- in our example above, the name `S`
307 /// - where_clauses -- the list of where clauses declared on the type (`T: Eq`, in our example).
308 fn implied_bounds_program_clauses
<'a
, I
, Wc
>(
309 builder
: &'a
mut ClauseBuilder
<'_
, I
>,
314 Wc
: Iterator
<Item
= &'a QuantifiedWhereClause
<I
>>,
316 let interner
= builder
.interner();
318 for qwc
in where_clauses
{
319 builder
.push_binders(qwc
.clone(), |builder
, wc
| {
320 builder
.push_clause(wc
.into_from_env_goal(interner
), Some(ty
.clone().from_env()));
325 impl<I
: Interner
> ToProgramClauses
<I
> for AdtDatum
<I
> {
326 /// Given the following type definition: `struct Foo<T: Eq> { }`, generate:
329 /// -- Rule WellFormed-Type
331 /// WF(Foo<T>) :- WF(T: Eq).
334 /// -- Rule Implied-Bound-From-Type
336 /// FromEnv(T: Eq) :- FromEnv(Foo<T>).
340 /// IsFullyVisible(Foo<T>) :- IsFullyVisible(T).
344 /// If the type `Foo` is marked `#[upstream]`, we also generate:
347 /// forall<T> { IsUpstream(Foo<T>). }
350 /// Otherwise, if the type `Foo` is not marked `#[upstream]`, we generate:
352 /// forall<T> { IsLocal(Foo<T>). }
355 /// Given an `#[upstream]` type that is also fundamental:
360 /// struct Box<T, U> {}
363 /// We generate the following clauses:
366 /// forall<T, U> { IsLocal(Box<T, U>) :- IsLocal(T). }
367 /// forall<T, U> { IsLocal(Box<T, U>) :- IsLocal(U). }
369 /// forall<T, U> { IsUpstream(Box<T, U>) :- IsUpstream(T), IsUpstream(U). }
371 /// // Generated for both upstream and local fundamental types
372 /// forall<T, U> { DownstreamType(Box<T, U>) :- DownstreamType(T). }
373 /// forall<T, U> { DownstreamType(Box<T, U>) :- DownstreamType(U). }
376 #[instrument(level = "debug", skip(builder))]
377 fn to_program_clauses(
379 builder
: &mut ClauseBuilder
<'_
, I
>,
380 _environment
: &Environment
<I
>,
382 let interner
= builder
.interner();
383 let binders
= self.binders
.map_ref(|b
| &b
.where_clauses
).cloned();
385 builder
.push_binders(binders
, |builder
, where_clauses
| {
386 let self_ty
= TyKind
::Adt(self.id
, builder
.substitution_in_scope()).intern(interner
);
388 well_formed_program_clauses(builder
, self_ty
.clone(), where_clauses
.iter());
390 implied_bounds_program_clauses(builder
, &self_ty
, where_clauses
.iter());
392 fully_visible_program_clauses(
395 &builder
.substitution_in_scope(),
398 // Types that are not marked `#[upstream]` satisfy IsLocal(Ty)
399 if !self.flags
.upstream
{
400 // `IsLocalTy(Ty)` depends *only* on whether the type
401 // is marked #[upstream] and nothing else
402 builder
.push_fact(DomainGoal
::IsLocal(self_ty
.clone()));
403 } else if self.flags
.fundamental
{
404 // If a type is `#[upstream]`, but is also
405 // `#[fundamental]`, it satisfies IsLocal if and only
406 // if its parameters satisfy IsLocal
407 for type_param
in builder
.substitution_in_scope().type_parameters(interner
) {
409 DomainGoal
::IsLocal(self_ty
.clone()),
410 Some(DomainGoal
::IsLocal(type_param
)),
414 DomainGoal
::IsUpstream(self_ty
.clone()),
416 .substitution_in_scope()
417 .type_parameters(interner
)
418 .map(|type_param
| DomainGoal
::IsUpstream(type_param
)),
421 // The type is just upstream and not fundamental
422 builder
.push_fact(DomainGoal
::IsUpstream(self_ty
.clone()));
425 if self.flags
.fundamental
{
428 .substitution_in_scope()
429 .type_parameters(interner
)
432 "Only fundamental types with type parameters are supported"
434 for type_param
in builder
.substitution_in_scope().type_parameters(interner
) {
436 DomainGoal
::DownstreamType(self_ty
.clone()),
437 Some(DomainGoal
::DownstreamType(type_param
)),
445 impl<I
: Interner
> ToProgramClauses
<I
> for FnDefDatum
<I
> {
446 /// Given the following function definition: `fn bar<T>() where T: Eq`, generate:
449 /// -- Rule WellFormed-Type
451 /// WF(bar<T>) :- WF(T: Eq)
454 /// -- Rule Implied-Bound-From-Type
456 /// FromEnv(T: Eq) :- FromEnv(bar<T>).
460 /// IsFullyVisible(bar<T>) :- IsFullyVisible(T).
463 #[instrument(level = "debug", skip(builder))]
464 fn to_program_clauses(
466 builder
: &mut ClauseBuilder
<'_
, I
>,
467 _environment
: &Environment
<I
>,
469 let interner
= builder
.interner();
470 let binders
= self.binders
.map_ref(|b
| &b
.where_clauses
).cloned();
472 builder
.push_binders(binders
, |builder
, where_clauses
| {
473 let ty
= TyKind
::FnDef(self.id
, builder
.substitution_in_scope()).intern(interner
);
475 well_formed_program_clauses(builder
, ty
.clone(), where_clauses
.iter());
477 implied_bounds_program_clauses(builder
, &ty
, where_clauses
.iter());
479 fully_visible_program_clauses(builder
, ty
, &builder
.substitution_in_scope());
484 impl<I
: Interner
> ToProgramClauses
<I
> for TraitDatum
<I
> {
485 /// Given the following trait declaration: `trait Ord<T> where Self: Eq<T> { ... }`, generate:
488 /// -- Rule WellFormed-TraitRef
489 /// forall<Self, T> {
490 /// WF(Self: Ord<T>) :- Implemented(Self: Ord<T>), WF(Self: Eq<T>).
494 /// and the reverse rules:
497 /// -- Rule Implemented-From-Env
498 /// forall<Self, T> {
499 /// (Self: Ord<T>) :- FromEnv(Self: Ord<T>).
502 /// -- Rule Implied-Bound-From-Trait
503 /// forall<Self, T> {
504 /// FromEnv(Self: Eq<T>) :- FromEnv(Self: Ord<T>).
508 /// As specified in the orphan rules, if a trait is not marked `#[upstream]`, the current crate
509 /// can implement it for any type. To represent that, we generate:
512 /// // `Ord<T>` would not be `#[upstream]` when compiling `std`
513 /// forall<Self, T> { LocalImplAllowed(Self: Ord<T>). }
516 /// For traits that are `#[upstream]` (i.e. not in the current crate), the orphan rules dictate
517 /// that impls are allowed as long as at least one type parameter is local and each type
518 /// prior to that is fully visible. That means that each type prior to the first local
519 /// type cannot contain any of the type parameters of the impl.
521 /// This rule is fairly complex, so we expand it and generate a program clause for each
522 /// possible case. This is represented as follows:
525 /// // for `#[upstream] trait Foo<T, U, V> where Self: Eq<T> { ... }`
526 /// forall<Self, T, U, V> {
527 /// LocalImplAllowed(Self: Foo<T, U, V>) :- IsLocal(Self).
530 /// forall<Self, T, U, V> {
531 /// LocalImplAllowed(Self: Foo<T, U, V>) :-
532 /// IsFullyVisible(Self),
536 /// forall<Self, T, U, V> {
537 /// LocalImplAllowed(Self: Foo<T, U, V>) :-
538 /// IsFullyVisible(Self),
539 /// IsFullyVisible(T),
543 /// forall<Self, T, U, V> {
544 /// LocalImplAllowed(Self: Foo<T, U, V>) :-
545 /// IsFullyVisible(Self),
546 /// IsFullyVisible(T),
547 /// IsFullyVisible(U),
552 /// The overlap check uses compatible { ... } mode to ensure that it accounts for impls that
553 /// may exist in some other *compatible* world. For every upstream trait, we add a rule to
554 /// account for the fact that upstream crates are able to compatibly add impls of upstream
555 /// traits for upstream types.
558 /// // For `#[upstream] trait Foo<T, U, V> where Self: Eq<T> { ... }`
559 /// forall<Self, T, U, V> {
560 /// Implemented(Self: Foo<T, U, V>) :-
561 /// Implemented(Self: Eq<T>), // where clauses
562 /// Compatible, // compatible modality
563 /// IsUpstream(Self),
567 /// CannotProve. // returns ambiguous
571 /// In certain situations, this is too restrictive. Consider the following code:
574 /// /* In crate std */
578 /// /* In crate bar (depends on std) */
580 /// impl Bar for str { }
581 /// impl<T> Bar for T where T: Sized { }
584 /// Here, because of the rules we've defined, these two impls overlap. The std crate is
585 /// upstream to bar, and thus it is allowed to compatibly implement Sized for str. If str
586 /// can implement Sized in a compatible future, these two impls definitely overlap since the
587 /// second impl covers all types that implement Sized.
589 /// The solution we've got right now is to mark Sized as "fundamental" when it is defined.
590 /// This signals to the Rust compiler that it can rely on the fact that str does not
591 /// implement Sized in all contexts. A consequence of this is that we can no longer add an
592 /// implementation of Sized compatibly for str. This is the trade off you make when defining
593 /// a fundamental trait.
595 /// To implement fundamental traits, we simply just do not add the rule above that allows
596 /// upstream types to implement upstream traits. Fundamental traits are not allowed to
597 /// compatibly do that.
598 fn to_program_clauses(&self, builder
: &mut ClauseBuilder
<'_
, I
>, environment
: &Environment
<I
>) {
599 let interner
= builder
.interner();
600 let binders
= self.binders
.map_ref(|b
| &b
.where_clauses
).cloned();
601 builder
.push_binders(binders
, |builder
, where_clauses
| {
602 let trait_ref
= chalk_ir
::TraitRef
{
604 substitution
: builder
.substitution_in_scope(),
608 trait_ref
.clone().well_formed(),
612 .map(|qwc
| qwc
.into_well_formed_goal(interner
))
613 .casted
::<Goal
<_
>>(interner
)
614 .chain(Some(trait_ref
.clone().cast(interner
))),
617 // The number of parameters will always be at least 1
618 // because of the Self parameter that is automatically
619 // added to every trait. This is important because
620 // otherwise the added program clauses would not have any
622 let type_parameters
: Vec
<_
> = trait_ref
.type_parameters(interner
).collect();
624 if environment
.has_compatible_clause(interner
) {
625 // Note: even though we do check for a `Compatible` clause here,
626 // we also keep it as a condition for the clauses below, purely
627 // for logical consistency. But really, it's not needed and could be
630 // Drop trait can't have downstream implementation because it can only
631 // be implemented with the same genericity as the struct definition,
632 // i.e. Drop implementation for `struct S<T: Eq> {}` is forced to be
633 // `impl Drop<T: Eq> for S<T> { ... }`. That means that orphan rules
634 // prevent Drop from being implemented in downstream crates.
635 if self.well_known
!= Some(WellKnownTrait
::Drop
) {
636 // Add all cases for potential downstream impls that could exist
637 for i
in 0..type_parameters
.len() {
644 .chain(iter
::once(DomainGoal
::Compatible
.cast(interner
)))
645 .chain((0..i
).map(|j
| {
646 DomainGoal
::IsFullyVisible(type_parameters
[j
].clone())
650 DomainGoal
::DownstreamType(type_parameters
[i
].clone())
653 .chain(iter
::once(GoalData
::CannotProve
.intern(interner
))),
658 // Fundamental traits can be reasoned about negatively without any ambiguity, so no
659 // need for this rule if the trait is fundamental.
660 if !self.flags
.fundamental
{
667 .chain(iter
::once(DomainGoal
::Compatible
.cast(interner
)))
670 .type_parameters(interner
)
671 .map(|ty
| DomainGoal
::IsUpstream(ty
).cast(interner
)),
673 .chain(iter
::once(GoalData
::CannotProve
.intern(interner
))),
679 if !self.flags
.upstream
{
680 // Impls for traits declared locally always pass the impl rules
681 builder
.push_fact(DomainGoal
::LocalImplAllowed(trait_ref
.clone()));
683 // Impls for remote traits must have a local type in the right place
684 for i
in 0..type_parameters
.len() {
686 DomainGoal
::LocalImplAllowed(trait_ref
.clone()),
688 .map(|j
| DomainGoal
::IsFullyVisible(type_parameters
[j
].clone()))
689 .chain(Some(DomainGoal
::IsLocal(type_parameters
[i
].clone()))),
694 // Reverse implied bound rules: given (e.g.) `trait Foo: Bar + Baz`,
695 // we create rules like:
698 // FromEnv(T: Bar) :- FromEnv(T: Foo)
704 // FromEnv(T: Baz) :- FromEnv(T: Foo)
706 for qwc
in where_clauses
{
707 builder
.push_binders(qwc
, |builder
, wc
| {
709 wc
.into_from_env_goal(interner
),
710 Some(trait_ref
.clone().from_env()),
715 // Finally, for every trait `Foo` we make a rule
718 // Implemented(T: Foo) :- FromEnv(T: Foo)
720 builder
.push_clause(trait_ref
.clone(), Some(trait_ref
.from_env()));
725 impl<I
: Interner
> ToProgramClauses
<I
> for AssociatedTyDatum
<I
> {
726 /// For each associated type, we define the "projection
727 /// equality" rules. There are always two; one for a successful normalization,
728 /// and one for the "fallback" notion of equality.
730 /// Given: (here, `'a` and `T` represent zero or more parameters)
734 /// type Assoc<'a, T>: Bounds where WC;
738 /// we generate the 'fallback' rule:
741 /// -- Rule AliasEq-Placeholder
742 /// forall<Self, 'a, T> {
743 /// AliasEq(<Self as Foo>::Assoc<'a, T> = (Foo::Assoc<'a, T>)<Self>).
750 /// -- Rule AliasEq-Normalize
751 /// forall<Self, 'a, T, U> {
752 /// AliasEq(<T as Foo>::Assoc<'a, T> = U) :-
753 /// Normalize(<T as Foo>::Assoc -> U).
757 /// We used to generate an "elaboration" rule like this:
761 /// T: Foo :- exists<U> { AliasEq(<T as Foo>::Assoc = U) }.
765 /// but this caused problems with the recursive solver. In
766 /// particular, whenever normalization is possible, we cannot
767 /// solve that projection uniquely, since we can now elaborate
768 /// `AliasEq` to fallback *or* normalize it. So instead we
769 /// handle this kind of reasoning through the `FromEnv` predicate.
771 /// We also generate rules specific to WF requirements and implied bounds:
774 /// -- Rule WellFormed-AssocTy
775 /// forall<Self, 'a, T> {
776 /// WellFormed((Foo::Assoc)<Self, 'a, T>) :- WellFormed(Self: Foo), WellFormed(WC).
779 /// -- Rule Implied-WC-From-AssocTy
780 /// forall<Self, 'a, T> {
781 /// FromEnv(WC) :- FromEnv((Foo::Assoc)<Self, 'a, T>).
784 /// -- Rule Implied-Bound-From-AssocTy
785 /// forall<Self, 'a, T> {
786 /// FromEnv(<Self as Foo>::Assoc<'a,T>: Bounds) :- FromEnv(Self: Foo), WC.
789 /// -- Rule Implied-Trait-From-AssocTy
790 /// forall<Self,'a, T> {
791 /// FromEnv(Self: Foo) :- FromEnv((Foo::Assoc)<Self, 'a,T>).
794 fn to_program_clauses(
796 builder
: &mut ClauseBuilder
<'_
, I
>,
797 _environment
: &Environment
<I
>,
799 let interner
= builder
.interner();
800 let binders
= self.binders
.clone();
801 builder
.push_binders(
804 AssociatedTyDatumBound
{
808 let substitution
= builder
.substitution_in_scope();
810 let projection
= ProjectionTy
{
811 associated_ty_id
: self.id
,
812 substitution
: substitution
.clone(),
814 let projection_ty
= AliasTy
::Projection(projection
.clone()).intern(interner
);
816 // Retrieve the trait ref embedding the associated type
817 let trait_ref
= builder
.db
.trait_ref_from_projection(&projection
);
819 // Construct an application from the projection. So if we have `<T as Iterator>::Item`,
820 // we would produce `(Iterator::Item)<T>`.
821 let ty
= TyKind
::AssociatedType(self.id
, substitution
).intern(interner
);
823 let projection_eq
= AliasEq
{
824 alias
: AliasTy
::Projection(projection
.clone()),
828 // Fallback rule. The solver uses this to move between the projection
829 // and placeholder type.
832 // AliasEq(<Self as Foo>::Assoc = (Foo::Assoc)<Self>).
834 builder
.push_fact_with_priority(projection_eq
, None
, ClausePriority
::Low
);
836 // Well-formedness of projection type.
839 // WellFormed((Foo::Assoc)<Self>) :- WellFormed(Self: Foo), WellFormed(WC).
842 WellFormed
::Ty(ty
.clone()),
843 iter
::once(WellFormed
::Trait(trait_ref
.clone()).cast
::<Goal
<_
>>(interner
))
848 .map(|qwc
| qwc
.into_well_formed_goal(interner
))
853 // Assuming well-formedness of projection type means we can assume
854 // the trait ref as well. Mostly used in function bodies.
857 // FromEnv(Self: Foo) :- FromEnv((Foo::Assoc)<Self>).
859 builder
.push_clause(FromEnv
::Trait(trait_ref
.clone()), Some(ty
.from_env()));
861 // Reverse rule for where clauses.
864 // FromEnv(WC) :- FromEnv((Foo::Assoc)<Self>).
867 // This is really a family of clauses, one for each where clause.
868 for qwc
in &where_clauses
{
869 builder
.push_binders(qwc
.clone(), |builder
, wc
| {
871 wc
.into_from_env_goal(interner
),
872 Some(FromEnv
::Ty(ty
.clone())),
877 // Reverse rule for implied bounds.
880 // FromEnv(<Self as Foo>::Assoc: Bounds) :- FromEnv(Self: Foo), WC
882 for quantified_bound
in bounds
{
883 builder
.push_binders(quantified_bound
, |builder
, bound
| {
884 for wc
in bound
.into_where_clauses(interner
, projection_ty
.clone()) {
886 wc
.into_from_env_goal(interner
),
888 FromEnv
::Trait(trait_ref
.clone()).cast
::<Goal
<_
>>(interner
),
890 .chain(where_clauses
.iter().cloned().casted(interner
)),
896 // add new type parameter U
897 builder
.push_bound_ty(|builder
, ty
| {
898 // `Normalize(<T as Foo>::Assoc -> U)`
899 let normalize
= Normalize
{
900 alias
: AliasTy
::Projection(projection
.clone()),
904 // `AliasEq(<T as Foo>::Assoc = U)`
905 let projection_eq
= AliasEq
{
906 alias
: AliasTy
::Projection(projection
),
910 // Projection equality rule from above.
913 // AliasEq(<T as Foo>::Assoc = U) :-
914 // Normalize(<T as Foo>::Assoc -> U).
916 builder
.push_clause(projection_eq
, Some(normalize
));