Skip to content

Tracking issue for release notes of #127672: Stabilize opaque type precise capturing (RFC 3617) #129577

Closed
@rustbot

Description

@rustbot

This issue tracks the release notes text for #127672.

  • Issue is nominated for the responsible team (and T-release nomination is removed).
  • Proposed text is drafted by team responsible for underlying change.
  • Issue is nominated for release team review of clarity for wider audience.
  • Release team includes text in release notes/blog posts.

Release notes text:

The section title will be de-duplicated by the release team with other release notes issues.
Prefer to use the standard titles from previous releases.
More than one section can be included if needed.

# Language
- [Stabilize opaque type precise capturing (RFC 3617)](https://github.com/rust-lang/rust/pull/127672)

Release blog section (if any, leave blank if no section is expected):

### Replacing `Captures` trick with `use<..>` syntax

Rust now supports `use<..>` syntax within certain impl Trait bounds to control which generic lifetime parameters are captured.

Return-position impl Trait (RPIT) types in Rust *capture* certain generic parameters.  Capturing a generic parameter allows that parameter to be used in the hidden type.  That in turn affects borrow checking.

In Rust 2021 and earlier editions, lifetime parameters are not captured in opaque types on bare functions and on functions and methods of inherent impls unless those lifetime parameters are mentioned syntactically in the opaque type.  E.g., this is an error:

```rust
//@ edition: 2021
fn f(x: &()) -> impl Sized { x }
```

```
error[E0700]: hidden type for `impl Sized` captures lifetime that does not appear in bounds
 --> src/main.rs:1:30
  |
1 | fn f(x: &()) -> impl Sized { x }
  |         ---     ----------   ^
  |         |       |
  |         |       opaque type defined here
  |         hidden type `&()` captures the anonymous lifetime defined here
  |
help: add a `use<...>` bound to explicitly capture `'_`
  |
1 | fn f(x: &()) -> impl Sized + use<'_> { x }
  |                            +++++++++
```

With the new `use<..>` syntax, we can fix this, as suggested in the error, by writing:

```rust
fn f(x: &()) -> impl Sized + use<'_> { x }
```

Previously, correctly fixing this class of error required defining a dummy trait, conventionally called `Captures`, and using it as follows:

```rust
trait Captures<T: ?Sized> {}
impl<T: ?Sized, U: ?Sized> Captures<T> for U {}

fn f(x: &()) -> impl Sized + Captures<&'_ ()> { x }
```

That was called "the `Captures` trick", and it was a bit baroque and subtle.  It's no longer needed.

There are some limitations to what is being stabilized.  The `use<..>` syntax cannot currently appear within traits or within trait impls, and it must list all in-scope generic type and const parameters.  We hope to lift these restrictions over time.

Note that in Rust 2024, the example above will "just work" without needing `use<..>` syntax (or any tricks).  This is because in the new edition, opaque types will automatically capture all lifetime parameters in scope.  This is a better default, and we've seen a lot of evidence about how this cleans up code.  In Rust 2024, `use<..>` syntax will serve as an important way of opting-out of that default.

For more details about `use<..>` syntax, capturing, and how this applies to Rust 2024, see the ["RPIT lifetime capture rules"](https://doc.rust-lang.org/nightly/edition-guide/rust-2024/rpit-lifetime-capture.html) chapter of the edition guide.  For details about the overall direction, see our recent blog post, ["Changes to `impl Trait` in Rust 2024"](2024-09-05-impl-trait-capture-rules.md).

Metadata

Metadata

Assignees

Labels

T-langRelevant to the language teamrelnotesMarks issues that should be documented in the release notes of the next release.relnotes-tracking-issueMarks issues tracking what text to put in release notes.

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions