Skip to content

Commit

Permalink
Remove the words "elide" and "elided"
Browse files Browse the repository at this point in the history
We instead speak about these not being present in most cases, and in
the places that doesn't quite work, we talk about them being
"omitted" to avoid the "elided" word.
  • Loading branch information
traviscross committed Aug 6, 2024
1 parent e95a649 commit a831726
Showing 1 changed file with 23 additions and 23 deletions.
46 changes: 23 additions & 23 deletions src/rust-2024/rpit-lifetime-capture.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ This chapter describes changes related to the **Lifetime Capture Rules 2024** in

## Summary

- In Rust 2024, *all* in-scope generic parameters, including lifetime parameters, are implicitly captured when the `use<..>` bound is elided (i.e. not present).
- In Rust 2024, *all* in-scope generic parameters, including lifetime parameters, are implicitly captured when the `use<..>` bound is not present.
- In all editions, `use<..>` bounds allow for specifying explicitly which lifetime parameters to capture in RPIT opaque types.
- Uses of the `Captures` trick (`Captures<..>` bounds) and of the outlives trick (e.g. `'_` bounds) can be replaced by `use<..>` bounds (in all editions) or removed entirely (in Rust 2024).

Expand Down Expand Up @@ -70,34 +70,34 @@ fn test<'a>(x: &'a ()) -> impl Sized + 'static {

The bounds list of an RPIT opaque type may contain at most one `use<..>` bound. If this bound is present, then the listed generic parameters are the only ones captured.

### Edition-specific rules for elided `use<..>` bounds
### Edition-specific rules when no `use<..>` bound is present

If the `use<..>` bound is *elided* (i.e., not present), then the compiler uses edition-specific rules to decide which in-scope generic parameters to capture implicitly.
If the `use<..>` bound is not present, then the compiler uses edition-specific rules to decide which in-scope generic parameters to capture implicitly.

In all editions, all in-scope type and const generic parameters are captured implicitly when the `use<..>` bound is elided. E.g.:
In all editions, all in-scope type and const generic parameters are captured implicitly when the `use<..>` bound is not present. E.g.:

```rust
# #![feature(precise_capturing)]
fn f_elided<T, const C: usize>() -> impl Sized {}
// ~~~~~~~~~~
// The `use<..>` bound is elided here.
fn f_implicit<T, const C: usize>() -> impl Sized {}
// ~~~~~~~~~~
// No `use<..>` bound is present here.
//
// In all editions, the above is equivalent to:
fn f_explicit<T, const C: usize>() -> impl Sized + use<T, C> {}
```

In Rust 2021 and earlier editions, when the `use<..>` bound is elided, generic lifetime parameters are only implicitly captured when they appear syntactically within a bound in RPIT opaque types in the signature of bare functions and associated functions and methods within inherent impls. However, starting in Rust 2024, these in-scope generic lifetime parameters *are* implicitly captured. E.g.:
In Rust 2021 and earlier editions, when the `use<..>` bound is not present, generic lifetime parameters are only implicitly captured when they appear syntactically within a bound in RPIT opaque types in the signature of bare functions and associated functions and methods within inherent impls. However, starting in Rust 2024, these in-scope generic lifetime parameters *are* implicitly captured. E.g.:

```rust
# #![feature(precise_capturing)]
fn f_elided(_: &()) -> impl Sized {}
fn f_implicit(_: &()) -> impl Sized {}
// In Rust 2021 and earlier, the above is equivalent to:
fn f_2021(_: &()) -> impl Sized + use<> {}
// In Rust 2024 and later, it's equivalent to:
fn f_2024(_: &()) -> impl Sized + use<'_> {}
```

This makes the behavior consistent with RPIT opaque types in the signature of associated functions and methods within trait impls, uses of RPIT within trait definitions (RPITIT), and opaque `Future` types created by `async fn`, all of which implicitly capture all in-scope generic lifetime parameters in all editions when the `use<..>` bound is elided.
This makes the behavior consistent with RPIT opaque types in the signature of associated functions and methods within trait impls, uses of RPIT within trait definitions (RPITIT), and opaque `Future` types created by `async fn`, all of which implicitly capture all in-scope generic lifetime parameters in all editions when the `use<..>` bound is not present.

