-
Notifications
You must be signed in to change notification settings - Fork 13.2k
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 opt_alias_variances
and use it in outlives code
#136554
Merged
Merged
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
compiler-errors
commented
Feb 4, 2025
compiler-errors
commented
Feb 4, 2025
lcnr
reviewed
Feb 5, 2025
lcnr
reviewed
Feb 5, 2025
7062c4e
to
2591170
Compare
2591170
to
d17a4a7
Compare
@bors r+ rollup |
matthiaskrgr
added a commit
to matthiaskrgr/rust
that referenced
this pull request
Feb 7, 2025
…s, r=lcnr Add `opt_alias_variances` and use it in outlives code ...so to fix some subtle outlives bugs with precise capturing in traits, and eventually make it easier to compute variances for "forced unconstrained" trait lifetimes. r? lcnr
This was referenced Feb 7, 2025
bors
added a commit
to rust-lang-ci/rust
that referenced
this pull request
Feb 8, 2025
…iaskrgr Rollup of 7 pull requests Successful merges: - rust-lang#135179 (Make sure to use `Receiver` trait when extracting object method candidate) - rust-lang#136554 (Add `opt_alias_variances` and use it in outlives code) - rust-lang#136556 ([AIX] Update tests/ui/wait-forked-but-failed-child.rs to accomodate exiting and idle processes.) - rust-lang#136589 (Enable "jump to def" feature on rustc docs) - rust-lang#136615 (sys: net: Add UEFI stubs) - rust-lang#136635 (Remove outdated `base_port` calculation in std net test) - rust-lang#136682 (Move two windows process tests to tests/ui) r? `@ghost` `@rustbot` modify labels: rollup
rust-timer
added a commit
to rust-lang-ci/rust
that referenced
this pull request
Feb 8, 2025
Rollup merge of rust-lang#136554 - compiler-errors:opt-alias-variances, r=lcnr Add `opt_alias_variances` and use it in outlives code ...so to fix some subtle outlives bugs with precise capturing in traits, and eventually make it easier to compute variances for "forced unconstrained" trait lifetimes. r? lcnr
github-actions bot
pushed a commit
to tautschnig/verify-rust-std
that referenced
this pull request
Mar 11, 2025
…iaskrgr Rollup of 7 pull requests Successful merges: - rust-lang#135179 (Make sure to use `Receiver` trait when extracting object method candidate) - rust-lang#136554 (Add `opt_alias_variances` and use it in outlives code) - rust-lang#136556 ([AIX] Update tests/ui/wait-forked-but-failed-child.rs to accomodate exiting and idle processes.) - rust-lang#136589 (Enable "jump to def" feature on rustc docs) - rust-lang#136615 (sys: net: Add UEFI stubs) - rust-lang#136635 (Remove outdated `base_port` calculation in std net test) - rust-lang#136682 (Move two windows process tests to tests/ui) r? `@ghost` `@rustbot` modify labels: rollup
jhpratt
added a commit
to jhpratt/rust
that referenced
this pull request
Mar 26, 2025
…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
rust-timer
added a commit
to rust-lang-ci/rust
that referenced
this pull request
Mar 26, 2025
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Labels
S-waiting-on-bors
Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
T-compiler
Relevant to the compiler team, which will review and decide on the PR/issue.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
...so to fix some subtle outlives bugs with precise capturing in traits, and eventually make it easier to compute variances for "forced unconstrained" trait lifetimes.
r? lcnr