@@ -405,7 +405,7 @@ Notice that we are now also requiring `Implemented(Self: Trait)` for
405
405
traversing all the implied bounds transitively. This does not change anything
406
406
when checking whether impls are legal, because since we assume
407
407
that 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
409
409
require to prove the set of all bounds transitively implied by the where
410
410
clauses.
411
411
@@ -462,41 +462,38 @@ are effectively visiting all the transitive implied bounds, and only these.
462
462
463
463
## Implied bounds on types
464
464
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:
470
467
471
- For types, we just use rules like these ones:
472
468
``` rust,ignore
473
469
struct Type<...> where WC1, ..., WCn {
474
470
...
475
471
}
476
472
```
477
473
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
+
478
478
``` text
479
479
forall<...> {
480
- WellFormed(Type<...>) :- WC1, ..., WCn.
480
+ WellFormed(Type<...>) :- WellFormed( WC1) , ..., WellFormed( WCn) .
481
481
}
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:
482
487
488
+ ``` text
483
489
forall<...> {
484
490
FromEnv(WC1) :- FromEnv(Type<...>).
485
491
...
486
492
FromEnv(WCn) :- FromEnv(Type<...>).
487
493
}
488
494
```
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.
499
495
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