Trait logic: Explain what each domain goal means

This commit is contained in:
Tyler Mandry 2018-05-25 23:03:09 -04:00 committed by Who? Me?!
parent 3ea4a0b683
commit 01f9d655ee
2 changed files with 73 additions and 24 deletions

View File

@ -67,7 +67,7 @@ its inputs P0..Pm:
Projection = <P0 as TraitName<P1..Pn>>::AssocItem<Pn+1..Pm>
```
Given that, we can define a `DomainGoal` as follows:
Given these, we can define a `DomainGoal` as follows:
```text
DomainGoal = Implemented(TraitRef)
@ -78,33 +78,82 @@ DomainGoal = Implemented(TraitRef)
| WellFormed(Type)
| WellFormed(TraitRef)
| WellFormed(Projection = Type)
| Outlives(Type, Region)
| Outlives(Region, Region)
| Outlives(Type: Region)
| Outlives(Region: Region)
```
- `Implemented(TraitRef)` -- true if the given trait is
implemented for the given input types and lifetimes
- `FromEnv(TraitEnv)` -- true if the given trait is *assumed* to be implemented;
that is, if it can be derived from the in-scope where clauses
- as we'll see in the section on lowering, `FromEnv(X)` implies
`Implemented(X)` but not vice versa. This distinction is crucial
to [implied bounds].
- `ProjectionEq(Projection = Type)` -- the given associated type `Projection`
is equal to `Type`; see [the section on associated
types](./traits-associated-types.html)
- in general, proving `ProjectionEq(TraitRef::Item = Type)` also
requires proving `Implemented(TraitRef)`
- `Normalize(Projection -> Type)` -- the given associated type `Projection` can
be [normalized][n] to `Type`
- as discussed in [the section on associated
types](./traits-associated-types.html),
`Normalize` implies `ProjectionEq` but not vice versa
- `WellFormed(..)` -- these goals imply that the given item is
*well-formed*
- well-formedness is important to [implied bounds].
Let's break down each one of these, one-by-one.
#### Implemented(TraitRef)
e.g. `Implemented(i32: Copy)`
True if the given trait is implemented for the given input types and lifetimes.
#### ProjectionEq(Projection = Type)
e.g. `ProjectionEq<T as Iterator>::Item = u8`
The given associated type `Projection` is equal to `Type`; this can be proved
with either normalization or using skolemized types. See [the section
on associated types](./traits-associated-types.html).
#### Normalize(Projection -> Type)
e.g. `ProjectionEq<T as Iterator>::Item -> u8`
The given associated type `Projection` can be [normalized][n] to `Type`.
As discussed in [the section on associated
types](./traits-associated-types.html), `Normalize` implies `ProjectionEq`,
but not vice versa. In general, proving `Normalize(<T as Trait>::Item -> U)`
also requires proving `Implemented(T: Trait)`.
[n]: ./traits-associated-types.html#normalize
#### FromEnv(TraitRef), FromEnv(Projection = Type)
e.g. `FromEnv(Self: Add<i32>)`
e.g. `FromEnv(<Self as StreamingIterator>::Item<'a> = &'a [u8])`
True if the inner `TraitRef` or projection equality is *assumed* to be true;
that is, if it can be derived from the in-scope where clauses.
For example, given the following function:
```rust
fn loud_clone<T: Clone>(stuff: &T) -> T {
println!("cloning!");
stuff.clone()
}
```
Inside the body of our function, we would have `FromEnv(T: Clone)`. In-scope
where clauses nest, so a function body inside an impl body inherits the
impl body's where clauses, too.
This and the next rule are used to implement [implied bounds]. As we'll see
in the section on lowering, `FromEnv(X)` implies `Implemented(X)`, but not
vice versa. This distinction is crucial to implied bounds.
#### WellFormed(Item)
These goals imply that the given item is *well-formed*.
We can talk about different types of items being well-formed:
**Types**, like `WellFormed(Vec<i32>)`, which is true in Rust, or
`WellFormed(Vec<str>)`, which is not (because `str` is not `Sized`.)
**TraitRefs**, like `WellFormed(Vec<i32>: Clone)`.
**Projections**, like `WellFormed(T: Iterator<Item = u32>)`.
Well-formedness is important to [implied bounds]. In particular, the reason
it is okay to assume `FromEnv(T: Clone)` in the example above is that we
_also_ verify `WellFormed(T: Clone)` for each call site of `loud_clone`.
#### Outlives(Type: Region), Outlives(Region: Region)
e.g. `Outlives(&'a str: 'b)`, `Outlives('a: 'static)`
True if the given type or region on the left outlives the right-hand region.
<a name="coinductive"></a>
## Coinductive goals

View File

@ -113,7 +113,7 @@ forall<Self, P1..Pn> {
```
This clause says that if we are assuming that the trait holds, then we can also
assume that it's where-clauses hold. It's perhaps useful to see an example:
assume that its where-clauses hold. It's perhaps useful to see an example:
```rust,ignore
trait Eq: PartialEq { ... }