-
Notifications
You must be signed in to change notification settings - Fork 13.8k
add CloneFromCell and Cell::get_cloned #145685
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
Conversation
fe78582
to
dd990a7
Compare
This comment has been minimized.
This comment has been minimized.
dd990a7
to
9c8de73
Compare
@rustbot ready (unless the CI fails) |
library/core/src/cell.rs
Outdated
/// Types that can be cloned from a copy of the value. | ||
/// | ||
/// # Safety | ||
/// | ||
/// Implementing this trait is safe for any type that can be safely bitwise copied. | ||
#[unstable(feature = "cell_get_cloned", issue = "145329")] | ||
// Allow potential overlapping implementations in user code | ||
#[marker] | ||
pub unsafe trait CloneFromCopy: Clone {} |
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.
The docs and safety comment don't quite cover it; moves are bitwise copies, and of course that can be cloned as well as the original. Copy
really just means that a bitwise copy doesn't invalidate the original. I'm not sure what the exact preconditions are here though, in most cases isn't this just something like Freeze + Unpin
?
I'm sure I am missing something, cc @programmerjake
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.
the idea is that if you have &Cell<T>
it's unsound to call T::clone
on that reference for generic T
since it could contain references to the same &Cell<T>
which allows it to modify T
while a &T
was passed to clone
. So, instead, we do a bitwise copy of T
to a another memory location that isn't aliased and call T::clone
on that, making sure to forget the bitwise copy using something like ManuallyDrop
. not all types are safe to just outright bitwise copy while the original is still valid (e.g. doing a bitwise copy on T = Cell<Option<String>>
allows you to drop the String
twice by taking it from the copy and from the original Cell<Cell<Option<String>>>
).
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.
T: CloneFromCopy
means the following code is sound:
pub fn clone_from_copy<T: CloneFromCopy>(v: &Cell<T>) -> T {
let copy = unsafe { ManuallyDrop::new(ptr::read(v).into_inner()) };
T::clone(©)
}
To put the above into preconditions, @rustbot author |
Reminder, once the PR becomes ready for a review, use |
9c8de73
to
0e2d70c
Compare
@rustbot ready |
library/core/src/cell.rs
Outdated
/// | ||
/// # Safety | ||
/// | ||
/// Implementing this trait is safe for any type that can be safely bitwise copied while the |
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.
sorry I wasn't very clear before: it's important to not drop the bitwise copy, otherwise it's not safe to impl for Rc
and other reference-counted types:
fn f(v: &Cell<Rc<u8>>) -> Rc<u8>
where
Rc<u8>: CloneFromCopy,
{
// Safety: this is unsound, but CloneFromCopy's current wording implies this is fine:
let copy = unsafe { ptr::read(v.as_ptr()) };
let retval = copy.clone();
drop(copy);
retval
}
fn cause_use_after_free() {
let a = Cell::new(Rc::new(0u8));
let b = f(&a); // f clones once and drops once so reference count is 1
drop(a); // reference count is now 0, backing memory is freed
dbg!(b); // use after free, this is UB
}
(I'll effectively delegate this review to Jake) @rustbot author |
0e2d70c
to
ef2f42b
Compare
@rustbot ready |
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.
generally looks good, though I think we should wait and see if we can't do: #145329 (comment) (edit: we can't)
901f49a
to
08b4641
Compare
Thanks Jacob for reviewing. @bors r=programmerjake,tgross35 rollup |
…mmerjake,tgross35 add CloneFromCell and Cell::get_cloned Tracking issue: rust-lang#145329
Rollup of 14 pull requests Successful merges: - #142670 (Document fully-qualified syntax in `as`' keyword doc) - #144908 (Fix doctest output json) - #145685 (add CloneFromCell and Cell::get_cloned) - #146330 (Bump unicode_data and printables to version 17.0.0) - #146451 (Fix atan2 inaccuracy in documentation) - #146479 (add mem::conjure_zst) - #147190 (std: `sys::net` cleanups) - #147245 (only replace the intended comma in pattern suggestions) - #147251 (Do not assert that a change in global cache only happens when concurrent) - #147269 (Add regression test for 123953) - #147277 (Extract common logic for iterating over features) - #147280 (Return to needs-llvm-components being info-only) - #147292 (Respect `-Z` unstable options in `rustdoc --test`) - #147300 (Add xtensa arch to object file creation) r? `@ghost` `@rustbot` modify labels: rollup
…mmerjake,tgross35 add CloneFromCell and Cell::get_cloned Tracking issue: rust-lang#145329
…mmerjake,tgross35 add CloneFromCell and Cell::get_cloned Tracking issue: rust-lang#145329
…mmerjake,tgross35 add CloneFromCell and Cell::get_cloned Tracking issue: rust-lang#145329
…mmerjake,tgross35 add CloneFromCell and Cell::get_cloned Tracking issue: rust-lang#145329
Rollup of 14 pull requests Successful merges: - #142670 (Document fully-qualified syntax in `as`' keyword doc) - #145685 (add CloneFromCell and Cell::get_cloned) - #146330 (Bump unicode_data and printables to version 17.0.0) - #146451 (Fix atan2 inaccuracy in documentation) - #146479 (add mem::conjure_zst) - #146874 (compiler: Hint at multiple crate versions if trait impl is for wrong ADT ) - #147117 (interpret `#[used]` as `#[used(compiler)]` on illumos) - #147190 (std: `sys::net` cleanups) - #147251 (Do not assert that a change in global cache only happens when concurrent) - #147280 (Return to needs-llvm-components being info-only) - #147288 (compiletest: Make `DirectiveLine` responsible for name/value splitting) - #147309 (Add documentation about unwinding to wasm targets) - #147315 (bless autodiff batching test) - #147323 (Fix top level ui tests check in tidy) r? `@ghost` `@rustbot` modify labels: rollup
…mmerjake,tgross35 add CloneFromCell and Cell::get_cloned Tracking issue: rust-lang#145329
Rollup of 11 pull requests Successful merges: - #142670 (Document fully-qualified syntax in `as`' keyword doc) - #145685 (add CloneFromCell and Cell::get_cloned) - #146330 (Bump unicode_data and printables to version 17.0.0) - #146451 (Fix atan2 inaccuracy in documentation) - #146479 (add mem::conjure_zst) - #147117 (interpret `#[used]` as `#[used(compiler)]` on illumos) - #147190 (std: `sys::net` cleanups) - #147251 (Do not assert that a change in global cache only happens when concurrent) - #147280 (Return to needs-llvm-components being info-only) - #147288 (compiletest: Make `DirectiveLine` responsible for name/value splitting) - #147315 (bless autodiff batching test) r? `@ghost` `@rustbot` modify labels: rollup
…mmerjake,tgross35 add CloneFromCell and Cell::get_cloned Tracking issue: rust-lang#145329
Rollup of 10 pull requests Successful merges: - #142670 (Document fully-qualified syntax in `as`' keyword doc) - #145685 (add CloneFromCell and Cell::get_cloned) - #146330 (Bump unicode_data and printables to version 17.0.0) - #146451 (Fix atan2 inaccuracy in documentation) - #146479 (add mem::conjure_zst) - #147117 (interpret `#[used]` as `#[used(compiler)]` on illumos) - #147190 (std: `sys::net` cleanups) - #147251 (Do not assert that a change in global cache only happens when concurrent) - #147280 (Return to needs-llvm-components being info-only) - #147315 (bless autodiff batching test) r? `@ghost` `@rustbot` modify labels: rollup
Tracking issue: #145329