]> git.proxmox.com Git - rustc.git/blame - vendor/chalk-solve/src/clauses/program_clauses.rs
New upstream version 1.46.0~beta.2+dfsg1
[rustc.git] / vendor / chalk-solve / src / clauses / program_clauses.rs
CommitLineData
f9f354fc 1use crate::clauses::builder::ClauseBuilder;
f035d41b 2use crate::rust_ir::*;
f9f354fc 3use crate::split::Split;
f035d41b 4use chalk_ir::cast::{Cast, CastTo, Caster};
f9f354fc
XL
5use chalk_ir::interner::Interner;
6use chalk_ir::*;
f9f354fc 7use std::iter;
f035d41b 8use tracing::instrument;
f9f354fc
XL
9
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.
13pub trait ToProgramClauses<I: Interner> {
14 fn to_program_clauses(&self, builder: &mut ClauseBuilder<'_, I>);
15}
16
17impl<I: Interner> ToProgramClauses<I> for ImplDatum<I> {
18 /// Given `impl<T: Clone> Clone for Vec<T> { ... }`, generate:
19 ///
20 /// ```notrust
21 /// -- Rule Implemented-From-Impl
22 /// forall<T> {
23 /// Implemented(Vec<T>: Clone) :- Implemented(T: Clone).
24 /// }
25 /// ```
26 ///
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
30 /// on its own.
31 fn to_program_clauses(&self, builder: &mut ClauseBuilder<'_, I>) {
32 if self.is_positive() {
33 let binders = self.binders.map_ref(|b| (&b.trait_ref, &b.where_clauses));
34 builder.push_binders(&binders, |builder, (trait_ref, where_clauses)| {
35 builder.push_clause(trait_ref, where_clauses);
36 });
37 }
38 }
39}
40
41impl<I: Interner> ToProgramClauses<I> for AssociatedTyValue<I> {
42 /// Given the following trait:
43 ///
44 /// ```notrust
45 /// trait Iterable {
46 /// type IntoIter<'a>: 'a;
47 /// }
48 /// ```
49 ///
50 /// Then for the following impl:
51 /// ```notrust
52 /// impl<T> Iterable for Vec<T> where T: Clone {
53 /// type IntoIter<'a> = Iter<'a, T>;
54 /// }
55 /// ```
56 ///
57 /// we generate:
58 ///
59 /// ```notrust
60 /// -- Rule Normalize-From-Impl
61 /// forall<'a, T> {
62 /// Normalize(<Vec<T> as Iterable>::IntoIter<'a> -> Iter<'a, T>>) :-
63 /// Implemented(T: Clone), // (1)
64 /// Implemented(Iter<'a, T>: 'a). // (2)
65 /// }
66 /// ```
67 fn to_program_clauses(&self, builder: &mut ClauseBuilder<'_, I>) {
68 let impl_datum = builder.db.impl_datum(self.impl_id);
69 let associated_ty = builder.db.associated_ty_data(self.associated_ty_id);
70
71 builder.push_binders(&self.value, |builder, assoc_ty_value| {
72 let all_parameters = builder.placeholders_in_scope().to_vec();
73
74 // Get the projection for this associated type:
75 //
76 // * `impl_params`: `[!T]`
77 // * `projection`: `<Vec<!T> as Iterable>::Iter<'!a>`
78 let (impl_params, projection) = builder
79 .db
80 .impl_parameters_and_projection_from_associated_ty_value(&all_parameters, self);
81
82 // Assemble the full list of conditions for projection to be valid.
83 // This comes in two parts, marked as (1) and (2) in doc above:
84 //
85 // 1. require that the where clauses from the impl apply
86 let interner = builder.db.interner();
87 let impl_where_clauses = impl_datum
88 .binders
89 .map_ref(|b| &b.where_clauses)
90 .into_iter()
91 .map(|wc| wc.substitute(interner, impl_params));
92
93 // 2. any where-clauses from the `type` declaration in the trait: the
94 // parameters must be substituted with those of the impl
95 let assoc_ty_where_clauses = associated_ty
96 .binders
97 .map_ref(|b| &b.where_clauses)
98 .into_iter()
99 .map(|wc| wc.substitute(interner, &projection.substitution));
100
101 // Create the final program clause:
102 //
103 // ```notrust
104 // -- Rule Normalize-From-Impl
105 // forall<'a, T> {
106 // Normalize(<Vec<T> as Iterable>::IntoIter<'a> -> Iter<'a, T>>) :-
107 // Implemented(T: Clone), // (1)
108 // Implemented(Iter<'a, T>: 'a). // (2)
109 // }
110 // ```
111 builder.push_clause(
112 Normalize {
113 alias: AliasTy::Projection(projection.clone()),
114 ty: assoc_ty_value.ty,
115 },
116 impl_where_clauses.chain(assoc_ty_where_clauses),
117 );
118 });
119 }
120}
121
122impl<I: Interner> ToProgramClauses<I> for OpaqueTyDatum<I> {
123 /// Given `opaque type T<..>: A + B = HiddenTy;`, we generate:
124 ///
125 /// ```notrust
126 /// AliasEq(T<..> = HiddenTy) :- Reveal.
127 /// AliasEq(T<..> = !T<..>).
128 /// Implemented(!T<..>: A).
129 /// Implemented(!T<..>: B).
f9f354fc
XL
130 /// ```
131 /// where `!T<..>` is the placeholder for the unnormalized type `T<..>`.
f035d41b 132 #[instrument(level = "debug", skip(builder))]
f9f354fc 133 fn to_program_clauses(&self, builder: &mut ClauseBuilder<'_, I>) {
f9f354fc
XL
134 builder.push_binders(&self.bound, |builder, opaque_ty_bound| {
135 let interner = builder.interner();
136 let substitution = builder.substitution_in_scope();
137 let alias = AliasTy::Opaque(OpaqueTy {
138 opaque_ty_id: self.opaque_ty_id,
139 substitution: substitution.clone(),
140 });
141
142 let alias_placeholder_ty = Ty::new(
143 interner,
144 ApplicationTy {
f035d41b 145 name: self.opaque_ty_id.cast(interner),
f9f354fc
XL
146 substitution,
147 },
148 );
149
150 // AliasEq(T<..> = HiddenTy) :- Reveal.
151 builder.push_clause(
152 DomainGoal::Holds(
153 AliasEq {
154 alias: alias.clone(),
f035d41b 155 ty: builder.db.hidden_opaque_type(self.opaque_ty_id),
f9f354fc
XL
156 }
157 .cast(interner),
158 ),
159 iter::once(DomainGoal::Reveal(())),
160 );
161
162 // AliasEq(T<..> = !T<..>).
163 builder.push_fact(DomainGoal::Holds(
164 AliasEq {
165 alias: alias.clone(),
166 ty: alias_placeholder_ty.clone(),
167 }
168 .cast(interner),
169 ));
170
171 let substitution = Substitution::from1(interner, alias_placeholder_ty.clone());
f035d41b 172 for bound in opaque_ty_bound.bounds {
f9f354fc
XL
173 // Implemented(!T<..>: Bound).
174 let bound_with_placeholder_ty = bound.substitute(interner, &substitution);
175 builder.push_binders(&bound_with_placeholder_ty, |builder, bound| {
176 builder.push_fact(bound);
177 });
178 }
179 });
180 }
181}
182
f035d41b
XL
183fn application_ty<I: Interner>(
184 builder: &mut ClauseBuilder<'_, I>,
185 type_name: impl CastTo<TypeName<I>>,
186) -> ApplicationTy<I> {
187 let interner = builder.interner();
188 ApplicationTy {
189 name: type_name.cast(interner),
190 substitution: builder.substitution_in_scope(),
191 }
192}
193
194/// Generates the "well-formed" program clauses for an applicative type
195/// with the name `type_name`. For example, given a struct definition:
196///
197/// ```ignore
198/// struct Foo<T: Eq> { }
199/// ```
200///
201/// we would generate the clause:
202///
203/// ```notrust
204/// forall<T> {
205/// WF(Foo<T>) :- WF(T: Eq).
206/// }
207/// ```
208///
209/// # Parameters
210/// - builder -- the clause builder. We assume all the generic types from `Foo` are in scope
211/// - type_name -- in our example above, the name `Foo`
212/// - where_clauses -- the list of where clauses declared on the type (`T: Eq`, in our example)
213fn well_formed_program_clauses<'a, I, Wc>(
214 builder: &'a mut ClauseBuilder<'_, I>,
215 type_name: impl CastTo<TypeName<I>>,
216 where_clauses: Wc,
217) where
218 I: Interner,
219 Wc: Iterator<Item = &'a QuantifiedWhereClause<I>>,
220{
221 let interner = builder.interner();
222 let appl_ty = application_ty(builder, type_name);
223 let ty = appl_ty.clone().intern(interner);
224 builder.push_clause(
225 WellFormed::Ty(ty.clone()),
226 where_clauses
227 .cloned()
228 .map(|qwc| qwc.into_well_formed_goal(interner)),
229 );
230}
231
232/// Generates the "fully visible" program clauses for an applicative type
233/// with the name `type_name`. For example, given a struct definition:
234///
235/// ```ignore
236/// struct Foo<T: Eq> { }
237/// ```
238///
239/// we would generate the clause:
240///
241/// ```notrust
242/// forall<T> {
243/// IsFullyVisible(Foo<T>) :- IsFullyVisible(T).
244/// }
245/// ```
246///
247/// # Parameters
248///
249/// - builder -- the clause builder. We assume all the generic types from `Foo` are in scope
250/// - type_name -- in our example above, the name `Foo`
251fn fully_visible_program_clauses<'a, I>(
252 builder: &'a mut ClauseBuilder<'_, I>,
253 type_name: impl CastTo<TypeName<I>>,
254) where
255 I: Interner,
256{
257 let interner = builder.interner();
258 let appl_ty = application_ty(builder, type_name);
259 let ty = appl_ty.clone().intern(interner);
260 builder.push_clause(
261 DomainGoal::IsFullyVisible(ty.clone()),
262 appl_ty
263 .type_parameters(interner)
264 .map(|typ| DomainGoal::IsFullyVisible(typ).cast::<Goal<_>>(interner)),
265 );
266}
267
268/// Generates the "implied bounds" clauses for an applicative
269/// type with the name `type_name`. For example, if `type_name`
270/// represents a struct `S` that is declared like:
271///
272/// ```ignore
273/// struct S<T> where T: Eq { }
274/// ```
275///
276/// then we would generate the rule:
277///
278/// ```notrust
279/// FromEnv(T: Eq) :- FromEnv(S<T>)
280/// ```
281///
282/// # Parameters
283///
284/// - builder -- the clause builder. We assume all the generic types from `S` are in scope.
285/// - type_name -- in our example above, the name `S`
286/// - where_clauses -- the list of where clauses declared on the type (`T: Eq`, in our example).
287fn implied_bounds_program_clauses<'a, I, Wc>(
288 builder: &'a mut ClauseBuilder<'_, I>,
289 type_name: impl CastTo<TypeName<I>>,
290 where_clauses: Wc,
291) where
292 I: Interner,
293 Wc: Iterator<Item = &'a QuantifiedWhereClause<I>>,
294{
295 let interner = builder.interner();
296 let appl_ty = application_ty(builder, type_name);
297 let ty = appl_ty.clone().intern(interner);
298
299 for qwc in where_clauses {
300 builder.push_binders(&qwc, |builder, wc| {
301 builder.push_clause(wc.into_from_env_goal(interner), Some(ty.clone().from_env()));
302 });
303 }
304}
305
306impl<I: Interner> ToProgramClauses<I> for AdtDatum<I> {
f9f354fc
XL
307 /// Given the following type definition: `struct Foo<T: Eq> { }`, generate:
308 ///
309 /// ```notrust
310 /// -- Rule WellFormed-Type
311 /// forall<T> {
312 /// WF(Foo<T>) :- WF(T: Eq).
313 /// }
314 ///
315 /// -- Rule Implied-Bound-From-Type
316 /// forall<T> {
317 /// FromEnv(T: Eq) :- FromEnv(Foo<T>).
318 /// }
319 ///
320 /// forall<T> {
321 /// IsFullyVisible(Foo<T>) :- IsFullyVisible(T).
322 /// }
323 /// ```
324 ///
325 /// If the type `Foo` is marked `#[upstream]`, we also generate:
326 ///
327 /// ```notrust
328 /// forall<T> { IsUpstream(Foo<T>). }
329 /// ```
330 ///
331 /// Otherwise, if the type `Foo` is not marked `#[upstream]`, we generate:
332 /// ```notrust
333 /// forall<T> { IsLocal(Foo<T>). }
334 /// ```
335 ///
336 /// Given an `#[upstream]` type that is also fundamental:
337 ///
338 /// ```notrust
339 /// #[upstream]
340 /// #[fundamental]
341 /// struct Box<T> {}
342 /// ```
343 ///
344 /// We generate the following clauses:
345 ///
346 /// ```notrust
347 /// forall<T> { IsLocal(Box<T>) :- IsLocal(T). }
348 ///
349 /// forall<T> { IsUpstream(Box<T>) :- IsUpstream(T). }
350 ///
351 /// // Generated for both upstream and local fundamental types
352 /// forall<T> { DownstreamType(Box<T>) :- DownstreamType(T). }
353 /// ```
354 ///
f035d41b 355 #[instrument(level = "debug", skip(builder))]
f9f354fc 356 fn to_program_clauses(&self, builder: &mut ClauseBuilder<'_, I>) {
f9f354fc
XL
357 let interner = builder.interner();
358 let binders = self.binders.map_ref(|b| &b.where_clauses);
f035d41b
XL
359 let id = self.id;
360
f9f354fc 361 builder.push_binders(&binders, |builder, where_clauses| {
f035d41b 362 well_formed_program_clauses(builder, id, where_clauses.iter());
f9f354fc 363
f035d41b 364 implied_bounds_program_clauses(builder, id, where_clauses.iter());
f9f354fc 365
f035d41b
XL
366 fully_visible_program_clauses(builder, id);
367
368 let self_appl_ty = application_ty(builder, id);
369 let self_ty = self_appl_ty.clone().intern(interner);
f9f354fc
XL
370
371 // Fundamental types often have rules in the form of:
372 // Goal(FundamentalType<T>) :- Goal(T)
373 // This macro makes creating that kind of clause easy
374 macro_rules! fundamental_rule {
375 ($goal:ident) => {
376 // Fundamental types must always have at least one
377 // type parameter for this rule to make any
378 // sense. We currently do not have have any
379 // fundamental types with more than one type
380 // parameter, nor do we know what the behaviour
381 // for that should be. Thus, we are asserting here
382 // that there is only a single type parameter
383 // until the day when someone makes a decision
384 // about how that should behave.
385 assert_eq!(
386 self_appl_ty.len_type_parameters(interner),
387 1,
388 "Only fundamental types with a single parameter are supported"
389 );
390
391 builder.push_clause(
392 DomainGoal::$goal(self_ty.clone()),
393 Some(DomainGoal::$goal(
394 // This unwrap is safe because we asserted
395 // above for the presence of a type
396 // parameter
397 self_appl_ty.first_type_parameter(interner).unwrap(),
398 )),
399 );
400 };
401 }
402
403 // Types that are not marked `#[upstream]` satisfy IsLocal(TypeName)
404 if !self.flags.upstream {
405 // `IsLocalTy(Ty)` depends *only* on whether the type
406 // is marked #[upstream] and nothing else
407 builder.push_fact(DomainGoal::IsLocal(self_ty.clone()));
408 } else if self.flags.fundamental {
409 // If a type is `#[upstream]`, but is also
410 // `#[fundamental]`, it satisfies IsLocal if and only
411 // if its parameters satisfy IsLocal
412 fundamental_rule!(IsLocal);
413 fundamental_rule!(IsUpstream);
414 } else {
415 // The type is just upstream and not fundamental
416 builder.push_fact(DomainGoal::IsUpstream(self_ty.clone()));
417 }
418
419 if self.flags.fundamental {
420 fundamental_rule!(DownstreamType);
421 }
f035d41b
XL
422 });
423 }
424}
f9f354fc 425
f035d41b
XL
426impl<I: Interner> ToProgramClauses<I> for FnDefDatum<I> {
427 /// Given the following function definition: `fn bar<T>() where T: Eq`, generate:
428 ///
429 /// ```notrust
430 /// -- Rule WellFormed-Type
431 /// forall<T> {
432 /// WF(bar<T>) :- WF(T: Eq)
433 /// }
434 ///
435 /// -- Rule Implied-Bound-From-Type
436 /// forall<T> {
437 /// FromEnv(T: Eq) :- FromEnv(bar<T>).
438 /// }
439 ///
440 /// forall<T> {
441 /// IsFullyVisible(bar<T>) :- IsFullyVisible(T).
442 /// }
443 /// ```
444 #[instrument(level = "debug", skip(builder))]
445 fn to_program_clauses(&self, builder: &mut ClauseBuilder<'_, I>) {
446 let binders = self.binders.map_ref(|b| &b.where_clauses);
447 let id = self.id;
448
449 builder.push_binders(&binders, |builder, where_clauses| {
450 well_formed_program_clauses(builder, id, where_clauses.iter());
451
452 implied_bounds_program_clauses(builder, id, where_clauses.iter());
453
454 fully_visible_program_clauses(builder, id);
f9f354fc
XL
455 });
456 }
457}
458
459impl<I: Interner> ToProgramClauses<I> for TraitDatum<I> {
460 /// Given the following trait declaration: `trait Ord<T> where Self: Eq<T> { ... }`, generate:
461 ///
462 /// ```notrust
463 /// -- Rule WellFormed-TraitRef
464 /// forall<Self, T> {
465 /// WF(Self: Ord<T>) :- Implemented(Self: Ord<T>), WF(Self: Eq<T>).
466 /// }
467 /// ```
468 ///
469 /// and the reverse rules:
470 ///
471 /// ```notrust
472 /// -- Rule Implemented-From-Env
473 /// forall<Self, T> {
474 /// (Self: Ord<T>) :- FromEnv(Self: Ord<T>).
475 /// }
476 ///
477 /// -- Rule Implied-Bound-From-Trait
478 /// forall<Self, T> {
479 /// FromEnv(Self: Eq<T>) :- FromEnv(Self: Ord<T>).
480 /// }
481 /// ```
482 ///
483 /// As specified in the orphan rules, if a trait is not marked `#[upstream]`, the current crate
484 /// can implement it for any type. To represent that, we generate:
485 ///
486 /// ```notrust
487 /// // `Ord<T>` would not be `#[upstream]` when compiling `std`
488 /// forall<Self, T> { LocalImplAllowed(Self: Ord<T>). }
489 /// ```
490 ///
491 /// For traits that are `#[upstream]` (i.e. not in the current crate), the orphan rules dictate
492 /// that impls are allowed as long as at least one type parameter is local and each type
493 /// prior to that is fully visible. That means that each type prior to the first local
494 /// type cannot contain any of the type parameters of the impl.
495 ///
496 /// This rule is fairly complex, so we expand it and generate a program clause for each
497 /// possible case. This is represented as follows:
498 ///
499 /// ```notrust
500 /// // for `#[upstream] trait Foo<T, U, V> where Self: Eq<T> { ... }`
501 /// forall<Self, T, U, V> {
502 /// LocalImplAllowed(Self: Foo<T, U, V>) :- IsLocal(Self).
503 /// }
504 ///
505 /// forall<Self, T, U, V> {
506 /// LocalImplAllowed(Self: Foo<T, U, V>) :-
507 /// IsFullyVisible(Self),
508 /// IsLocal(T).
509 /// }
510 ///
511 /// forall<Self, T, U, V> {
512 /// LocalImplAllowed(Self: Foo<T, U, V>) :-
513 /// IsFullyVisible(Self),
514 /// IsFullyVisible(T),
515 /// IsLocal(U).
516 /// }
517 ///
518 /// forall<Self, T, U, V> {
519 /// LocalImplAllowed(Self: Foo<T, U, V>) :-
520 /// IsFullyVisible(Self),
521 /// IsFullyVisible(T),
522 /// IsFullyVisible(U),
523 /// IsLocal(V).
524 /// }
525 /// ```
526 ///
527 /// The overlap check uses compatible { ... } mode to ensure that it accounts for impls that
528 /// may exist in some other *compatible* world. For every upstream trait, we add a rule to
529 /// account for the fact that upstream crates are able to compatibly add impls of upstream
530 /// traits for upstream types.
531 ///
532 /// ```notrust
533 /// // For `#[upstream] trait Foo<T, U, V> where Self: Eq<T> { ... }`
534 /// forall<Self, T, U, V> {
535 /// Implemented(Self: Foo<T, U, V>) :-
536 /// Implemented(Self: Eq<T>), // where clauses
537 /// Compatible, // compatible modality
538 /// IsUpstream(Self),
539 /// IsUpstream(T),
540 /// IsUpstream(U),
541 /// IsUpstream(V),
542 /// CannotProve. // returns ambiguous
543 /// }
544 /// ```
545 ///
546 /// In certain situations, this is too restrictive. Consider the following code:
547 ///
548 /// ```notrust
549 /// /* In crate std */
550 /// trait Sized { }
551 /// struct str { }
552 ///
553 /// /* In crate bar (depends on std) */
554 /// trait Bar { }
555 /// impl Bar for str { }
556 /// impl<T> Bar for T where T: Sized { }
557 /// ```
558 ///
559 /// Here, because of the rules we've defined, these two impls overlap. The std crate is
560 /// upstream to bar, and thus it is allowed to compatibly implement Sized for str. If str
561 /// can implement Sized in a compatible future, these two impls definitely overlap since the
562 /// second impl covers all types that implement Sized.
563 ///
564 /// The solution we've got right now is to mark Sized as "fundamental" when it is defined.
565 /// This signals to the Rust compiler that it can rely on the fact that str does not
566 /// implement Sized in all contexts. A consequence of this is that we can no longer add an
567 /// implementation of Sized compatibly for str. This is the trade off you make when defining
568 /// a fundamental trait.
569 ///
570 /// To implement fundamental traits, we simply just do not add the rule above that allows
571 /// upstream types to implement upstream traits. Fundamental traits are not allowed to
572 /// compatibly do that.
573 fn to_program_clauses(&self, builder: &mut ClauseBuilder<'_, I>) {
574 let interner = builder.interner();
575 let binders = self.binders.map_ref(|b| &b.where_clauses);
576 builder.push_binders(&binders, |builder, where_clauses| {
577 let trait_ref = chalk_ir::TraitRef {
578 trait_id: self.id,
579 substitution: builder.substitution_in_scope(),
580 };
581
582 builder.push_clause(
583 trait_ref.clone().well_formed(),
584 where_clauses
585 .iter()
586 .cloned()
587 .map(|qwc| qwc.into_well_formed_goal(interner))
588 .casted::<Goal<_>>(interner)
589 .chain(Some(trait_ref.clone().cast(interner))),
590 );
591
592 // The number of parameters will always be at least 1
593 // because of the Self parameter that is automatically
594 // added to every trait. This is important because
595 // otherwise the added program clauses would not have any
596 // conditions.
597 let type_parameters: Vec<_> = trait_ref.type_parameters(interner).collect();
598
599 // Drop trait can't have downstream implementation because it can only
600 // be implemented with the same genericity as the struct definition,
601 // i.e. Drop implementation for `struct S<T: Eq> {}` is forced to be
602 // `impl Drop<T: Eq> for S<T> { ... }`. That means that orphan rules
603 // prevent Drop from being implemented in downstream crates.
f035d41b 604 if self.well_known != Some(WellKnownTrait::Drop) {
f9f354fc
XL
605 // Add all cases for potential downstream impls that could exist
606 for i in 0..type_parameters.len() {
607 builder.push_clause(
608 trait_ref.clone(),
609 where_clauses
610 .iter()
611 .cloned()
612 .casted(interner)
613 .chain(iter::once(DomainGoal::Compatible(()).cast(interner)))
614 .chain((0..i).map(|j| {
615 DomainGoal::IsFullyVisible(type_parameters[j].clone())
616 .cast(interner)
617 }))
618 .chain(iter::once(
619 DomainGoal::DownstreamType(type_parameters[i].clone())
620 .cast(interner),
621 ))
622 .chain(iter::once(GoalData::CannotProve(()).intern(interner))),
623 );
624 }
625 }
626
627 // Orphan rules:
628 if !self.flags.upstream {
629 // Impls for traits declared locally always pass the impl rules
630 builder.push_fact(DomainGoal::LocalImplAllowed(trait_ref.clone()));
631 } else {
632 // Impls for remote traits must have a local type in the right place
633 for i in 0..type_parameters.len() {
634 builder.push_clause(
635 DomainGoal::LocalImplAllowed(trait_ref.clone()),
636 (0..i)
637 .map(|j| DomainGoal::IsFullyVisible(type_parameters[j].clone()))
638 .chain(Some(DomainGoal::IsLocal(type_parameters[i].clone()))),
639 );
640 }
641 }
642
643 // Fundamental traits can be reasoned about negatively without any ambiguity, so no
644 // need for this rule if the trait is fundamental.
645 if !self.flags.fundamental {
646 builder.push_clause(
647 trait_ref.clone(),
648 where_clauses
649 .iter()
650 .cloned()
651 .casted(interner)
652 .chain(iter::once(DomainGoal::Compatible(()).cast(interner)))
653 .chain(
654 trait_ref
655 .type_parameters(interner)
656 .map(|ty| DomainGoal::IsUpstream(ty).cast(interner)),
657 )
658 .chain(iter::once(GoalData::CannotProve(()).intern(interner))),
659 );
660 }
661
662 // Reverse implied bound rules: given (e.g.) `trait Foo: Bar + Baz`,
663 // we create rules like:
664 //
665 // ```
666 // FromEnv(T: Bar) :- FromEnv(T: Foo)
667 // ```
668 //
669 // and
670 //
671 // ```
672 // FromEnv(T: Baz) :- FromEnv(T: Foo)
673 // ```
674 for qwc in &where_clauses {
675 builder.push_binders(qwc, |builder, wc| {
676 builder.push_clause(
677 wc.into_from_env_goal(interner),
678 Some(trait_ref.clone().from_env()),
679 );
680 });
681 }
682
683 // Finally, for every trait `Foo` we make a rule
684 //
685 // ```
686 // Implemented(T: Foo) :- FromEnv(T: Foo)
687 // ```
688 builder.push_clause(trait_ref.clone(), Some(trait_ref.clone().from_env()));
689 });
690 }
691}
692
693impl<I: Interner> ToProgramClauses<I> for AssociatedTyDatum<I> {
694 /// For each associated type, we define the "projection
695 /// equality" rules. There are always two; one for a successful normalization,
696 /// and one for the "fallback" notion of equality.
697 ///
698 /// Given: (here, `'a` and `T` represent zero or more parameters)
699 ///
700 /// ```notrust
701 /// trait Foo {
702 /// type Assoc<'a, T>: Bounds where WC;
703 /// }
704 /// ```
705 ///
706 /// we generate the 'fallback' rule:
707 ///
708 /// ```notrust
709 /// -- Rule AliasEq-Placeholder
710 /// forall<Self, 'a, T> {
711 /// AliasEq(<Self as Foo>::Assoc<'a, T> = (Foo::Assoc<'a, T>)<Self>).
712 /// }
713 /// ```
714 ///
715 /// and
716 ///
717 /// ```notrust
718 /// -- Rule AliasEq-Normalize
719 /// forall<Self, 'a, T, U> {
720 /// AliasEq(<T as Foo>::Assoc<'a, T> = U) :-
721 /// Normalize(<T as Foo>::Assoc -> U).
722 /// }
723 /// ```
724 ///
725 /// We used to generate an "elaboration" rule like this:
726 ///
727 /// ```notrust
728 /// forall<T> {
729 /// T: Foo :- exists<U> { AliasEq(<T as Foo>::Assoc = U) }.
730 /// }
731 /// ```
732 ///
733 /// but this caused problems with the recursive solver. In
734 /// particular, whenever normalization is possible, we cannot
735 /// solve that projection uniquely, since we can now elaborate
736 /// `AliasEq` to fallback *or* normalize it. So instead we
737 /// handle this kind of reasoning through the `FromEnv` predicate.
738 ///
739 /// We also generate rules specific to WF requirements and implied bounds:
740 ///
741 /// ```notrust
742 /// -- Rule WellFormed-AssocTy
743 /// forall<Self, 'a, T> {
744 /// WellFormed((Foo::Assoc)<Self, 'a, T>) :- WellFormed(Self: Foo), WellFormed(WC).
745 /// }
746 ///
747 /// -- Rule Implied-WC-From-AssocTy
748 /// forall<Self, 'a, T> {
749 /// FromEnv(WC) :- FromEnv((Foo::Assoc)<Self, 'a, T>).
750 /// }
751 ///
752 /// -- Rule Implied-Bound-From-AssocTy
753 /// forall<Self, 'a, T> {
754 /// FromEnv(<Self as Foo>::Assoc<'a,T>: Bounds) :- FromEnv(Self: Foo), WC.
755 /// }
756 ///
757 /// -- Rule Implied-Trait-From-AssocTy
758 /// forall<Self,'a, T> {
759 /// FromEnv(Self: Foo) :- FromEnv((Foo::Assoc)<Self, 'a,T>).
760 /// }
761 /// ```
762 fn to_program_clauses(&self, builder: &mut ClauseBuilder<'_, I>) {
763 let interner = builder.interner();
764 let binders = self.binders.map_ref(|b| (&b.where_clauses, &b.bounds));
765 builder.push_binders(&binders, |builder, (where_clauses, bounds)| {
766 let substitution = builder.substitution_in_scope();
767
768 let projection = ProjectionTy {
769 associated_ty_id: self.id,
770 substitution: substitution.clone(),
771 };
772 let projection_ty = AliasTy::Projection(projection.clone()).intern(interner);
773
774 // Retrieve the trait ref embedding the associated type
775 let trait_ref = builder.db.trait_ref_from_projection(&projection);
776
777 // Construct an application from the projection. So if we have `<T as Iterator>::Item`,
778 // we would produce `(Iterator::Item)<T>`.
779 let app_ty: Ty<_> = ApplicationTy {
780 name: TypeName::AssociatedType(self.id),
781 substitution,
782 }
783 .intern(interner);
784
785 let projection_eq = AliasEq {
786 alias: AliasTy::Projection(projection.clone()),
787 ty: app_ty.clone(),
788 };
789
790 // Fallback rule. The solver uses this to move between the projection
791 // and placeholder type.
792 //
793 // forall<Self> {
794 // AliasEq(<Self as Foo>::Assoc = (Foo::Assoc)<Self>).
795 // }
796 builder.push_fact_with_priority(projection_eq, ClausePriority::Low);
797
798 // Well-formedness of projection type.
799 //
800 // forall<Self> {
801 // WellFormed((Foo::Assoc)<Self>) :- WellFormed(Self: Foo), WellFormed(WC).
802 // }
803 builder.push_clause(
804 WellFormed::Ty(app_ty.clone()),
805 iter::once(WellFormed::Trait(trait_ref.clone()).cast::<Goal<_>>(interner)).chain(
806 where_clauses
807 .iter()
808 .cloned()
809 .map(|qwc| qwc.into_well_formed_goal(interner))
810 .casted(interner),
811 ),
812 );
813
814 // Assuming well-formedness of projection type means we can assume
815 // the trait ref as well. Mostly used in function bodies.
816 //
817 // forall<Self> {
818 // FromEnv(Self: Foo) :- FromEnv((Foo::Assoc)<Self>).
819 // }
820 builder.push_clause(FromEnv::Trait(trait_ref.clone()), Some(app_ty.from_env()));
821
822 // Reverse rule for where clauses.
823 //
824 // forall<Self> {
825 // FromEnv(WC) :- FromEnv((Foo::Assoc)<Self>).
826 // }
827 //
828 // This is really a family of clauses, one for each where clause.
829 for qwc in &where_clauses {
830 builder.push_binders(qwc, |builder, wc| {
831 builder.push_clause(
832 wc.into_from_env_goal(interner),
833 Some(FromEnv::Ty(app_ty.clone())),
834 );
835 });
836 }
837
838 // Reverse rule for implied bounds.
839 //
840 // forall<Self> {
841 // FromEnv(<Self as Foo>::Assoc: Bounds) :- FromEnv(Self: Foo), WC
842 // }
843 for quantified_bound in &bounds {
844 builder.push_binders(quantified_bound, |builder, bound| {
845 for wc in bound.into_where_clauses(interner, projection_ty.clone()) {
846 builder.push_clause(
847 wc.into_from_env_goal(interner),
848 iter::once(FromEnv::Trait(trait_ref.clone()).cast::<Goal<_>>(interner))
849 .chain(where_clauses.iter().cloned().casted(interner)),
850 );
851 }
852 });
853 }
854
855 // add new type parameter U
856 builder.push_bound_ty(|builder, ty| {
857 // `Normalize(<T as Foo>::Assoc -> U)`
858 let normalize = Normalize {
859 alias: AliasTy::Projection(projection.clone()),
860 ty: ty.clone(),
861 };
862
863 // `AliasEq(<T as Foo>::Assoc = U)`
864 let projection_eq = AliasEq {
865 alias: AliasTy::Projection(projection),
866 ty,
867 };
868
869 // Projection equality rule from above.
870 //
871 // forall<T, U> {
872 // AliasEq(<T as Foo>::Assoc = U) :-
873 // Normalize(<T as Foo>::Assoc -> U).
874 // }
875 builder.push_clause(projection_eq, Some(normalize));
876 });
877 });
878 }
879}