Skip to content

Commit 80e9918

Browse files
committed
Update lowering rules for GATs
1 parent 37f5f85 commit 80e9918

File tree

2 files changed

+72
-38
lines changed

2 files changed

+72
-38
lines changed

src/traits-associated-types.md

+5-2
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,15 @@ we saw above would be lowered to a program clause like so:
5353

5454
```text
5555
forall<T> {
56-
Normalize(<Option<T> as IntoIterator>::Item -> T)
56+
Normalize(<Option<T> as IntoIterator>::Item -> T) :-
57+
Implemented(Option<T>: IntoIterator)
5758
}
5859
```
5960

61+
where in this case, the one `Implemented` condition is always true.
62+
6063
(An aside: since we do not permit quantification over traits, this is
61-
really more like a family of predicates, one for each associated
64+
really more like a family of program clauses, one for each associated
6265
type.)
6366

6467
We could apply that rule to normalize either of the examples that

src/traits-lowering-rules.md

+67-36
Original file line numberDiff line numberDiff line change
@@ -132,8 +132,6 @@ to be **well-formed**:
132132

133133
```text
134134
// Rule WellFormed-TraitRef
135-
//
136-
// For each where clause WC:
137135
forall<Self, P1..Pn> {
138136
WellFormed(Self: Trait<P1..Pn>) :- Implemented(Self: Trait<P1..Pn>) && WellFormed(WC)
139137
}
@@ -198,38 +196,72 @@ in detail in the [section on associated types](./traits-associated-types.html),
198196
but reproduced here for reference:
199197

200198
```text
201-
// Rule ProjectionEq-Normalize
202-
//
203-
// ProjectionEq can succeed by normalizing:
204-
forall<Self, P1..Pn, Pn+1..Pm, U> {
205-
ProjectionEq(<Self as Trait<P1..Pn>>::AssocType<Pn+1..Pm> = U) :-
206-
Normalize(<Self as Trait<P1..Pn>>::AssocType<Pn+1..Pm> -> U)
207-
}
199+
// Rule ProjectionEq-Normalize
200+
//
201+
// ProjectionEq can succeed by normalizing:
202+
forall<Self, P1..Pn, Pn+1..Pm, U> {
203+
ProjectionEq(<Self as Trait<P1..Pn>>::AssocType<Pn+1..Pm> = U) :-
204+
Normalize(<Self as Trait<P1..Pn>>::AssocType<Pn+1..Pm> -> U)
205+
}
206+
```
208207

209-
// Rule ProjectionEq-Skolemize
210-
//
211-
// ProjectionEq can succeed by skolemizing, see "associated type"
212-
// chapter for more:
213-
forall<Self, P1..Pn, Pn+1..Pm> {
214-
ProjectionEq(
215-
<Self as Trait<P1..Pn>>::AssocType<Pn+1..Pm> =
216-
(Trait::AssocType)<Self, P1..Pn, Pn+1..Pm>
217-
) :-
218-
// But only if the trait is implemented, and the conditions from
219-
// the associated type are met as well:
220-
Implemented(Self: Trait<P1..Pn>)
221-
&& WC1
222-
}
208+
```text
209+
// Rule ProjectionEq-Skolemize
210+
//
211+
// ProjectionEq can succeed by skolemizing, see "associated type"
212+
// chapter for more:
213+
forall<Self, P1..Pn, Pn+1..Pm> {
214+
ProjectionEq(
215+
<Self as Trait<P1..Pn>>::AssocType<Pn+1..Pm> =
216+
(Trait::AssocType)<Self, P1..Pn, Pn+1..Pm>
217+
)
218+
}
223219
```
224220

225221
The next rule covers implied bounds for the projection. In particular,
226-
the `Bounds` declared on the associated type must be proven to hold to
227-
show that the impl is well-formed, and hence we can rely on them
222+
the `Bounds` declared on the associated type must have been proven to hold
223+
to show that the impl is well-formed, and hence we can rely on them
228224
elsewhere.
229225

230226
```text
231-
// XXX how exactly should we set this up? Have to be careful;
232-
// presumably this has to be a kind of `FromEnv` setup.
227+
// Rule Implied-Bound-From-AssocTy
228+
//
229+
// For each `Bound` in `Bounds`:
230+
forall<Self, P1..Pn, Pn+1..Pm> {
231+
FromEnv(<Self as Trait<P1..Pn>>::AssocType<Pn+1..Pm>>: Bound) :-
232+
FromEnv(Self: Trait<P1..Pn>)
233+
}
234+
```
235+
236+
Next, we define the requirements for an instantiation of our associated
237+
type to be well-formed...
238+
239+
```text
240+
// Rule WellFormed-AssocTy
241+
forall<Self, P1..Pn, Pn+1..Pm> {
242+
WellFormed((Trait::AssocType)<Self, P1..Pn, Pn+1..Pm>) :-
243+
WC1, Implemented(Self: Trait<P1..Pn>)
244+
}
245+
```
246+
247+
...along with the reverse implications, when we can assume that it is
248+
well-formed.
249+
250+
```text
251+
// Rule Implied-WC-From-AssocTy
252+
//
253+
// For each where clause WC1:
254+
forall<Self, P1..Pn, Pn+1..Pm> {
255+
FromEnv(WC1) :- FromEnv((Trait::AssocType)<Self, P1..Pn, Pn+1..Pm>)
256+
}
257+
```
258+
259+
```text
260+
// Rule Implied-Trait-From-AssocTy
261+
forall<Self, P1..Pn, Pn+1..Pm> {
262+
FromEnv(Self: Trait<P1..Pn>) :-
263+
FromEnv((Trait::AssocType)<Self, P1..Pn, Pn+1..Pm>)
264+
}
233265
```
234266

235267
### Lowering function and constant declarations
@@ -269,26 +301,27 @@ In addition, we will lower all of the *impl items*.
269301
Given an impl that contains:
270302

271303
```rust,ignore
272-
impl<P0..Pn> Trait<A1..An> for A0
273-
where WC
304+
impl<P0..Pn> Trait<P1..Pn> for P0
305+
where WC_impl
274306
{
275-
type AssocType<Pn+1..Pm> where WC1 = T;
307+
type AssocType<Pn+1..Pm> = T;
276308
}
277309
```
278310

279-
We produce the following rule:
311+
and our where clause `WC1` on the trait associated type from above, we
312+
produce the following rule:
280313

281314
```text
282315
// Rule Normalize-From-Impl
283316
forall<P0..Pm> {
284317
forall<Pn+1..Pm> {
285-
Normalize(<A0 as Trait<A1..An>>::AssocType<Pn+1..Pm> -> T) :-
286-
WC && WC1
318+
Normalize(<P0 as Trait<P1..Pn>>::AssocType<Pn+1..Pm> -> T) :-
319+
Implemented(P0 as Trait) && WC1
287320
}
288321
}
289322
```
290323

291-
Note that `WC` and `WC1` both encode where-clauses that the impl can
324+
Note that `WC_impl` and `WC1` both encode where-clauses that the impl can
292325
rely on.
293326

294327
<a name="constant-vals"></a>
@@ -300,5 +333,3 @@ like to treat them exactly like normalization. This presumably
300333
involves adding a new kind of parameter (constant), and then having a
301334
`NormalizeValue` domain goal. This is *to be written* because the
302335
details are a bit up in the air.
303-
304-

0 commit comments

Comments
 (0)