|
1 | 1 | # Early and Late Bound Variables
|
2 | 2 |
|
3 |
| -In Rust, generic types are generally [_universally_ quantified][quant]. |
4 |
| -Notice, however, that in some cases, Rust has no way to represent such |
5 |
| -quantification. For example, there is no `forall<F> foo<F>` in Rust, where `F` |
6 |
| -is a generic type variable (though we can do it in some cases, like `for<'a> |
7 |
| -fn(&'a u32)`). As a result, we have a sort of weird split in how we represent |
8 |
| -some generic types: _early-_ and _late-_ bound parameters. |
| 3 | +In Rust, item definitions (like `fn`) can often have generic parameters, which |
| 4 | +are always [_universally_ quantified][quant]. That is, if you have a function |
| 5 | +like |
| 6 | + |
| 7 | +```rust |
| 8 | +fn foo<T>(x: T) { } |
| 9 | +``` |
| 10 | + |
| 11 | +this function is defined "for all T" (not "for some specific T", which would be |
| 12 | +[_existentially_ quantified][quant]). |
9 | 13 |
|
10 | 14 | [quant]: ./appendix/background.md#quantified
|
11 | 15 |
|
| 16 | +While Rust *items* can be quantified over types, lifetimes, and constants, the |
| 17 | +types of values in Rust are only ever quantified over lifetimes. So you can |
| 18 | +have a type like `for<'a> fn(&'a u32)`, which represents a function pointer |
| 19 | +that takes a reference with any lifetime, or `for<'a> dyn Trait<'a>`, which is |
| 20 | +a `dyn` trait for a trait implemented for any lifetime; but we have no type |
| 21 | +like `for<T> fn(T)`, which would be a function that takes a value of *any type* |
| 22 | +as a parameter. This is a consequence of monomorphization -- to support a value |
| 23 | +of type `for<T> fn(T)`, we would need a single function pointer that can be |
| 24 | +used for a parameter of any type, but in Rust we generate customized code for |
| 25 | +each parameter type. |
| 26 | + |
| 27 | +One consequence of this asymmetry is a weird split in how we represesent some |
| 28 | +generic types: _early-_ and _late-_ bound parameters. |
12 | 29 | Basically, if we cannot represent a type (e.g. a universally quantified type),
|
13 | 30 | we have to bind it _early_ so that the unrepresentable type is never around.
|
14 | 31 |
|
@@ -41,7 +58,7 @@ For example,
|
41 | 58 | ```rust,ignore
|
42 | 59 | trait Foo<T> {
|
43 | 60 | type Bar<U> = (Self, T, U);
|
44 |
| -} |
| 61 | +} |
45 | 62 | ```
|
46 | 63 |
|
47 | 64 | Here, the type `(Self, T, U)` would be `($0, $1, $2)`, where `$N` means a
|
|
0 commit comments