Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a high level explanation of early/late bound params #1982

Merged
merged 1 commit into from
May 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,9 @@
- [Which `ParamEnv` do I use?](./param_env/param_env_acquisition.md)
- [Type inference](./type-inference.md)
- [Trait solving](./traits/resolution.md)
- [Early and Late Bound Parameter Definitions](./early-late-bound-summary.md)
- [What are early and late bound parameters](./what-does-early-late-bound-mean.md)
- [Interactions with turbofishing](./turbofishing-and-early-late-bound.md)
- [Early and Late Bound Parameter Definitions](./early-late-bound-params/early-late-bound-summary.md)
- [Implementation nuances of early/late bound parameters](./early-late-bound-params/early-late-bound-implementation-nuances.md)
- [Interactions with turbofishing](./early-late-bound-params/turbofishing-and-early-late-bound.md)
- [Higher-ranked trait bounds](./traits/hrtb.md)
- [Caching subtleties](./traits/caching.md)
- [Implied bounds](./traits/implied-bounds.md)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,11 @@
# Early and Late Bound Parameter Definitions
# Early and Late Bound Parameter Implementation Nuances

Understanding this page likely requires a rudimentary understanding of higher ranked
trait bounds/`for<'a>`and also what types such as `dyn for<'a> Trait<'a>` and
`for<'a> fn(&'a u32)` mean. Reading [the nomincon chapter](https://doc.rust-lang.org/nomicon/hrtb.html)
on HRTB may be useful for understanding this syntax. The meaning of `for<'a> fn(&'a u32)`
is incredibly similar to the meaning of `T: for<'a> Trait<'a>`.

If you are looking for information on the `RegionKind` variants `ReLateBound` and `ReEarlyBound`
you should look at the section on [bound vars and params](./bound-vars-and-params.md). This section
discusses what makes generic parameters on functions and closures late/early bound. Not the general
concept of bound vars and generic parameters which `RegionKind` has named somewhat confusingly
with this topic.

## What does it mean for parameters to be early or late bound

All function definitions conceptually have a ZST (this is represented by `TyKind::FnDef` in rustc).
Expand Down
35 changes: 35 additions & 0 deletions src/early-late-bound-params/early-late-bound-summary.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Early/Late bound parameters

This section discusses what it means for generic parameters to be early or late bound.

```rust
fn foo<'a, T>(b: &'a T) -> &'a T { b }
// ^^ ^early bound
// ^^
// ^^late bound
```

Generally when referring to an item with generic parameters you must specify a list of generic arguments corresponding to the item's generic parameters. In
some cases it is permitted to elide these arguments but still, implicitly, a set of arguments are provided (i.e. `Vec::default()` desugars to `Vec::<_>::default()`).

For functions this is not necessarily the case, for example if we take the function `foo` from the example above and write the following code:
```rust
fn main() {
let f = foo::<_>;

let b = String::new();
let c = String::new();

f(&b);
drop(b);
f(&c);
}
```

This code compiles perfectly fine even though there is no single lifetime that could possibly be specified in `foo::<_>` that would allow for both
the `&b` and `&c` borrows to be used as arguments (note: the `drop(b)` line forces the `&b` borrow to be shorter than the `&c` borrow). This works because
the `'a` lifetime is _late bound_.

A generic parameter being late bound means that when we write `foo::<_>` we do not actually provide an argument for that parameter, instead we wait until _calling_ the function to provide the generic argument. In the above example this means that we are doing something like `f::<'_>(&b);` and `f::<'_>(&c);` (although in practice we do not actually support turbofishing late bound parameters in this manner)

It may be helpful to think of "early bound parameter" or "late bound parameter" as meaning "early provided parameter" and "late provided parameter", i.e. we provide the argument to the parameter either early (when naming the function) or late (when calling it).
10 changes: 0 additions & 10 deletions src/early-late-bound-summary.md

This file was deleted.