Skip to content

Commit 933d559

Browse files
Niko's intro
Co-authored-by: Niko Matsakis <niko@alum.mit.edu>
1 parent 4801418 commit 933d559

File tree

1 file changed

+24
-7
lines changed

1 file changed

+24
-7
lines changed

src/early-late-bound.md

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,31 @@
11
# Early and Late Bound Variables
22

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]).
913

1014
[quant]: ./appendix/background.md#quantified
1115

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.
1229
Basically, if we cannot represent a type (e.g. a universally quantified type),
1330
we have to bind it _early_ so that the unrepresentable type is never around.
1431

@@ -41,7 +58,7 @@ For example,
4158
```rust,ignore
4259
trait Foo<T> {
4360
type Bar<U> = (Self, T, U);
44-
}
61+
}
4562
```
4663

4764
Here, the type `(Self, T, U)` would be `($0, $1, $2)`, where `$N` means a

0 commit comments

Comments
 (0)