-
Notifications
You must be signed in to change notification settings - Fork 13.7k
Experiment: Reborrow trait #145726
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
Merged
Merged
Experiment: Reborrow trait #145726
+30
−0
Conversation
This file contains hidden or 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
rustbot has assigned @petrochenkov. Use |
This experiment has a tracking issue (#145612) and a lang team champion, so it's good to land from a lang perspective. |
@bors r+ rollup |
jhpratt
added a commit
to jhpratt/rust
that referenced
this pull request
Aug 22, 2025
… r=petrochenkov Experiment: Reborrow trait Tracking issue: rust-lang#145612 Starting off really small here: just introduce the unstable feature and the feature gate, and one of the two traits that the Reborrow experiment deals with. ### Cliff-notes explanation The `Reborrow` trait is conceptually a close cousin of `Copy` with the exception that it disables the source (`self`) for the lifetime of the target / result of the reborrow action. It can be viewed as a method of `fn reborrow(self: Self<'a>) -> Self<'a>` with the compiler adding tracking of the resulting `Self<'a>` (or any value derived from it that retains the `'a` lifetime) to keep the `self` disabled for reads and writes. No method is planned to be surfaced to the user, however, as reborrowing cannot be seen in code (except for method calls [`a.foo()` reborrows `a`] and explicit reborrows [`&*a`]) and thus triggering user-code in it could be viewed as "spooky action at a distance". Furthermore, the added compiler tracking cannot be seen on the method itself, violating the Golden Rule. Note that the userland "reborrow" method is not True Reborrowing, but rather a form of a "Fancy Deref": ```rust fn reborrow(&'short self: Self<'long>) -> Self<'short>; ``` The lifetime shortening is the issue here: a reborrowed `Self` or any value derived from it is bound to the method that called `reborrow`, since `&'short` is effectively a local variable. True Reborrowing does not shorten the lifetime of the result. To avoid having to introduce new kinds of references, new kinds of lifetime annotations, or a blessed trait method, no method will be introduced at all. Instead, the `Reborrow` trait is intended to be a derived trait that effectively reborrows each field individually; `Copy` fields end up just copying, while fields that themselves `Reborrow` get disabled in the source, usually leading to the source itself being disabled (some differences may appear with structs that contain multiple reborrowable fields). The goal of the experiment is to determine how the actual implementation here will shape out, and what the "bottom case" for the recursive / deriving `Reborrow` is. `Reborrow` has a friend trait, `CoerceShared`, which is equivalent to a `&'a mut T -> &'a T` conversion. This is needed as a different trait and different operation due to the different semantics it enforces on the source: a `CoerceShared` operation only disables the source for writes / exclusive access for the lifetime of the result. That trait is not yet introduced in this PR, though there is no particular reason why it could not be introduced.
bors
added a commit
that referenced
this pull request
Aug 23, 2025
Rollup of 20 pull requests Successful merges: - #132087 (Fix overly restrictive lifetime in `core::panic::Location::file` return type) - #137396 (Recover `param: Ty = EXPR`) - #142185 (Convert moves of references to copies in ReferencePropagation) - #144443 (Make target pointer width in target json an integer) - #144648 (Implementation: `#[feature(nonpoison_rwlock)]`) - #144897 (print raw lifetime idents with r#) - #145218 ([Debuginfo] improve enum value formatting in LLDB for better readability) - #145380 (Add codegen-llvm regression tests) - #145573 (Add an experimental unsafe(force_target_feature) attribute.) - #145597 (resolve: Remove `ScopeSet::Late`) - #145641 (On E0277, point at type that doesn't implement bound) - #145669 (rustdoc-search: GUI tests check for `//` in URL) - #145695 (Introduce ProjectionElem::try_map.) - #145710 (Fix the ABI parameter inconsistency issue in debug.rs for LoongArch64) - #145726 (Experiment: Reborrow trait) - #145731 (Make raw pointers work in type-based search) - #145736 (triagebot: Update style team reviewers) - #145738 (Uplift rustc_mir_transform::coverage::counters::union_find to rustc_data_structures.) - #145743 (doc: fix some typos in comment) - #145745 (tests: Ignore basic-stepping.rs on LoongArch) Failed merges: - #145670 (port `sanitize` attribute to the new parsing infrastructure) r? `@ghost` `@rustbot` modify labels: rollup
bors
added a commit
that referenced
this pull request
Aug 23, 2025
Rollup of 28 pull requests Successful merges: - #132087 (Fix overly restrictive lifetime in `core::panic::Location::file` return type) - #137396 (Recover `param: Ty = EXPR`) - #137457 (Fix host code appearing in Wasm binaries) - #142185 (Convert moves of references to copies in ReferencePropagation) - #144648 (Implementation: `#[feature(nonpoison_rwlock)]`) - #144897 (print raw lifetime idents with r#) - #145218 ([Debuginfo] improve enum value formatting in LLDB for better readability) - #145380 (Add codegen-llvm regression tests) - #145573 (Add an experimental unsafe(force_target_feature) attribute.) - #145597 (resolve: Remove `ScopeSet::Late`) - #145633 (Fix some typos in LocalKey documentation) - #145641 (On E0277, point at type that doesn't implement bound) - #145669 (rustdoc-search: GUI tests check for `//` in URL) - #145695 (Introduce ProjectionElem::try_map.) - #145710 (Fix the ABI parameter inconsistency issue in debug.rs for LoongArch64) - #145726 (Experiment: Reborrow trait) - #145731 (Make raw pointers work in type-based search) - #145736 (triagebot: Update style team reviewers) - #145738 (Uplift rustc_mir_transform::coverage::counters::union_find to rustc_data_structures.) - #145742 (rustdoc js: Even more typechecking improvments ) - #145743 (doc: fix some typos in comment) - #145745 (tests: Ignore basic-stepping.rs on LoongArch) - #145747 (Refactor lint buffering to avoid requiring a giant enum) - #145751 (fix(lexer): Allow '-' in the frontmatter infostring continue set) - #145761 (Add aarch64_be-unknown-hermit target) - #145762 (convert strings to symbols in attr diagnostics) - #145763 (Ship LLVM tools for the correct target when cross-compiling) - #145765 (Revert suggestions for missing methods in tuples) r? `@ghost` `@rustbot` modify labels: rollup
rust-timer
added a commit
that referenced
this pull request
Aug 23, 2025
Rollup merge of #145726 - aapoalas:reborrow-lang-experiment, r=petrochenkov Experiment: Reborrow trait Tracking issue: #145612 Starting off really small here: just introduce the unstable feature and the feature gate, and one of the two traits that the Reborrow experiment deals with. ### Cliff-notes explanation The `Reborrow` trait is conceptually a close cousin of `Copy` with the exception that it disables the source (`self`) for the lifetime of the target / result of the reborrow action. It can be viewed as a method of `fn reborrow(self: Self<'a>) -> Self<'a>` with the compiler adding tracking of the resulting `Self<'a>` (or any value derived from it that retains the `'a` lifetime) to keep the `self` disabled for reads and writes. No method is planned to be surfaced to the user, however, as reborrowing cannot be seen in code (except for method calls [`a.foo()` reborrows `a`] and explicit reborrows [`&*a`]) and thus triggering user-code in it could be viewed as "spooky action at a distance". Furthermore, the added compiler tracking cannot be seen on the method itself, violating the Golden Rule. Note that the userland "reborrow" method is not True Reborrowing, but rather a form of a "Fancy Deref": ```rust fn reborrow(&'short self: Self<'long>) -> Self<'short>; ``` The lifetime shortening is the issue here: a reborrowed `Self` or any value derived from it is bound to the method that called `reborrow`, since `&'short` is effectively a local variable. True Reborrowing does not shorten the lifetime of the result. To avoid having to introduce new kinds of references, new kinds of lifetime annotations, or a blessed trait method, no method will be introduced at all. Instead, the `Reborrow` trait is intended to be a derived trait that effectively reborrows each field individually; `Copy` fields end up just copying, while fields that themselves `Reborrow` get disabled in the source, usually leading to the source itself being disabled (some differences may appear with structs that contain multiple reborrowable fields). The goal of the experiment is to determine how the actual implementation here will shape out, and what the "bottom case" for the recursive / deriving `Reborrow` is. `Reborrow` has a friend trait, `CoerceShared`, which is equivalent to a `&'a mut T -> &'a T` conversion. This is needed as a different trait and different operation due to the different semantics it enforces on the source: a `CoerceShared` operation only disables the source for writes / exclusive access for the lifetime of the result. That trait is not yet introduced in this PR, though there is no particular reason why it could not be introduced.
github-actions bot
pushed a commit
to rust-lang/miri
that referenced
this pull request
Aug 24, 2025
Rollup of 28 pull requests Successful merges: - rust-lang/rust#132087 (Fix overly restrictive lifetime in `core::panic::Location::file` return type) - rust-lang/rust#137396 (Recover `param: Ty = EXPR`) - rust-lang/rust#137457 (Fix host code appearing in Wasm binaries) - rust-lang/rust#142185 (Convert moves of references to copies in ReferencePropagation) - rust-lang/rust#144648 (Implementation: `#[feature(nonpoison_rwlock)]`) - rust-lang/rust#144897 (print raw lifetime idents with r#) - rust-lang/rust#145218 ([Debuginfo] improve enum value formatting in LLDB for better readability) - rust-lang/rust#145380 (Add codegen-llvm regression tests) - rust-lang/rust#145573 (Add an experimental unsafe(force_target_feature) attribute.) - rust-lang/rust#145597 (resolve: Remove `ScopeSet::Late`) - rust-lang/rust#145633 (Fix some typos in LocalKey documentation) - rust-lang/rust#145641 (On E0277, point at type that doesn't implement bound) - rust-lang/rust#145669 (rustdoc-search: GUI tests check for `//` in URL) - rust-lang/rust#145695 (Introduce ProjectionElem::try_map.) - rust-lang/rust#145710 (Fix the ABI parameter inconsistency issue in debug.rs for LoongArch64) - rust-lang/rust#145726 (Experiment: Reborrow trait) - rust-lang/rust#145731 (Make raw pointers work in type-based search) - rust-lang/rust#145736 (triagebot: Update style team reviewers) - rust-lang/rust#145738 (Uplift rustc_mir_transform::coverage::counters::union_find to rustc_data_structures.) - rust-lang/rust#145742 (rustdoc js: Even more typechecking improvments ) - rust-lang/rust#145743 (doc: fix some typos in comment) - rust-lang/rust#145745 (tests: Ignore basic-stepping.rs on LoongArch) - rust-lang/rust#145747 (Refactor lint buffering to avoid requiring a giant enum) - rust-lang/rust#145751 (fix(lexer): Allow '-' in the frontmatter infostring continue set) - rust-lang/rust#145761 (Add aarch64_be-unknown-hermit target) - rust-lang/rust#145762 (convert strings to symbols in attr diagnostics) - rust-lang/rust#145763 (Ship LLVM tools for the correct target when cross-compiling) - rust-lang/rust#145765 (Revert suggestions for missing methods in tuples) r? `@ghost` `@rustbot` modify labels: rollup
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Labels
F-reborrow
`#![feature(reborrow)]`; see #145612
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.
T-libs
Relevant to the library 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.
Tracking issue: #145612
Starting off really small here: just introduce the unstable feature and the feature gate, and one of the two traits that the Reborrow experiment deals with.
Cliff-notes explanation
The
Reborrow
trait is conceptually a close cousin ofCopy
with the exception that it disables the source (self
) for the lifetime of the target / result of the reborrow action. It can be viewed as a method offn reborrow(self: Self<'a>) -> Self<'a>
with the compiler adding tracking of the resultingSelf<'a>
(or any value derived from it that retains the'a
lifetime) to keep theself
disabled for reads and writes.No method is planned to be surfaced to the user, however, as reborrowing cannot be seen in code (except for method calls [
a.foo()
reborrowsa
] and explicit reborrows [&*a
]) and thus triggering user-code in it could be viewed as "spooky action at a distance". Furthermore, the added compiler tracking cannot be seen on the method itself, violating the Golden Rule. Note that the userland "reborrow" method is not True Reborrowing, but rather a form of a "Fancy Deref":The lifetime shortening is the issue here: a reborrowed
Self
or any value derived from it is bound to the method that calledreborrow
, since&'short
is effectively a local variable. True Reborrowing does not shorten the lifetime of the result.To avoid having to introduce new kinds of references, new kinds of lifetime annotations, or a blessed trait method, no method will be introduced at all. Instead, the
Reborrow
trait is intended to be a derived trait that effectively reborrows each field individually;Copy
fields end up just copying, while fields that themselvesReborrow
get disabled in the source, usually leading to the source itself being disabled (some differences may appear with structs that contain multiple reborrowable fields). The goal of the experiment is to determine how the actual implementation here will shape out, and what the "bottom case" for the recursive / derivingReborrow
is.Reborrow
has a friend trait,CoerceShared
, which is equivalent to a&'a mut T -> &'a T
conversion. This is needed as a different trait and different operation due to the different semantics it enforces on the source: aCoerceShared
operation only disables the source for writes / exclusive access for the lifetime of the result. That trait is not yet introduced in this PR, though there is no particular reason why it could not be introduced.