-
Notifications
You must be signed in to change notification settings - Fork 114
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 chapter for Lifetime Capture Rules 2024 #316
Merged
Merged
+292
−4
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
This was referenced Aug 5, 2024
compiler-errors
suggested changes
Aug 5, 2024
This comment was marked as resolved.
This comment was marked as resolved.
Let's describe the changes to the opaque type lifetime capture rules, and what users will need to do to migrate, in some detail.
traviscross
force-pushed
the
TC/lifetime-capture-rules-2024
branch
from
August 6, 2024 19:31
9dcf78c
to
516f20e
Compare
matthiaskrgr
added a commit
to matthiaskrgr/rust
that referenced
this pull request
Aug 14, 2024
Update books ## rust-lang/book 7 commits in 67fa536768013d9d5a13f3a06790521d511ef711..04bc1396bb857f35b5dda1d773c9571e1f253304 2024-07-31 13:19:44 UTC to 2024-07-16 18:18:38 UTC - mdbook-trpl-listing: Add missing elided lifetimes (rust-lang/book#3995) - infra: include ghp-import and git push in generate-preview script (rust-lang/book#3998) - infra: add robots.txt for GH Pages previews (rust-lang/book#3997) - Clarify function definitions vs. expressions (rust-lang/book#3870) - infra: fix some shellcheck issues in CI config (rust-lang/book#3988) - infra: support test renderer in mdbook preprocessors (rust-lang/book#3982) - Improve handling of `<Listing>`s (rust-lang/book#3975) ## rust-lang/edition-guide 4 commits in 5454de3d12b9ccc6375b629cf7ccda8264640aac..aeeb287d41a0332c210da122bea8e0e91844ab3e 2024-08-06 21:16:24 UTC to 2024-07-29 21:41:36 UTC - Stabilize unsafe extern blocks (rust-lang/edition-guide#313) - Add chapter for Lifetime Capture Rules 2024 (rust-lang/edition-guide#316) - 2024: Add page for missing_fragment_specifier (rust-lang/edition-guide#315) - Add documentation for 2024 prelude migration. (rust-lang/edition-guide#314) ## rust-lang/nomicon 3 commits in 0ebdacadbda8ce2cd8fbf93985e15af61a7ab895..6ecf95c5f2bfa0e6314dfe282bf775fd1405f7e9 2024-08-11 16:55:29 UTC to 2024-08-09 23:25:22 UTC - Stabilize `min_exhaustive_patterns` (rust-lang/nomicon#445) - repr(int) enums: both size and sign matter (rust-lang/nomicon#458) - Update what-unsafe-does.md (rust-lang/nomicon#457) ## rust-lang/reference 6 commits in 2e191814f163ee1e77e2d6094eee4dd78a289c5b..62cd0df95061ba0ac886333f5cd7f3012f149da1 2024-08-11 21:06:12 UTC to 2024-07-30 06:34:03 UTC - Reformat (and only reformat) the inline assembly chapter (rust-lang/reference#1550) - Changes for unsafe extern blocks (RFC 3484) (rust-lang/reference#1536) - Stabilize Wasm relaxed SIMD (rust-lang/reference#1421) - Remove custom blockquote styling (rust-lang/reference#1547) - Fix std-links for generics with commas. (rust-lang/reference#1549) - Add details on how names are introduced. (rust-lang/reference#1052) ## rust-lang/rust-by-example 3 commits in 89aecb6951b77bc746da73df8c9f2b2ceaad494a..8f94061936e492159f4f6c09c0f917a7521893ff 2024-08-06 17:25:35 UTC to 2024-07-16 20:58:25 UTC - Update lifetime_bounds.md (rust-lang/rust-by-example#1869) - Remove the link to Japanese translation (rust-lang/rust-by-example#1868) - Add an example of implementing the FromStr trait for Circles. (rust-lang/rust-by-example#1865) ## rust-lang/rustc-dev-guide 12 commits in 0c4d55cb59fe440d1a630e4e5774d043968edb3f..43d83780db545a1ed6d45773312fc578987e3968 2024-08-08 17:54:27 UTC to 2024-07-19 07:15:12 UTC - Added 'the' in chapter "Running test" subtitle "Run unit tests on the compiler/library" (rust-lang/rustc-dev-guide#2040) - Correct rust code block in *Dataflow Analysis* (rust-lang/rustc-dev-guide#2037) - linkcheck: fix filtering of the source files (rust-lang/rustc-dev-guide#2019) - chore: fix some comments (rust-lang/rustc-dev-guide#2028) - linkcheck: fix reported broken links (part 2) (rust-lang/rustc-dev-guide#2024) - typo (rust-lang/rustc-dev-guide#2029) - Fix broken links in `llvm-coverage-instrumentation.md` (rust-lang/rustc-dev-guide#2027) - Fix invalid link to toolstate documentation (rust-lang/rustc-dev-guide#2021) - linkcheck: fix reported broken links (part 1) (rust-lang/rustc-dev-guide#2022) - fix link (rust-lang/rustc-dev-guide#2020) - MIR docs: fix borked links and update style (rust-lang/rustc-dev-guide#2017) - Update adding.md (rust-lang/rustc-dev-guide#2016)
rust-timer
added a commit
to rust-lang-ci/rust
that referenced
this pull request
Aug 15, 2024
Rollup merge of rust-lang#129015 - rustbot:docs-update, r=ehuss Update books ## rust-lang/book 7 commits in 67fa536768013d9d5a13f3a06790521d511ef711..04bc1396bb857f35b5dda1d773c9571e1f253304 2024-07-31 13:19:44 UTC to 2024-07-16 18:18:38 UTC - mdbook-trpl-listing: Add missing elided lifetimes (rust-lang/book#3995) - infra: include ghp-import and git push in generate-preview script (rust-lang/book#3998) - infra: add robots.txt for GH Pages previews (rust-lang/book#3997) - Clarify function definitions vs. expressions (rust-lang/book#3870) - infra: fix some shellcheck issues in CI config (rust-lang/book#3988) - infra: support test renderer in mdbook preprocessors (rust-lang/book#3982) - Improve handling of `<Listing>`s (rust-lang/book#3975) ## rust-lang/edition-guide 4 commits in 5454de3d12b9ccc6375b629cf7ccda8264640aac..aeeb287d41a0332c210da122bea8e0e91844ab3e 2024-08-06 21:16:24 UTC to 2024-07-29 21:41:36 UTC - Stabilize unsafe extern blocks (rust-lang/edition-guide#313) - Add chapter for Lifetime Capture Rules 2024 (rust-lang/edition-guide#316) - 2024: Add page for missing_fragment_specifier (rust-lang/edition-guide#315) - Add documentation for 2024 prelude migration. (rust-lang/edition-guide#314) ## rust-lang/nomicon 3 commits in 0ebdacadbda8ce2cd8fbf93985e15af61a7ab895..6ecf95c5f2bfa0e6314dfe282bf775fd1405f7e9 2024-08-11 16:55:29 UTC to 2024-08-09 23:25:22 UTC - Stabilize `min_exhaustive_patterns` (rust-lang/nomicon#445) - repr(int) enums: both size and sign matter (rust-lang/nomicon#458) - Update what-unsafe-does.md (rust-lang/nomicon#457) ## rust-lang/reference 6 commits in 2e191814f163ee1e77e2d6094eee4dd78a289c5b..62cd0df95061ba0ac886333f5cd7f3012f149da1 2024-08-11 21:06:12 UTC to 2024-07-30 06:34:03 UTC - Reformat (and only reformat) the inline assembly chapter (rust-lang/reference#1550) - Changes for unsafe extern blocks (RFC 3484) (rust-lang/reference#1536) - Stabilize Wasm relaxed SIMD (rust-lang/reference#1421) - Remove custom blockquote styling (rust-lang/reference#1547) - Fix std-links for generics with commas. (rust-lang/reference#1549) - Add details on how names are introduced. (rust-lang/reference#1052) ## rust-lang/rust-by-example 3 commits in 89aecb6951b77bc746da73df8c9f2b2ceaad494a..8f94061936e492159f4f6c09c0f917a7521893ff 2024-08-06 17:25:35 UTC to 2024-07-16 20:58:25 UTC - Update lifetime_bounds.md (rust-lang/rust-by-example#1869) - Remove the link to Japanese translation (rust-lang/rust-by-example#1868) - Add an example of implementing the FromStr trait for Circles. (rust-lang/rust-by-example#1865) ## rust-lang/rustc-dev-guide 12 commits in 0c4d55cb59fe440d1a630e4e5774d043968edb3f..43d83780db545a1ed6d45773312fc578987e3968 2024-08-08 17:54:27 UTC to 2024-07-19 07:15:12 UTC - Added 'the' in chapter "Running test" subtitle "Run unit tests on the compiler/library" (rust-lang/rustc-dev-guide#2040) - Correct rust code block in *Dataflow Analysis* (rust-lang/rustc-dev-guide#2037) - linkcheck: fix filtering of the source files (rust-lang/rustc-dev-guide#2019) - chore: fix some comments (rust-lang/rustc-dev-guide#2028) - linkcheck: fix reported broken links (part 2) (rust-lang/rustc-dev-guide#2024) - typo (rust-lang/rustc-dev-guide#2029) - Fix broken links in `llvm-coverage-instrumentation.md` (rust-lang/rustc-dev-guide#2027) - Fix invalid link to toolstate documentation (rust-lang/rustc-dev-guide#2021) - linkcheck: fix reported broken links (part 1) (rust-lang/rustc-dev-guide#2022) - fix link (rust-lang/rustc-dev-guide#2020) - MIR docs: fix borked links and update style (rust-lang/rustc-dev-guide#2017) - Update adding.md (rust-lang/rustc-dev-guide#2016)
bors
added a commit
to rust-lang-ci/rust
that referenced
this pull request
Aug 20, 2024
…=spastorino Stabilize opaque type precise capturing (RFC 3617) This PR partially stabilizes opaque type *precise capturing*, which was specified in [RFC 3617](rust-lang/rfcs#3617), and whose syntax was amended by FCP in [rust-lang#125836](rust-lang#125836). This feature, as stabilized here, gives us a way to explicitly specify the generic lifetime parameters that an RPIT-like opaque type captures. This solves the problem of overcapturing, for lifetime parameters in these opaque types, and will allow the Lifetime Capture Rules 2024 ([RFC 3498](rust-lang/rfcs#3498)) to be fully stabilized for RPIT in Rust 2024. ### What are we stabilizing? This PR stabilizes the use of a `use<'a, T>` bound in return-position impl Trait opaque types. Such a bound fully specifies the set of generic parameters captured by the RPIT opaque type, entirely overriding the implicit default behavior. E.g.: ```rust fn does_not_capture<'a, 'b>() -> impl Sized + use<'a> {} // ~~~~~~~~~~~~~~~~~~~~ // This RPIT opaque type does not capture `'b`. ``` The way we would suggest thinking of `impl Trait` types *without* an explicit `use<..>` bound is that the `use<..>` bound has been *elided*, and that the bound is filled in automatically by the compiler according to the edition-specific capture rules. All non-`'static` lifetime parameters, named (i.e. non-APIT) type parameters, and const parameters in scope are valid to name, including an elided lifetime if such a lifetime would also be valid in an outlives bound, e.g.: ```rust fn elided(x: &u8) -> impl Sized + use<'_> { x } ``` Lifetimes must be listed before type and const parameters, but otherwise the ordering is not relevant to the `use<..>` bound. Captured parameters may not be duplicated. For now, only one `use<..>` bound may appear in a bounds list. It may appear anywhere within the bounds list. ### How does this differ from the RFC? This stabilization differs from the RFC in one respect: the RFC originally specified `use<'a, T>` as syntactically part of the RPIT type itself, e.g.: ```rust fn capture<'a>() -> impl use<'a> Sized {} ``` However, settling on the final syntax was left as an open question. T-lang later decided via FCP in [rust-lang#125836](rust-lang#125836) to treat `use<..>` as a syntactic bound instead, e.g.: ```rust fn capture<'a>() -> impl Sized + use<'a> {} ``` ### What aren't we stabilizing? The key goal of this PR is to stabilize the parts of *precise capturing* that are needed to enable the migration to Rust 2024. There are some capabilities of *precise capturing* that the RFC specifies but that we're not stabilizing here, as these require further work on the type system. We hope to lift these limitations later. The limitations that are part of this PR were specified in the [RFC's stabilization strategy](https://rust-lang.github.io/rfcs/3617-precise-capturing.html#stabilization-strategy). #### Not capturing type or const parameters The RFC addresses the overcapturing of type and const parameters; that is, it allows for them to not be captured in opaque types. We're not stabilizing that in this PR. Since all in scope generic type and const parameters are implicitly captured in all editions, this is not needed for the migration to Rust 2024. For now, when using `use<..>`, all in scope type and const parameters must be nameable (i.e., APIT cannot be used) and included as arguments. For example, this is an error because `T` is in scope and not included as an argument: ```rust fn test<T>() -> impl Sized + use<> {} //~^ ERROR `impl Trait` must mention all type parameters in scope in `use<...>` ``` This is due to certain current limitations in the type system related to how generic parameters are represented as captured (i.e. bivariance) and how inference operates. We hope to relax this in the future, and this stabilization is forward compatible with doing so. #### Precise capturing for return-position impl Trait **in trait** (RPITIT) The RFC specifies precise capturing for RPITIT. We're not stabilizing that in this PR. Since RPITIT already adheres to the Lifetime Capture Rules 2024, this isn't needed for the migration to Rust 2024. The effect of this is that the anonymous associated types created by RPITITs must continue to capture all of the lifetime parameters in scope, e.g.: ```rust trait Foo<'a> { fn test() -> impl Sized + use<Self>; //~^ ERROR `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits } ``` To allow this involves a meaningful amount of type system work related to adding variance to GATs or reworking how generics are represented in RPITITs. We plan to do this work separately from the stabilization. See: - rust-lang#124029 Supporting precise capturing for RPITIT will also require us to implement a new algorithm for detecting refining capture behavior. This may involve looking through type parameters to detect cases where the impl Trait type in an implementation captures fewer lifetimes than the corresponding RPITIT in the trait definition, e.g.: ```rust trait Foo { fn rpit() -> impl Sized + use<Self>; } impl<'a> Foo for &'a () { // This is "refining" due to not capturing `'a` which // is implied by the trait's `use<Self>`. fn rpit() -> impl Sized + use<>; // This is not "refining". fn rpit() -> impl Sized + use<'a>; } ``` This stabilization is forward compatible with adding support for this later. ### The technical details This bound is purely syntactical and does not lower to a [`Clause`](https://doc.rust-lang.org/1.79.0/nightly-rustc/rustc_middle/ty/type.ClauseKind.html) in the type system. For the purposes of the type system (and for the types team's curiosity regarding this stabilization), we have no current need to represent this as a `ClauseKind`. Since opaques already capture a variable set of lifetimes depending on edition and their syntactical position (e.g. RPIT vs RPITIT), a `use<..>` bound is just a way to explicitly rather than implicitly specify that set of lifetimes, and this only affects opaque type lowering from AST to HIR. ### FCP plan While there's much discussion of the type system here, the feature in this PR is implemented internally as a transformation that happens before lowering to the type system layer. We already support impl Trait types partially capturing the in scope lifetimes; we just currently only expose that implicitly. So, in my (errs's) view as a types team member, there's nothing for types to weigh in on here with respect to the implementation being stabilized, and I'd suggest a lang-only proposed FCP (though we'll of course CC the team below). ### Authorship and acknowledgments This stabilization report was coauthored by compiler-errors and TC. TC would like to acknowledge the outstanding and speedy work that compiler-errors has done to make this feature happen. compiler-errors thanks TC for authoring the RFC, for all of his involvement in this feature's development, and pushing the Rust 2024 edition forward. ### Open items We're doing some things in parallel here. In signaling the intention to stabilize, we want to uncover any latent issues so we can be sure they get addressed. We want to give the maximum time for discussion here to happen by starting it while other remaining miscellaneous work proceeds. That work includes: - [x] Look into `syn` support. - dtolnay/syn#1677 - dtolnay/syn#1707 - [x] Look into `rustfmt` support. - rust-lang#126754 - [x] Look into `rust-analyzer` support. - rust-lang/rust-analyzer#17598 - rust-lang/rust-analyzer#17676 - [x] Look into `rustdoc` support. - rust-lang#127228 - rust-lang#127632 - rust-lang#127658 - [x] Suggest this feature to RfL (a known nightly user). - [x] Add a chapter to the edition guide. - rust-lang/edition-guide#316 - [x] Update the Reference. - rust-lang/reference#1577 ### (Selected) implementation history * rust-lang/rfcs#3498 * rust-lang/rfcs#3617 * rust-lang#123468 * rust-lang#125836 * rust-lang#126049 * rust-lang#126753 Closes rust-lang#123432. cc `@rust-lang/lang` `@rust-lang/types` `@rustbot` labels +T-lang +I-lang-nominated +A-impl-trait +F-precise_capturing Tracking: - rust-lang#123432 ---- For the compiler reviewer, I'll leave some inline comments about diagnostics fallout :^) r? compiler
bors
added a commit
to rust-lang-ci/rust
that referenced
this pull request
Aug 20, 2024
…=spastorino Stabilize opaque type precise capturing (RFC 3617) This PR partially stabilizes opaque type *precise capturing*, which was specified in [RFC 3617](rust-lang/rfcs#3617), and whose syntax was amended by FCP in [rust-lang#125836](rust-lang#125836). This feature, as stabilized here, gives us a way to explicitly specify the generic lifetime parameters that an RPIT-like opaque type captures. This solves the problem of overcapturing, for lifetime parameters in these opaque types, and will allow the Lifetime Capture Rules 2024 ([RFC 3498](rust-lang/rfcs#3498)) to be fully stabilized for RPIT in Rust 2024. ### What are we stabilizing? This PR stabilizes the use of a `use<'a, T>` bound in return-position impl Trait opaque types. Such a bound fully specifies the set of generic parameters captured by the RPIT opaque type, entirely overriding the implicit default behavior. E.g.: ```rust fn does_not_capture<'a, 'b>() -> impl Sized + use<'a> {} // ~~~~~~~~~~~~~~~~~~~~ // This RPIT opaque type does not capture `'b`. ``` The way we would suggest thinking of `impl Trait` types *without* an explicit `use<..>` bound is that the `use<..>` bound has been *elided*, and that the bound is filled in automatically by the compiler according to the edition-specific capture rules. All non-`'static` lifetime parameters, named (i.e. non-APIT) type parameters, and const parameters in scope are valid to name, including an elided lifetime if such a lifetime would also be valid in an outlives bound, e.g.: ```rust fn elided(x: &u8) -> impl Sized + use<'_> { x } ``` Lifetimes must be listed before type and const parameters, but otherwise the ordering is not relevant to the `use<..>` bound. Captured parameters may not be duplicated. For now, only one `use<..>` bound may appear in a bounds list. It may appear anywhere within the bounds list. ### How does this differ from the RFC? This stabilization differs from the RFC in one respect: the RFC originally specified `use<'a, T>` as syntactically part of the RPIT type itself, e.g.: ```rust fn capture<'a>() -> impl use<'a> Sized {} ``` However, settling on the final syntax was left as an open question. T-lang later decided via FCP in [rust-lang#125836](rust-lang#125836) to treat `use<..>` as a syntactic bound instead, e.g.: ```rust fn capture<'a>() -> impl Sized + use<'a> {} ``` ### What aren't we stabilizing? The key goal of this PR is to stabilize the parts of *precise capturing* that are needed to enable the migration to Rust 2024. There are some capabilities of *precise capturing* that the RFC specifies but that we're not stabilizing here, as these require further work on the type system. We hope to lift these limitations later. The limitations that are part of this PR were specified in the [RFC's stabilization strategy](https://rust-lang.github.io/rfcs/3617-precise-capturing.html#stabilization-strategy). #### Not capturing type or const parameters The RFC addresses the overcapturing of type and const parameters; that is, it allows for them to not be captured in opaque types. We're not stabilizing that in this PR. Since all in scope generic type and const parameters are implicitly captured in all editions, this is not needed for the migration to Rust 2024. For now, when using `use<..>`, all in scope type and const parameters must be nameable (i.e., APIT cannot be used) and included as arguments. For example, this is an error because `T` is in scope and not included as an argument: ```rust fn test<T>() -> impl Sized + use<> {} //~^ ERROR `impl Trait` must mention all type parameters in scope in `use<...>` ``` This is due to certain current limitations in the type system related to how generic parameters are represented as captured (i.e. bivariance) and how inference operates. We hope to relax this in the future, and this stabilization is forward compatible with doing so. #### Precise capturing for return-position impl Trait **in trait** (RPITIT) The RFC specifies precise capturing for RPITIT. We're not stabilizing that in this PR. Since RPITIT already adheres to the Lifetime Capture Rules 2024, this isn't needed for the migration to Rust 2024. The effect of this is that the anonymous associated types created by RPITITs must continue to capture all of the lifetime parameters in scope, e.g.: ```rust trait Foo<'a> { fn test() -> impl Sized + use<Self>; //~^ ERROR `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits } ``` To allow this involves a meaningful amount of type system work related to adding variance to GATs or reworking how generics are represented in RPITITs. We plan to do this work separately from the stabilization. See: - rust-lang#124029 Supporting precise capturing for RPITIT will also require us to implement a new algorithm for detecting refining capture behavior. This may involve looking through type parameters to detect cases where the impl Trait type in an implementation captures fewer lifetimes than the corresponding RPITIT in the trait definition, e.g.: ```rust trait Foo { fn rpit() -> impl Sized + use<Self>; } impl<'a> Foo for &'a () { // This is "refining" due to not capturing `'a` which // is implied by the trait's `use<Self>`. fn rpit() -> impl Sized + use<>; // This is not "refining". fn rpit() -> impl Sized + use<'a>; } ``` This stabilization is forward compatible with adding support for this later. ### The technical details This bound is purely syntactical and does not lower to a [`Clause`](https://doc.rust-lang.org/1.79.0/nightly-rustc/rustc_middle/ty/type.ClauseKind.html) in the type system. For the purposes of the type system (and for the types team's curiosity regarding this stabilization), we have no current need to represent this as a `ClauseKind`. Since opaques already capture a variable set of lifetimes depending on edition and their syntactical position (e.g. RPIT vs RPITIT), a `use<..>` bound is just a way to explicitly rather than implicitly specify that set of lifetimes, and this only affects opaque type lowering from AST to HIR. ### FCP plan While there's much discussion of the type system here, the feature in this PR is implemented internally as a transformation that happens before lowering to the type system layer. We already support impl Trait types partially capturing the in scope lifetimes; we just currently only expose that implicitly. So, in my (errs's) view as a types team member, there's nothing for types to weigh in on here with respect to the implementation being stabilized, and I'd suggest a lang-only proposed FCP (though we'll of course CC the team below). ### Authorship and acknowledgments This stabilization report was coauthored by compiler-errors and TC. TC would like to acknowledge the outstanding and speedy work that compiler-errors has done to make this feature happen. compiler-errors thanks TC for authoring the RFC, for all of his involvement in this feature's development, and pushing the Rust 2024 edition forward. ### Open items We're doing some things in parallel here. In signaling the intention to stabilize, we want to uncover any latent issues so we can be sure they get addressed. We want to give the maximum time for discussion here to happen by starting it while other remaining miscellaneous work proceeds. That work includes: - [x] Look into `syn` support. - dtolnay/syn#1677 - dtolnay/syn#1707 - [x] Look into `rustfmt` support. - rust-lang#126754 - [x] Look into `rust-analyzer` support. - rust-lang/rust-analyzer#17598 - rust-lang/rust-analyzer#17676 - [x] Look into `rustdoc` support. - rust-lang#127228 - rust-lang#127632 - rust-lang#127658 - [x] Suggest this feature to RfL (a known nightly user). - [x] Add a chapter to the edition guide. - rust-lang/edition-guide#316 - [x] Update the Reference. - rust-lang/reference#1577 ### (Selected) implementation history * rust-lang/rfcs#3498 * rust-lang/rfcs#3617 * rust-lang#123468 * rust-lang#125836 * rust-lang#126049 * rust-lang#126753 Closes rust-lang#123432. cc `@rust-lang/lang` `@rust-lang/types` `@rustbot` labels +T-lang +I-lang-nominated +A-impl-trait +F-precise_capturing Tracking: - rust-lang#123432 ---- For the compiler reviewer, I'll leave some inline comments about diagnostics fallout :^) r? compiler
10 tasks
github-actions bot
pushed a commit
to rust-lang/miri
that referenced
this pull request
Aug 26, 2024
Stabilize opaque type precise capturing (RFC 3617) This PR partially stabilizes opaque type *precise capturing*, which was specified in [RFC 3617](rust-lang/rfcs#3617), and whose syntax was amended by FCP in [#125836](rust-lang/rust#125836). This feature, as stabilized here, gives us a way to explicitly specify the generic lifetime parameters that an RPIT-like opaque type captures. This solves the problem of overcapturing, for lifetime parameters in these opaque types, and will allow the Lifetime Capture Rules 2024 ([RFC 3498](rust-lang/rfcs#3498)) to be fully stabilized for RPIT in Rust 2024. ### What are we stabilizing? This PR stabilizes the use of a `use<'a, T>` bound in return-position impl Trait opaque types. Such a bound fully specifies the set of generic parameters captured by the RPIT opaque type, entirely overriding the implicit default behavior. E.g.: ```rust fn does_not_capture<'a, 'b>() -> impl Sized + use<'a> {} // ~~~~~~~~~~~~~~~~~~~~ // This RPIT opaque type does not capture `'b`. ``` The way we would suggest thinking of `impl Trait` types *without* an explicit `use<..>` bound is that the `use<..>` bound has been *elided*, and that the bound is filled in automatically by the compiler according to the edition-specific capture rules. All non-`'static` lifetime parameters, named (i.e. non-APIT) type parameters, and const parameters in scope are valid to name, including an elided lifetime if such a lifetime would also be valid in an outlives bound, e.g.: ```rust fn elided(x: &u8) -> impl Sized + use<'_> { x } ``` Lifetimes must be listed before type and const parameters, but otherwise the ordering is not relevant to the `use<..>` bound. Captured parameters may not be duplicated. For now, only one `use<..>` bound may appear in a bounds list. It may appear anywhere within the bounds list. ### How does this differ from the RFC? This stabilization differs from the RFC in one respect: the RFC originally specified `use<'a, T>` as syntactically part of the RPIT type itself, e.g.: ```rust fn capture<'a>() -> impl use<'a> Sized {} ``` However, settling on the final syntax was left as an open question. T-lang later decided via FCP in [#125836](rust-lang/rust#125836) to treat `use<..>` as a syntactic bound instead, e.g.: ```rust fn capture<'a>() -> impl Sized + use<'a> {} ``` ### What aren't we stabilizing? The key goal of this PR is to stabilize the parts of *precise capturing* that are needed to enable the migration to Rust 2024. There are some capabilities of *precise capturing* that the RFC specifies but that we're not stabilizing here, as these require further work on the type system. We hope to lift these limitations later. The limitations that are part of this PR were specified in the [RFC's stabilization strategy](https://rust-lang.github.io/rfcs/3617-precise-capturing.html#stabilization-strategy). #### Not capturing type or const parameters The RFC addresses the overcapturing of type and const parameters; that is, it allows for them to not be captured in opaque types. We're not stabilizing that in this PR. Since all in scope generic type and const parameters are implicitly captured in all editions, this is not needed for the migration to Rust 2024. For now, when using `use<..>`, all in scope type and const parameters must be nameable (i.e., APIT cannot be used) and included as arguments. For example, this is an error because `T` is in scope and not included as an argument: ```rust fn test<T>() -> impl Sized + use<> {} //~^ ERROR `impl Trait` must mention all type parameters in scope in `use<...>` ``` This is due to certain current limitations in the type system related to how generic parameters are represented as captured (i.e. bivariance) and how inference operates. We hope to relax this in the future, and this stabilization is forward compatible with doing so. #### Precise capturing for return-position impl Trait **in trait** (RPITIT) The RFC specifies precise capturing for RPITIT. We're not stabilizing that in this PR. Since RPITIT already adheres to the Lifetime Capture Rules 2024, this isn't needed for the migration to Rust 2024. The effect of this is that the anonymous associated types created by RPITITs must continue to capture all of the lifetime parameters in scope, e.g.: ```rust trait Foo<'a> { fn test() -> impl Sized + use<Self>; //~^ ERROR `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits } ``` To allow this involves a meaningful amount of type system work related to adding variance to GATs or reworking how generics are represented in RPITITs. We plan to do this work separately from the stabilization. See: - rust-lang/rust#124029 Supporting precise capturing for RPITIT will also require us to implement a new algorithm for detecting refining capture behavior. This may involve looking through type parameters to detect cases where the impl Trait type in an implementation captures fewer lifetimes than the corresponding RPITIT in the trait definition, e.g.: ```rust trait Foo { fn rpit() -> impl Sized + use<Self>; } impl<'a> Foo for &'a () { // This is "refining" due to not capturing `'a` which // is implied by the trait's `use<Self>`. fn rpit() -> impl Sized + use<>; // This is not "refining". fn rpit() -> impl Sized + use<'a>; } ``` This stabilization is forward compatible with adding support for this later. ### The technical details This bound is purely syntactical and does not lower to a [`Clause`](https://doc.rust-lang.org/1.79.0/nightly-rustc/rustc_middle/ty/type.ClauseKind.html) in the type system. For the purposes of the type system (and for the types team's curiosity regarding this stabilization), we have no current need to represent this as a `ClauseKind`. Since opaques already capture a variable set of lifetimes depending on edition and their syntactical position (e.g. RPIT vs RPITIT), a `use<..>` bound is just a way to explicitly rather than implicitly specify that set of lifetimes, and this only affects opaque type lowering from AST to HIR. ### FCP plan While there's much discussion of the type system here, the feature in this PR is implemented internally as a transformation that happens before lowering to the type system layer. We already support impl Trait types partially capturing the in scope lifetimes; we just currently only expose that implicitly. So, in my (errs's) view as a types team member, there's nothing for types to weigh in on here with respect to the implementation being stabilized, and I'd suggest a lang-only proposed FCP (though we'll of course CC the team below). ### Authorship and acknowledgments This stabilization report was coauthored by compiler-errors and TC. TC would like to acknowledge the outstanding and speedy work that compiler-errors has done to make this feature happen. compiler-errors thanks TC for authoring the RFC, for all of his involvement in this feature's development, and pushing the Rust 2024 edition forward. ### Open items We're doing some things in parallel here. In signaling the intention to stabilize, we want to uncover any latent issues so we can be sure they get addressed. We want to give the maximum time for discussion here to happen by starting it while other remaining miscellaneous work proceeds. That work includes: - [x] Look into `syn` support. - dtolnay/syn#1677 - dtolnay/syn#1707 - [x] Look into `rustfmt` support. - rust-lang/rust#126754 - [x] Look into `rust-analyzer` support. - rust-lang/rust-analyzer#17598 - rust-lang/rust-analyzer#17676 - [x] Look into `rustdoc` support. - rust-lang/rust#127228 - rust-lang/rust#127632 - rust-lang/rust#127658 - [x] Suggest this feature to RfL (a known nightly user). - [x] Add a chapter to the edition guide. - rust-lang/edition-guide#316 - [x] Update the Reference. - rust-lang/reference#1577 ### (Selected) implementation history * rust-lang/rfcs#3498 * rust-lang/rfcs#3617 * rust-lang/rust#123468 * rust-lang/rust#125836 * rust-lang/rust#126049 * rust-lang/rust#126753 Closes #123432. cc `@rust-lang/lang` `@rust-lang/types` `@rustbot` labels +T-lang +I-lang-nominated +A-impl-trait +F-precise_capturing Tracking: - rust-lang/rust#123432 ---- For the compiler reviewer, I'll leave some inline comments about diagnostics fallout :^) r? compiler
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Let's describe the changes to the opaque type lifetime capture rules in some detail.
To do this, we first describe precise capturing, as we'll use that syntax both for describing the meaning of capturing and to describe the migration steps.
Arguably, some of what we describe isn't strictly tied to the edition. People could migrate to the
use<..>
syntax in any edition. However, this is all part of the same change, both conceptually and practically, so it's better to just describe this in one place.cc @compiler-errors
Tracking:
precise_capturing
syntax rust#123432