@@ -405,7 +405,7 @@ Notice that we are now also requiring `Implemented(Self: Trait)` for
405405traversing all the implied bounds transitively. This does not change anything
406406when checking whether impls are legal, because since we assume
407407that the where clauses hold inside the impl, we know that the corresponding
408- trait reference do hold. Thanks to this setup, you can see that we indeed
408+ trait reference does hold. Thanks to this setup, you can see that we indeed
409409require to prove the set of all bounds transitively implied by the where
410410clauses.
411411
@@ -462,41 +462,38 @@ are effectively visiting all the transitive implied bounds, and only these.
462462
463463## Implied bounds on types
464464
465- We mainly talked about implied bounds for traits because this was the most
466- subtle regarding implementation. Implied bounds on types are simpler,
467- especially because if we assume that a type is well-formed, we don't use that
468- fact to deduce that other types are well-formed, we only use it to deduce
469- that e.g. some trait bounds hold.
465+ We mainly talked about implied bounds for traits, but implied bounds on types
466+ are very similar. Suppose we have the following definition:
470467
471- For types, we just use rules like these ones:
472468``` rust,ignore
473469struct Type<...> where WC1, ..., WCn {
474470 ...
475471}
476472```
477473
474+ To prove that ` Type<...> ` is well-formed, we would need to prove a goal of the
475+ form ` WellFormed(Type<...>). ` . The ` WellFormed(Type<...>) ` predicate is defined
476+ by the rule:
477+
478478``` text
479479forall<...> {
480- WellFormed(Type<...>) :- WC1, ..., WCn.
480+ WellFormed(Type<...>) :- WellFormed( WC1) , ..., WellFormed( WCn) .
481481}
482+ ```
483+
484+ Conversely, if we know a type is well-formed from our environment (for example
485+ because it appears as an argument of one of our functions), we can have implied
486+ bounds thanks to the below set of rules:
482487
488+ ``` text
483489forall<...> {
484490 FromEnv(WC1) :- FromEnv(Type<...>).
485491 ...
486492 FromEnv(WCn) :- FromEnv(Type<...>).
487493}
488494```
489- We can see that we have this asymmetry between well-formedness check,
490- which only verifies that the direct superbounds hold, and implied bounds which
491- gives access to all bounds transitively implied by the where clauses. In that
492- case this is ok because as we said, we don't use ` FromEnv(Type<...>) ` to deduce
493- other ` FromEnv(OtherType<...>) ` things, nor do we use ` FromEnv(Type: Trait) ` to
494- deduce ` FromEnv(OtherType<...>) ` things. So in that sense type definitions are
495- "less recursive" than traits, and we saw in a previous subsection that
496- it was the combination of asymmetry and recursive trait / impls that led to
497- unsoundness. As such, the ` WellFormed(Type<...>) ` predicate does not need
498- to be co-inductive.
499495
500- This asymmetry optimization is useful because in a real Rust program, we have
501- to check the well-formedness of types very often (e.g. for each type which
502- appears in the body of a function).
496+ Looking at the above rules, we see that we can never encounter a chain of
497+ deductions of the form ` WellFormed(Type<...>) :- ... :- WellFormed(Type<...>) ` .
498+ So in contrast with traits, the ` WellFormed(Type<...>) ` predicate does not need
499+ to be co-inductive.
0 commit comments