-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
RFC: core::mem::replace_with
for temporarily moving out of ownership.
#1736
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
- Feature Name: mem-replace-with | ||
- Start Date: 2016-09-01 | ||
- RFC PR: (leave this empty) | ||
- Rust Issue: (leave this empty) | ||
|
||
# Summary | ||
[summary]: #summary | ||
|
||
Add a new function to `core::mem` (and thus `std::mem`), `replace_with`, which | ||
invokes a closure that takes temporary ownership over some value behind a | ||
mutable reference. | ||
|
||
This is similar to the functions provided by [the take_mut crate](https://crates.io/crates/take_mut). | ||
|
||
# Motivation | ||
[motivation]: #motivation | ||
|
||
A common pattern, especially for low-level programmers, is to acquire ownership | ||
of a value behind a reference without immediately giving it a replacement value. | ||
|
||
`core::mem::replace_with` allows such thing by generalizing | ||
`core::mem::replace`, to allow the replacement value being generated by a | ||
closure and even depend on the old value. | ||
|
||
Unfortunately, there are no safe implementation in the standard library, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. s/are/is/ to match "implementation". Or alternatively, "the standard library doesn't provide any safe implementation" |
||
leading some Rust users to either reimplement a safe interface for such a | ||
feature (often flawed due to unwinding, see below) or use things like | ||
`ptr::read`. | ||
|
||
This should standardize the ecosystem with respect to that. | ||
|
||
# Detailed design | ||
[design]: #detailed-design | ||
|
||
A complete implementation can be found [here](https://github.com/rust-lang/rust/pull/36186). This implementation is pretty simple, with only one trick which is crucial to safety: handling unwinding. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we just include the code here? The implementation is short, and including makes the RFC self-contained. |
||
|
||
Without handling unwinding, the closure could unwind and invoke destructors on | ||
the invalid value. Thus we use "exit guards" which are placed in the stack | ||
frame (as a variable) and holds a destructor exiting the program. | ||
|
||
This behavior is rather specific and it is not certain that it will be kept in | ||
the future, so we leave the unwinding behavior unspecified for now. | ||
|
||
# Drawbacks | ||
[drawbacks]: #drawbacks | ||
|
||
It expands the core library slightly, and the panic semantics might not be | ||
clear for everyone. | ||
|
||
# Alternatives | ||
[alternatives]: #alternatives | ||
|
||
1. Specify the unwinding behavior to abort. | ||
|
||
2. Use `catch_unwind` and print an error on unwinding (in libstd). | ||
|
||
3. Require `T: Default` and replace the value as such on panic, so we are sure the dropping value is in fact valid. | ||
|
||
4. Leave it out of the standard library. | ||
|
||
# Unresolved questions | ||
[unresolved]: #unresolved-questions | ||
|
||
Are there currently any crates relying on invariants that this will break? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you include a simple example of this pattern and the problem it causes?