@@ -5,7 +5,7 @@ associated types. The full system consists of several moving parts,
5
5
which we will introduce one by one:
6
6
7
7
- Projection and the ` Normalize ` predicate
8
- - Skolemization
8
+ - Placeholder associated type projections
9
9
- The ` ProjectionEq ` predicate
10
10
- Integration with unification
11
11
@@ -14,11 +14,11 @@ which we will introduce one by one:
14
14
When a trait defines an associated type (e.g.,
15
15
[ the ` Item ` type in the ` IntoIterator ` trait] [ intoiter-item ] ), that
16
16
type can be referenced by the user using an ** associated type
17
- projection** like ` <Option<u32> as IntoIterator>::Item ` . (Often,
18
- though, people will use the shorthand syntax ` T::Item ` – presently,
19
- that syntax is expanded during
20
- [ "type collection"] ( ../type-checking.html ) into the explicit form,
21
- though that is something we may want to change in the future.)
17
+ projection** like ` <Option<u32> as IntoIterator>::Item ` .
18
+
19
+ > Often, people will use the shorthand syntax ` T::Item ` . Presently, that
20
+ > syntax is expanded during [ "type collection"] ( ../type-checking.html ) into the
21
+ > explicit form, though that is something we may want to change in the future.
22
22
23
23
[ intoiter-item ] : https://doc.rust-lang.org/nightly/core/iter/trait.IntoIterator.html#associatedtype.Item
24
24
@@ -41,10 +41,11 @@ IntoIterator>::Item` to just `u32`.
41
41
42
42
In this case, the projection was a "monomorphic" one – that is, it
43
43
did not have any type parameters. Monomorphic projections are special
44
- because they can ** always** be fully normalized – but often we can
45
- normalize other associated type projections as well. For example,
46
- ` <Option<?T> as IntoIterator>::Item ` (where ` ?T ` is an inference
47
- variable) can be normalized to just ` ?T ` .
44
+ because they can ** always** be fully normalized.
45
+
46
+ Often, we can normalize other associated type projections as well. For
47
+ example, ` <Option<?T> as IntoIterator>::Item ` , where ` ?T ` is an inference
48
+ variable, can be normalized to just ` ?T ` .
48
49
49
50
In our logic, normalization is defined by a predicate
50
51
` Normalize ` . The ` Normalize ` clauses arise only from
@@ -60,9 +61,8 @@ forall<T> {
60
61
61
62
where in this case, the one ` Implemented ` condition is always true.
62
63
63
- (An aside: since we do not permit quantification over traits, this is
64
- really more like a family of program clauses, one for each associated
65
- type.)
64
+ > Since we do not permit quantification over traits, this is really more like
65
+ > a family of program clauses, one for each associated type.
66
66
67
67
We could apply that rule to normalize either of the examples that
68
68
we've seen so far.
@@ -76,17 +76,18 @@ normalized. For example, consider this function:
76
76
fn foo<T: IntoIterator>(...) { ... }
77
77
```
78
78
79
- In this context, how would we normalize the type ` T::Item ` ? Without
80
- knowing what ` T ` is, we can't really do so. To represent this case, we
81
- introduce a type called a ** placeholder associated type
82
- projection** . This is written like so ` (IntoIterator::Item)<T> ` . You
83
- may note that it looks a lot like a regular type (e.g., ` Option<T> ` ),
84
- except that the "name" of the type is ` (IntoIterator::Item) ` . This is
85
- not an accident: placeholder associated type projections work just like
86
- ordinary types like ` Vec<T> ` when it comes to unification. That is,
87
- they are only considered equal if (a) they are both references to the
88
- same associated type, like ` IntoIterator::Item ` and (b) their type
89
- arguments are equal.
79
+ In this context, how would we normalize the type ` T::Item ` ?
80
+
81
+ Without knowing what ` T ` is, we can't really do so. To represent this case,
82
+ we introduce a type called a ** placeholder associated type projection** . This
83
+ is written like so: ` (IntoIterator::Item)<T> ` .
84
+
85
+ You may note that it looks a lot like a regular type (e.g., ` Option<T> ` ),
86
+ except that the "name" of the type is ` (IntoIterator::Item) ` . This is not an
87
+ accident: placeholder associated type projections work just like ordinary
88
+ types like ` Vec<T> ` when it comes to unification. That is, they are only
89
+ considered equal if (a) they are both references to the same associated type,
90
+ like ` IntoIterator::Item ` and (b) their type arguments are equal.
90
91
91
92
Placeholder associated types are never written directly by the user.
92
93
They are used internally by the trait system only, as we will see
@@ -106,9 +107,10 @@ placeholder associated types (see the `TypeName` enum declared in
106
107
So far we have seen two ways to answer the question of "When can we
107
108
consider an associated type projection equal to another type?":
108
109
109
- - the ` Normalize ` predicate could be used to transform associated type
110
- projections when we knew which impl was applicable;
111
- - ** placeholder** associated types can be used when we don't.
110
+ - the ` Normalize ` predicate could be used to transform projections when we
111
+ knew which impl applied;
112
+ - ** placeholder** associated types can be used when we don't. This is also
113
+ known as ** lazy normalization** .
112
114
113
115
We now introduce the ` ProjectionEq ` predicate to bring those two cases
114
116
together. The ` ProjectionEq ` predicate looks like so:
@@ -151,16 +153,16 @@ might just fail, in which case we get back `Err(NoSolution)`. This
151
153
would happen, for example, if we tried to unify ` u32 ` and ` i32 ` .
152
154
153
155
The key point is that, on success, unification can also give back to
154
- us a set of subgoals that still remain to be proven (it can also give
156
+ us a set of subgoals that still remain to be proven. (It can also give
155
157
back region constraints, but those are not relevant here).
156
158
157
- Whenever unification encounters an (un -placeholder!) associated type
159
+ Whenever unification encounters a non -placeholder associated type
158
160
projection P being equated with some other type T, it always succeeds,
159
161
but it produces a subgoal ` ProjectionEq(P = T) ` that is propagated
160
162
back up. Thus it falls to the ordinary workings of the trait system
161
163
to process that constraint.
162
164
163
- ( If we unify two projections P1 and P2, then unification produces a
164
- variable X and asks us to prove that ` ProjectionEq(P1 = X) ` and
165
- ` ProjectionEq(P2 = X) ` . That used to be needed in an older system to
166
- prevent cycles; I rather doubt it still is. -nmatsakis)
165
+ > If we unify two projections P1 and P2, then unification produces a
166
+ > variable X and asks us to prove that ` ProjectionEq(P1 = X) ` and
167
+ > ` ProjectionEq(P2 = X) ` . ( That used to be needed in an older system to
168
+ > prevent cycles; I rather doubt it still is. -nmatsakis)
0 commit comments