Skip to content

Commit bb86786

Browse files
tmandrymark-i-m
authored andcommitted
Trait logic: Explain what each domain goal means
1 parent 2debb43 commit bb86786

File tree

2 files changed

+73
-24
lines changed

2 files changed

+73
-24
lines changed

src/traits-goals-and-clauses.md

Lines changed: 72 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ its inputs P0..Pm:
6767
Projection = <P0 as TraitName<P1..Pn>>::AssocItem<Pn+1..Pm>
6868
```
6969

70-
Given that, we can define a `DomainGoal` as follows:
70+
Given these, we can define a `DomainGoal` as follows:
7171

7272
```text
7373
DomainGoal = Implemented(TraitRef)
@@ -78,33 +78,82 @@ DomainGoal = Implemented(TraitRef)
7878
| WellFormed(Type)
7979
| WellFormed(TraitRef)
8080
| WellFormed(Projection = Type)
81-
| Outlives(Type, Region)
82-
| Outlives(Region, Region)
81+
| Outlives(Type: Region)
82+
| Outlives(Region: Region)
8383
```
8484

85-
- `Implemented(TraitRef)` -- true if the given trait is
86-
implemented for the given input types and lifetimes
87-
- `FromEnv(TraitEnv)` -- true if the given trait is *assumed* to be implemented;
88-
that is, if it can be derived from the in-scope where clauses
89-
- as we'll see in the section on lowering, `FromEnv(X)` implies
90-
`Implemented(X)` but not vice versa. This distinction is crucial
91-
to [implied bounds].
92-
- `ProjectionEq(Projection = Type)` -- the given associated type `Projection`
93-
is equal to `Type`; see [the section on associated
94-
types](./traits-associated-types.html)
95-
- in general, proving `ProjectionEq(TraitRef::Item = Type)` also
96-
requires proving `Implemented(TraitRef)`
97-
- `Normalize(Projection -> Type)` -- the given associated type `Projection` can
98-
be [normalized][n] to `Type`
99-
- as discussed in [the section on associated
100-
types](./traits-associated-types.html),
101-
`Normalize` implies `ProjectionEq` but not vice versa
102-
- `WellFormed(..)` -- these goals imply that the given item is
103-
*well-formed*
104-
- well-formedness is important to [implied bounds].
85+
Let's break down each one of these, one-by-one.
86+
87+
#### Implemented(TraitRef)
88+
e.g. `Implemented(i32: Copy)`
89+
90+
True if the given trait is implemented for the given input types and lifetimes.
91+
92+
#### ProjectionEq(Projection = Type)
93+
e.g. `ProjectionEq<T as Iterator>::Item = u8`
94+
95+
The given associated type `Projection` is equal to `Type`; this can be proved
96+
with either normalization or using skolemized types. See [the section
97+
on associated types](./traits-associated-types.html).
98+
99+
#### Normalize(Projection -> Type)
100+
e.g. `ProjectionEq<T as Iterator>::Item -> u8`
101+
102+
The given associated type `Projection` can be [normalized][n] to `Type`.
103+
104+
As discussed in [the section on associated
105+
types](./traits-associated-types.html), `Normalize` implies `ProjectionEq`,
106+
but not vice versa. In general, proving `Normalize(<T as Trait>::Item -> U)`
107+
also requires proving `Implemented(T: Trait)`.
105108

106109
[n]: ./traits-associated-types.html#normalize
107110

111+
#### FromEnv(TraitRef), FromEnv(Projection = Type)
112+
e.g. `FromEnv(Self: Add<i32>)`
113+
114+
e.g. `FromEnv(<Self as StreamingIterator>::Item<'a> = &'a [u8])`
115+
116+
True if the inner `TraitRef` or projection equality is *assumed* to be true;
117+
that is, if it can be derived from the in-scope where clauses.
118+
119+
For example, given the following function:
120+
121+
```rust
122+
fn loud_clone<T: Clone>(stuff: &T) -> T {
123+
println!("cloning!");
124+
stuff.clone()
125+
}
126+
```
127+
128+
Inside the body of our function, we would have `FromEnv(T: Clone)`. In-scope
129+
where clauses nest, so a function body inside an impl body inherits the
130+
impl body's where clauses, too.
131+
132+
This and the next rule are used to implement [implied bounds]. As we'll see
133+
in the section on lowering, `FromEnv(X)` implies `Implemented(X)`, but not
134+
vice versa. This distinction is crucial to implied bounds.
135+
136+
#### WellFormed(Item)
137+
These goals imply that the given item is *well-formed*.
138+
139+
We can talk about different types of items being well-formed:
140+
141+
**Types**, like `WellFormed(Vec<i32>)`, which is true in Rust, or
142+
`WellFormed(Vec<str>)`, which is not (because `str` is not `Sized`.)
143+
144+
**TraitRefs**, like `WellFormed(Vec<i32>: Clone)`.
145+
146+
**Projections**, like `WellFormed(T: Iterator<Item = u32>)`.
147+
148+
Well-formedness is important to [implied bounds]. In particular, the reason
149+
it is okay to assume `FromEnv(T: Clone)` in the example above is that we
150+
_also_ verify `WellFormed(T: Clone)` for each call site of `loud_clone`.
151+
152+
#### Outlives(Type: Region), Outlives(Region: Region)
153+
e.g. `Outlives(&'a str: 'b)`, `Outlives('a: 'static)`
154+
155+
True if the given type or region on the left outlives the right-hand region.
156+
108157
<a name="coinductive"></a>
109158

110159
## Coinductive goals

src/traits-lowering-rules.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ forall<Self, P1..Pn> {
113113
```
114114

115115
This clause says that if we are assuming that the trait holds, then we can also
116-
assume that it's where-clauses hold. It's perhaps useful to see an example:
116+
assume that its where-clauses hold. It's perhaps useful to see an example:
117117

118118
```rust,ignore
119119
trait Eq: PartialEq { ... }

0 commit comments

Comments
 (0)