### Outer generic parameters

Expand All @@ -109,12 +109,12 @@ struct S<T, const C: usize>((T, [(); C]));
impl<T, const C: usize> S<T, C> {
// ~~~~~~~~~~~~~~~~~
// These generic parameters are in scope.
fn f_elided<U>() -> impl Sized {}
// ~ ~~~~~~~~~~
// ^ This generic is in scope too.
// ^
// |
// The `use<..>` bound is elided here.
fn f_implicit<U>() -> impl Sized {}
// ~ ~~~~~~~~~~
// ^ This generic is in scope too.
// ^
// |
// No `use<..>` bound is present here.
//
// In all editions, it's equivalent to:
fn f_explicit<U>() -> impl Sized + use<T, U, C> {}
Expand All @@ -130,7 +130,7 @@ Similarly, generic lifetime parameters introduced into scope by a higher-ranked
trait Tr<'a> { type Ty; }
impl Tr<'_> for () { type Ty = (); }

fn f_elided() -> impl for<'a> Tr<'a, Ty = impl Copy + use<>> {}
fn f_implicit() -> impl for<'a> Tr<'a, Ty = impl Copy> {}
// In Rust 2021 and earlier, the above is equivalent to:
fn f_2021() -> impl for<'a> Tr<'a, Ty = impl Copy + use<>> {}
// In Rust 2024 and later, it's equivalent to:
Expand All @@ -146,9 +146,9 @@ Anonymous (i.e. unnamed) generic parameters created by the use of APIT (argument

```rust
# #![feature(precise_capturing)]
fn f_elided(_: impl Sized) -> impl Sized {}
// ~~~~~~~~~~
// This is called APIT.
fn f_implicit(_: impl Sized) -> impl Sized {}
// ~~~~~~~~~~
// This is called APIT.
//
// The above is *roughly* equivalent to:
fn f_explicit<_0: Sized>(_: _0) -> impl Sized + use<_0> {}
Expand Down Expand Up @@ -214,7 +214,7 @@ fn f<'a, T: Sized>(x: &'a (), y: T) -> impl Sized + use<T> { (*x, y) }
# }
```

Note that this changes the API of the function slightly as a type argument can now be explicitly provided for this parameter using turbofish syntax. If this is undesired, you might consider instead whether you can simply continue to elide the `use<..>` bound and allow the lifetime to be captured. This might be particularly desirable if you might in the future want to use that lifetime in the hidden type and would like to save space for that.
Note that this changes the API of the function slightly as a type argument can now be explicitly provided for this parameter using turbofish syntax. If this is undesired, you might consider instead whether you can simply continue to omit the `use<..>` bound and allow the lifetime to be captured. This might be particularly desirable if you might in the future want to use that lifetime in the hidden type and would like to save space for that.

### Migrating away from the `Captures` trick

Expand Down Expand Up @@ -249,7 +249,7 @@ fn f<'a, T>(x: &'a (), y: T) -> impl Sized + use<'a, T> {
# }
```

In Rust 2024, the `use<..>` bound can often be elided entirely, and the above can be written simply as:
In Rust 2024, the `use<..>` bound can often be omitted entirely, and the above can be written simply as:

<!-- TODO: edition2024 -->
```rust
Expand Down Expand Up @@ -296,7 +296,7 @@ fn f<T>(x: &(), y: T) -> impl Sized + use<'_, T> {
# }
```

In Rust 2024, the `use<..>` bound can often be elided entirely, and the above can be written simply as:
In Rust 2024, the `use<..>` bound can often be omitted entirely, and the above can be written simply as:

<!-- TODO: edition2024 -->
```rust
Expand Down

0 comments on commit a831726

Please sign in to comment.