-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Stabilize #![feature(precise_capturing_in_traits)]
#138128
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
Stabilize #![feature(precise_capturing_in_traits)]
#138128
Conversation
r? @SparrowLii rustbot has assigned @SparrowLii. Use |
I'm putting up this staiblization report up with a request for comments. I think it's basiclaly as ready as it's going to get, but it's very likely I'm missing something that someone wants to see here 😸 cc @rust-lang/lang and @rust-lang/types -- would be cool if y'all could point out anything you'd like to see that's missing from this doc. |
Fantastic. Huge thanks to @compiler-errors for... let me count the ways:
Having reviewed the (exemplary) stabilization report and all tests, and having beat on this a bit myself, this all looks right to me, so I propose: |
Team member @traviscross has proposed to merge this. The next step is review by the rest of the tagged team members:
No concerns currently listed. Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! cc @rust-lang/lang-advisors: FCP proposed for lang, please feel free to register concerns. |
This is blocked on tool support OR deciding it can be done later (not particularly married to either option) |
cc @Veykril @rust-lang/rust-analyzer |
@traviscross AFAIK we (rust-analyzer) don't model capturing yet (our lifetime handling is very-incomplete-to-outright-missing), and goto def etc. should already work. |
@rfcbot reviewed |
1 similar comment
@rfcbot reviewed |
@rustbot labels -I-lang-nominated +I-lang-radar We discussed this in the lang call today to resounding applause. |
🔔 This is now entering its final comment period, as per the review above. 🔔 |
The final comment period, with a disposition to merge, as per the review above, is now complete. As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed. This will be merged soon. |
02ffae3
to
eb3707e
Compare
@bors r+ |
🌲 The tree is currently closed for pull requests below priority 100. This pull request will be tested once the tree is reopened. |
@bors r- This is still waiting for documentation. |
Thanks to @compiler-errors for putting up the Reference PR which is now approved. @rustbot labels -S-waiting-on-documentation This is then ready to go on all fronts, so... @bors r=oli-obk,traviscross rollup |
Rollup of 11 pull requests Successful merges: - rust-lang#138128 (Stabilize `#![feature(precise_capturing_in_traits)]`) - rust-lang#138834 (Group test diffs by stage in post-merge analysis) - rust-lang#138867 (linker: Fix staticlib naming for UEFI) - rust-lang#138874 (Batch mark waiters as unblocked when resuming in the deadlock handler) - rust-lang#138875 (Trusty: Fix build for anonymous pipes and std::sys::process) - rust-lang#138877 (Ignore doctests only in specified targets) - rust-lang#138885 (Fix ui pattern_types test for big-endian platforms) - rust-lang#138905 (Add target maintainer information for powerpc64-unknown-linux-musl) - rust-lang#138911 (Allow defining opaques in statics and consts) - rust-lang#138917 (rustdoc: remove useless `Symbol::is_empty` checks.) - rust-lang#138945 (Override PartialOrd methods for bool) r? `@ghost` `@rustbot` modify labels: rollup
Rollup merge of rust-lang#138128 - compiler-errors:precise-capturing-in-traits, r=oli-obk,traviscross Stabilize `#![feature(precise_capturing_in_traits)]` # Precise capturing (`+ use<>` bounds) in traits - Stabilization Report Fixes rust-lang#130044. ## Stabilization summary This report proposes the stabilization of `use<>` precise capturing bounds in return-position impl traits in traits (RPITITs). This completes a missing part of [RFC 3617 "Precise capturing"]. Precise capturing in traits was not ready for stabilization when the first subset was proposed for stabilization (namely, RPITs on free and inherent functions - rust-lang#127672) since this feature has a slightly different implementation, and it hadn't yet been implemented or tested at the time. It is now complete, and the type system implications of this stabilization are detailed below. ## Motivation Currently, RPITITs capture all in-scope lifetimes, according to the decision made in the ["lifetime capture rules 2024" RFC](https://rust-lang.github.io/rfcs/3498-lifetime-capture-rules-2024.html#return-position-impl-trait-in-trait-rpitit). However, traits can be designed such that some lifetimes in arguments may not want to be captured. There is currently no way to express this. ## Major design decisions since the RFC No major decisions were made. This is simply an extension to the RFC that was understood as a follow-up from the original stabilization. ## What is stabilized? Users may write `+ use<'a, T>` bounds on their RPITITs. This conceptually modifies the desugaring of the RPITIT to omit the lifetimes that we would copy over from the method. For example, ```rust trait Foo { fn method<'a>(&'a self) -> impl Sized; // ... desugars to something like: type RPITIT_1<'a>: Sized; fn method_desugared<'a>(&'a self) -> Self::RPITIT_1<'a>; // ... whereas with precise capturing ... fn precise<'a>(&'a self) -> impl Sized + use<Self>; // ... desugars to something like: type RPITIT_2: Sized; fn precise_desugared<'a>(&'a self) -> Self::RPITIT_2; } ``` And thus the GAT doesn't name `'a`. In the compiler internals, it's not implemented exactly like this, but not in a way that users should expect to be able to observe. #### Limitations on what generics must be captured Currently, we require that all generics from the trait (including the `Self`) type are captured. This is because the generics from the trait are required to be *invariant* in order to do associated type normalization. And like regular precise capturing bounds, all type and const generics in scope must be captured. Thus, only the in-scope method lifetimes may be relaxed with this syntax today. ## What isn't stabilized? (a.k.a. potential future work) See section above. Relaxing the requirement to capture all type and const generics in scope may be relaxed when rust-lang#130043 is implemented, however it currently interacts with some underexplored corners of the type system (e.g. unconstrained type bivariance) so I don't expect it to come soon after. ## Implementation summary This functionality is implemented analogously to the way that *opaque type* precise capturing works. Namely, we currently use *variance* to model the capturedness of lifetimes. However, since RPITITs are anonymous GATs instead of opaque types, we instead modify the type relation of GATs to consider variances for RPITITs (along with opaque types which it has done since rust-lang#103491). https://github.com/rust-lang/rust/blob/30f168ef811aec63124eac677e14699baa9395bd/compiler/rustc_middle/src/ty/util.rs#L954-L976 https://github.com/rust-lang/rust/blob/30f168ef811aec63124eac677e14699baa9395bd/compiler/rustc_type_ir/src/relate.rs#L240-L244 Using variance to model capturedness is an implementation detail, and in the future it would be desirable if opaques and RPITITs simply did not include the uncaptured lifetimes in their generics. This can be changed in a forwards-compatible way, and almost certainly would not be observable by users (at least not negatively, since it may indeed fix some bugs along the way). ## Tests * Test that the lifetime isn't actually captured: `tests/ui/impl-trait/precise-capturing/rpitit.rs` and `tests/ui/impl-trait/precise-capturing/rpitit-outlives.rs` and `tests/ui/impl-trait/precise-capturing/rpitit-outlives-2.rs`. * Technical test for variance computation: `tests/ui/impl-trait/in-trait/variance.rs`. * Test that you must capture all trait generics: `tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs`. * Test that you cannot capture more than what the trait specifies: `tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.rs` and `tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.rs`. * Undercapturing (refinement) lint: `tests/ui/impl-trait/in-trait/refine-captures.rs`. ### What other unstable features may be exposed by this feature? I don't believe that this exposes any new unstable features indirectly. ## Remaining bugs and open issues Not aware of any open issues or bugs. ## Tooling support Rustfmt: ✅ Supports formatting `+ use<>` everywhere. Clippy: ✅ No support needed, unless specific clippy lints are impl'd to care for precise capturing itself. Rustdoc: ✅ Rendering `+ use<>` precise capturing bounds is supported. Rust-analyzer: ✅ Parser support, and then lifetime support isn't needed rust-lang#138128 (comment) (previous: ~~:question: There is parser support, but I am unsure of rust-analyzer's level of support for RPITITs in general.~~) ## History Tracking issue: rust-lang#130044 * rust-lang#131033 * rust-lang#132795 * rust-lang#136554
Rollup of 11 pull requests Successful merges: - rust-lang#138128 (Stabilize `#![feature(precise_capturing_in_traits)]`) - rust-lang#138834 (Group test diffs by stage in post-merge analysis) - rust-lang#138867 (linker: Fix staticlib naming for UEFI) - rust-lang#138874 (Batch mark waiters as unblocked when resuming in the deadlock handler) - rust-lang#138875 (Trusty: Fix build for anonymous pipes and std::sys::process) - rust-lang#138877 (Ignore doctests only in specified targets) - rust-lang#138885 (Fix ui pattern_types test for big-endian platforms) - rust-lang#138905 (Add target maintainer information for powerpc64-unknown-linux-musl) - rust-lang#138911 (Allow defining opaques in statics and consts) - rust-lang#138917 (rustdoc: remove useless `Symbol::is_empty` checks.) - rust-lang#138945 (Override PartialOrd methods for bool) r? `@ghost` `@rustbot` modify labels: rollup
This MR contains the following updates: | Package | Update | Change | |---|---|---| | [rust](https://github.com/rust-lang/rust) | minor | `1.86.0` -> `1.87.0` | MR created with the help of [el-capitano/tools/renovate-bot](https://gitlab.com/el-capitano/tools/renovate-bot). **Proposed changes to behavior should be submitted there as MRs.** --- ### Release Notes <details> <summary>rust-lang/rust (rust)</summary> ### [`v1.87.0`](https://github.com/rust-lang/rust/blob/HEAD/RELEASES.md#Version-1870-2025-05-15) [Compare Source](rust-lang/rust@1.86.0...1.87.0) \========================== <a id="1.87.0-Language"></a> ## Language - [Stabilize `asm_goto` feature](rust-lang/rust#133870) - [Allow parsing open beginning ranges (`..EXPR`) after unary operators `!`, `-`, and `*`](rust-lang/rust#134900). - [Don't require method impls for methods with `Self: Sized` bounds in `impl`s for unsized types](rust-lang/rust#135480) - [Stabilize `feature(precise_capturing_in_traits)` allowing `use<...>` bounds on return position `impl Trait` in `trait`s](rust-lang/rust#138128) <a id="1.87.0-Compiler"></a> ## Compiler - [x86: make SSE2 required for i686 targets and use it to pass SIMD types](rust-lang/rust#135408) <a id="1.87.0-Platform-Support"></a> ## Platform Support - [Remove `i586-pc-windows-msvc` target](rust-lang/rust#137957) Refer to Rust's [platform support page][platform-support-doc] for more information on Rust's tiered platform support. [platform-support-doc]: https://doc.rust-lang.org/rustc/platform-support.html <a id="1.87.0-Libraries"></a> ## Libraries - [Stabilize the anonymous pipe API](rust-lang/rust#127154) - [Add support for unbounded left/right shift operations](rust-lang/rust#129375) - [Print pointer metadata in `Debug` impl of raw pointers](rust-lang/rust#135080) - [`Vec::with_capacity` guarantees it allocates with the amount requested, even if `Vec::capacity` returns a different number.](rust-lang/rust#135933) - Most `std::arch` intrinsics which don't take pointer arguments can now be called from safe code if the caller has the appropriate target features already enabled (rust-lang/stdarch#1714, rust-lang/stdarch#1716, rust-lang/stdarch#1717) - [Undeprecate `env::home_dir`](rust-lang/rust#137327) - [Denote `ControlFlow` as `#[must_use]`](rust-lang/rust#137449) - [Macros such as `assert_eq!` and `vec!` now support `const {...}` expressions](rust-lang/rust#138162) <a id="1.87.0-Stabilized-APIs"></a> ## Stabilized APIs - [`Vec::extract_if`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.extract_if) - [`vec::ExtractIf`](https://doc.rust-lang.org/stable/std/vec/struct.ExtractIf.html) - [`LinkedList::extract_if`](https://doc.rust-lang.org/stable/std/collections/struct.LinkedList.html#method.extract_if) - [`linked_list::ExtractIf`](https://doc.rust-lang.org/stable/std/collections/linked_list/struct.ExtractIf.html) - [`<[T]>::split_off`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.split_off) - [`<[T]>::split_off_mut`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.split_off_mut) - [`<[T]>::split_off_first`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.split_off_first) - [`<[T]>::split_off_first_mut`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.split_off_first_mut) - [`<[T]>::split_off_last`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.split_off_last) - [`<[T]>::split_off_last_mut`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.split_off_last_mut) - [`String::extend_from_within`](https://doc.rust-lang.org/stable/alloc/string/struct.String.html#method.extend_from_within) - [`os_str::Display`](https://doc.rust-lang.org/stable/std/ffi/os_str/struct.Display.html) - [`OsString::display`](https://doc.rust-lang.org/stable/std/ffi/struct.OsString.html#method.display) - [`OsStr::display`](https://doc.rust-lang.org/stable/std/ffi/struct.OsStr.html#method.display) - [`io::pipe`](https://doc.rust-lang.org/stable/std/io/fn.pipe.html) - [`io::PipeReader`](https://doc.rust-lang.org/stable/std/io/struct.PipeReader.html) - [`io::PipeWriter`](https://doc.rust-lang.org/stable/std/io/struct.PipeWriter.html) - [`impl From<PipeReader> for OwnedHandle`](https://doc.rust-lang.org/stable/std/os/windows/io/struct.OwnedHandle.html#impl-From%3CPipeReader%3E-for-OwnedHandle) - [`impl From<PipeWriter> for OwnedHandle`](https://doc.rust-lang.org/stable/std/os/windows/io/struct.OwnedHandle.html#impl-From%3CPipeWriter%3E-for-OwnedHandle) - [`impl From<PipeReader> for Stdio`](https://doc.rust-lang.org/stable/std/process/struct.Stdio.html) - [`impl From<PipeWriter> for Stdio`](https://doc.rust-lang.org/stable/std/process/struct.Stdio.html#impl-From%3CPipeWriter%3E-for-Stdio) - [`impl From<PipeReader> for OwnedFd`](https://doc.rust-lang.org/stable/std/os/fd/struct.OwnedFd.html#impl-From%3CPipeReader%3E-for-OwnedFd) - [`impl From<PipeWriter> for OwnedFd`](https://doc.rust-lang.org/stable/std/os/fd/struct.OwnedFd.html#impl-From%3CPipeWriter%3E-for-OwnedFd) - [`Box<MaybeUninit<T>>::write`](https://doc.rust-lang.org/stable/std/boxed/struct.Box.html#method.write) - [`impl TryFrom<Vec<u8>> for String`](https://doc.rust-lang.org/stable/std/string/struct.String.html#impl-TryFrom%3CVec%3Cu8%3E%3E-for-String) - [`<*const T>::offset_from_unsigned`](https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.offset_from_unsigned) - [`<*const T>::byte_offset_from_unsigned`](https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.byte_offset_from_unsigned) - [`<*mut T>::offset_from_unsigned`](https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.offset_from_unsigned-1) - [`<*mut T>::byte_offset_from_unsigned`](https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.byte_offset_from_unsigned-1) - [`NonNull::offset_from_unsigned`](https://doc.rust-lang.org/stable/std/ptr/struct.NonNull.html#method.offset_from_unsigned) - [`NonNull::byte_offset_from_unsigned`](https://doc.rust-lang.org/stable/std/ptr/struct.NonNull.html#method.byte_offset_from_unsigned) - [`<uN>::cast_signed`](https://doc.rust-lang.org/stable/std/primitive.usize.html#method.cast_signed) - [`NonZero::<uN>::cast_signed`](https://doc.rust-lang.org/stable/std/num/struct.NonZero.html#method.cast_signed-5). - [`<iN>::cast_unsigned`](https://doc.rust-lang.org/stable/std/primitive.isize.html#method.cast_unsigned). - [`NonZero::<iN>::cast_unsigned`](https://doc.rust-lang.org/stable/std/num/struct.NonZero.html#method.cast_unsigned-5). - [`<uN>::is_multiple_of`](https://doc.rust-lang.org/stable/std/primitive.usize.html#method.is_multiple_of) - [`<uN>::unbounded_shl`](https://doc.rust-lang.org/stable/std/primitive.usize.html#method.unbounded_shl) - [`<uN>::unbounded_shr`](https://doc.rust-lang.org/stable/std/primitive.usize.html#method.unbounded_shr) - [`<iN>::unbounded_shl`](https://doc.rust-lang.org/stable/std/primitive.isize.html#method.unbounded_shl) - [`<iN>::unbounded_shr`](https://doc.rust-lang.org/stable/std/primitive.isize.html#method.unbounded_shr) - [`<iN>::midpoint`](https://doc.rust-lang.org/stable/std/primitive.isize.html#method.midpoint) - [`<str>::from_utf8`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.from_utf8) - [`<str>::from_utf8_mut`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.from_utf8\_mut) - [`<str>::from_utf8_unchecked`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.from_utf8\_unchecked) - [`<str>::from_utf8_unchecked_mut`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.from_utf8\_unchecked_mut) These previously stable APIs are now stable in const contexts: - [`core::str::from_utf8_mut`](https://doc.rust-lang.org/stable/std/str/fn.from_utf8\_mut.html) - [`<[T]>::copy_from_slice`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.copy_from_slice) - [`SocketAddr::set_ip`](https://doc.rust-lang.org/stable/std/net/enum.SocketAddr.html#method.set_ip) - [`SocketAddr::set_port`](https://doc.rust-lang.org/stable/std/net/enum.SocketAddr.html#method.set_port), - [`SocketAddrV4::set_ip`](https://doc.rust-lang.org/stable/std/net/struct.SocketAddrV4.html#method.set_ip) - [`SocketAddrV4::set_port`](https://doc.rust-lang.org/stable/std/net/struct.SocketAddrV4.html#method.set_port), - [`SocketAddrV6::set_ip`](https://doc.rust-lang.org/stable/std/net/struct.SocketAddrV6.html#method.set_ip) - [`SocketAddrV6::set_port`](https://doc.rust-lang.org/stable/std/net/struct.SocketAddrV6.html#method.set_port) - [`SocketAddrV6::set_flowinfo`](https://doc.rust-lang.org/stable/std/net/struct.SocketAddrV6.html#method.set_flowinfo) - [`SocketAddrV6::set_scope_id`](https://doc.rust-lang.org/stable/std/net/struct.SocketAddrV6.html#method.set_scope_id) - [`char::is_digit`](https://doc.rust-lang.org/stable/std/primitive.char.html#method.is_digit) - [`char::is_whitespace`](https://doc.rust-lang.org/stable/std/primitive.char.html#method.is_whitespace) - [`<[[T; N]]>::as_flattened`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.as_flattened) - [`<[[T; N]]>::as_flattened_mut`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.as_flattened_mut) - [`String::into_bytes`](https://doc.rust-lang.org/stable/std/string/struct.String.html#method.into_bytes) - [`String::as_str`](https://doc.rust-lang.org/stable/std/string/struct.String.html#method.as_str) - [`String::capacity`](https://doc.rust-lang.org/stable/std/string/struct.String.html#method.capacity) - [`String::as_bytes`](https://doc.rust-lang.org/stable/std/string/struct.String.html#method.as_bytes) - [`String::len`](https://doc.rust-lang.org/stable/std/string/struct.String.html#method.len) - [`String::is_empty`](https://doc.rust-lang.org/stable/std/string/struct.String.html#method.is_empty) - [`String::as_mut_str`](https://doc.rust-lang.org/stable/std/string/struct.String.html#method.as_mut_str) - [`String::as_mut_vec`](https://doc.rust-lang.org/stable/std/string/struct.String.html#method.as_mut_vec) - [`Vec::as_ptr`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.as_ptr) - [`Vec::as_slice`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.as_slice) - [`Vec::capacity`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.capacity) - [`Vec::len`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.len) - [`Vec::is_empty`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.is_empty) - [`Vec::as_mut_slice`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.as_mut_slice) - [`Vec::as_mut_ptr`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.as_mut_ptr) <a id="1.87.0-Cargo"></a> ## Cargo - [Add terminal integration via ANSI OSC 9;4 sequences](rust-lang/cargo#14615) - [chore: bump openssl to v3](rust-lang/cargo#15232) - [feat(package): add --exclude-lockfile flag](rust-lang/cargo#15234) <a id="1.87.0-Compatibility-Notes"></a> ## Compatibility Notes - [Rust now raises an error for macro invocations inside the `#![crate_name]` attribute](rust-lang/rust#127581) - [Unstable fields are now always considered to be inhabited](rust-lang/rust#133889) - [Macro arguments of unary operators followed by open beginning ranges may now be matched differently](rust-lang/rust#134900) - [Make `Debug` impl of raw pointers print metadata if present](rust-lang/rust#135080) - [Warn against function pointers using unsupported ABI strings in dependencies](rust-lang/rust#135767) - [Associated types on `dyn` types are no longer deduplicated](rust-lang/rust#136458) - [Forbid attributes on `..` inside of struct patterns (`let Struct { #[attribute] .. }) =`](rust-lang/rust#136490) - [Make `ptr_cast_add_auto_to_object` lint into hard error](rust-lang/rust#136764) - Many `std::arch` intrinsics are now safe to call in some contexts, there may now be new `unused_unsafe` warnings in existing codebases. - [Limit `width` and `precision` formatting options to 16 bits on all targets](rust-lang/rust#136932) - [Turn order dependent trait objects future incompat warning into a hard error](rust-lang/rust#136968) - [Denote `ControlFlow` as `#[must_use]`](rust-lang/rust#137449) - [Windows: The standard library no longer links `advapi32`, except on win7.](rust-lang/rust#138233) Code such as C libraries that were relying on this assumption may need to explicitly link advapi32. - [Proc macros can no longer observe expanded `cfg(true)` attributes.](rust-lang/rust#138844) - [Start changing the internal representation of pasted tokens](rust-lang/rust#124141). Certain invalid declarative macros that were previously accepted in obscure circumstances are now correctly rejected by the compiler. Use of a `tt` fragment specifier can often fix these macros. - [Don't allow flattened format_args in const.](rust-lang/rust#139624) <a id="1.87.0-Internal-Changes"></a> ## Internal Changes These changes do not affect any public interfaces of Rust, but they represent significant improvements to the performance or internals of rustc and related tools. - [Update to LLVM 20](rust-lang/rust#135763) </details> --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever MR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this MR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this MR, check this box --- This MR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MC4xMS4xOSIsInVwZGF0ZWRJblZlciI6IjQwLjExLjE5IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJSZW5vdmF0ZSBCb3QiXX0=-->
Precise capturing (
+ use<>
bounds) in traits - Stabilization ReportFixes #130044.
Stabilization summary
This report proposes the stabilization of
use<>
precise capturing bounds in return-position impl traits in traits (RPITITs). This completes a missing part of [RFC 3617 "Precise capturing"].Precise capturing in traits was not ready for stabilization when the first subset was proposed for stabilization (namely, RPITs on free and inherent functions - #127672) since this feature has a slightly different implementation, and it hadn't yet been implemented or tested at the time. It is now complete, and the type system implications of this stabilization are detailed below.
Motivation
Currently, RPITITs capture all in-scope lifetimes, according to the decision made in the "lifetime capture rules 2024" RFC. However, traits can be designed such that some lifetimes in arguments may not want to be captured. There is currently no way to express this.
Major design decisions since the RFC
No major decisions were made. This is simply an extension to the RFC that was understood as a follow-up from the original stabilization.
What is stabilized?
Users may write
+ use<'a, T>
bounds on their RPITITs. This conceptually modifies the desugaring of the RPITIT to omit the lifetimes that we would copy over from the method. For example,And thus the GAT doesn't name
'a
. In the compiler internals, it's not implemented exactly like this, but not in a way that users should expect to be able to observe.Limitations on what generics must be captured
Currently, we require that all generics from the trait (including the
Self
) type are captured. This is because the generics from the trait are required to be invariant in order to do associated type normalization.And like regular precise capturing bounds, all type and const generics in scope must be captured.
Thus, only the in-scope method lifetimes may be relaxed with this syntax today.
What isn't stabilized? (a.k.a. potential future work)
See section above. Relaxing the requirement to capture all type and const generics in scope may be relaxed when #130043 is implemented, however it currently interacts with some underexplored corners of the type system (e.g. unconstrained type bivariance) so I don't expect it to come soon after.
Implementation summary
This functionality is implemented analogously to the way that opaque type precise capturing works.
Namely, we currently use variance to model the capturedness of lifetimes. However, since RPITITs are anonymous GATs instead of opaque types, we instead modify the type relation of GATs to consider variances for RPITITs (along with opaque types which it has done since #103491).
rust/compiler/rustc_middle/src/ty/util.rs
Lines 954 to 976 in 30f168e
rust/compiler/rustc_type_ir/src/relate.rs
Lines 240 to 244 in 30f168e
Using variance to model capturedness is an implementation detail, and in the future it would be desirable if opaques and RPITITs simply did not include the uncaptured lifetimes in their generics. This can be changed in a forwards-compatible way, and almost certainly would not be observable by users (at least not negatively, since it may indeed fix some bugs along the way).
Tests
tests/ui/impl-trait/precise-capturing/rpitit.rs
andtests/ui/impl-trait/precise-capturing/rpitit-outlives.rs
andtests/ui/impl-trait/precise-capturing/rpitit-outlives-2.rs
.tests/ui/impl-trait/in-trait/variance.rs
.tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs
.tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.rs
andtests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.rs
.tests/ui/impl-trait/in-trait/refine-captures.rs
.What other unstable features may be exposed by this feature?
I don't believe that this exposes any new unstable features indirectly.
Remaining bugs and open issues
Not aware of any open issues or bugs.
Tooling support
Rustfmt: ✅ Supports formatting
+ use<>
everywhere.Clippy: ✅ No support needed, unless specific clippy lints are impl'd to care for precise capturing itself.
Rustdoc: ✅ Rendering
+ use<>
precise capturing bounds is supported.Rust-analyzer: ✅ Parser support, and then lifetime support isn't needed #138128 (comment) (previous:
❓ There is parser support, but I am unsure of rust-analyzer's level of support for RPITITs in general.)History
Tracking issue: #130044
use<..>
in RPITIT for refinement #132795opt_alias_variances
and use it in outlives code #136554