Skip to content

Commit 529a755

Browse files
scalexmmark-i-m
authored andcommitted
Add chalk rules for type defs
1 parent 6317149 commit 529a755

File tree

1 file changed

+75
-1
lines changed

1 file changed

+75
-1
lines changed

src/traits/lowering-rules.md

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,80 @@ we must show that `WellFormed(TraitRef)`. This in turn justifies the
174174
implied bounds rules that allow us to extend the set of `FromEnv`
175175
items.
176176

177+
## Lowering type definitions
178+
179+
We also want to have some rules which define when a type is well-formed.
180+
For example, given this type:
181+
182+
```rust,ignore
183+
struct Set<K> where K: Hash { ... }
184+
```
185+
186+
then `Set<i32>` is well-formed because `i32` implements `Hash`, but
187+
`Set<NotHash>` would not be well-formed. Basically, a type is well-formed
188+
if its parameters verify the where clauses written on the type definition.
189+
190+
Hence, for every type definition:
191+
192+
```rust, ignore
193+
struct Type<P1..Pn> where WC { ... }
194+
```
195+
196+
we produce the following rule:
197+
198+
```text
199+
// Rule WellFormed-Type
200+
forall<P1..Pn> {
201+
WellFormed(Type<P1..Pn>) :- WC
202+
}
203+
```
204+
205+
Note that we use `struct` for defining a type, but this should be understood
206+
as a general type definition (it could be e.g. a generic `enum`).
207+
208+
Conversely, we define rules which say that if we assume that a type is
209+
well-formed, we can also assume that its where clauses hold. That is,
210+
we produce the following family of rules:
211+
212+
```text
213+
// Rule FromEnv-Type
214+
//
215+
// For each where clause `WC`
216+
forall<P1..Pn> {
217+
FromEnv(WC) :- FromEnv(Type<P1..Pn>)
218+
}
219+
```
220+
221+
As for the implied bounds RFC, functions will *assume* that their arguments
222+
are well-formed. For example, suppose we have the following bit of code:
223+
224+
```rust,ignore
225+
trait Hash: Eq { }
226+
struct Set<K: Hash> { ... }
227+
228+
fn foo<K>(collection: Set<K>, x: K, y: K) {
229+
// `x` and `y` can be equalized even if we did not explicitly write
230+
// `where K: Eq`
231+
if x == y {
232+
...
233+
}
234+
}
235+
```
236+
237+
in the `foo` function, we assume that `Set<K>` is well-formed, i.e. we have
238+
`FromEnv(Set<K>)` in our environment. Because of the previous rule, we get
239+
`FromEnv(K: Hash)` without needing an explicit where clause. And because
240+
of the `Hash` trait definition, there also exists a rule which says:
241+
242+
```text
243+
forall<K> {
244+
FromEnv(K: Eq) :- FromEnv(K: Hash)
245+
}
246+
```
247+
248+
which means that we finally get `FromEnv(K: Eq)` and then can compare `x`
249+
and `y` without needing an explicit where clause.
250+
177251
<a name="trait-items"></a>
178252

179253
## Lowering trait items
@@ -333,4 +407,4 @@ Chalk didn't model functions and constants, but I would eventually
333407
like to treat them exactly like normalization. This presumably
334408
involves adding a new kind of parameter (constant), and then having a
335409
`NormalizeValue` domain goal. This is *to be written* because the
336-
details are a bit up in the air.
410+
details are a bit up in the air.

0 commit comments

Comments
 (0)