-
-
Notifications
You must be signed in to change notification settings - Fork 77
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 cast_{arc,rc}
(and slice and try), and {wrap,peel}_{arc,rc}
.
#132
Conversation
{try_,}cast_{arc,rc}
, and {wrap,peel}_{arc,rc}
.cast_{arc,rc}
(etc.), and {wrap,peel}_{arc,rc}
.
cast_{arc,rc}
(etc.), and {wrap,peel}_{arc,rc}
.cast_{arc,rc}
(and slice and try), and {wrap,peel}_{arc,rc}
.
Note: In safe code, there is no way for a user to observe modifications to a #![feature(get_mut_unchecked)]
use std::rc::Rc;
fn main() {
let a: Rc<bool> = Rc::new(false);
let mut b: Rc<u8> = bytemuck::allocation::cast_rc(a.clone());
unsafe {
let b = Rc::get_mut_unchecked(&mut b);
*b = 2;
}
dbg!(a); // UB: reading 0x02 as bool
} I'll add a note about this to the doc-comment of Alternately, the bounds for (This is not a problem with `Rc::get_mut` or `Rc::make_mut`)use std::rc::Rc;
fn main() {
let a: Rc<bool> = Rc::new(false);
let mut b: Rc<u8> = bytemuck::allocation::cast_rc(a.clone());
drop(a);
*Rc::get_mut(&mut b).unwrap() = 2;
// There is no way to observe 0x02 as bool, becasuse `a` was dropped,
// otherwise get_mut would have returned None
let c: Rc<bool> = Rc::new(false);
let mut d: Rc<u8> = bytemuck::allocation::cast_rc(c.clone());
*Rc::make_mut(&mut d) = 2;
// There is no way to observe 0x02 as bool, becasuse the value in `d`
// was cloned.
assert_eq!(*c, false);
} |
We need the stronger bounds. Because an Rc puts a value "in two places", we have to basically act like the cast is going in both directions at once. |
…xistence of `Rc::get_mut_unchecked`.
3c50442
to
ca54869
Compare
Okay, I changed the bounds to |
I completely thought that Rc let you mutate the value with some sort of |
My main concern with this is that the API is very quickly becoming very large. You have I imagine that there is a more concise trait-based solution hidden inside all of this code duplication. |
I do share the concern about duplication. I'm going to approve and merge this now, because I don't like to have people's PRs get stuck. However, I won't publish it to crates.io immediately. If someone hatches an idea for the duplication problem we can do that before a publish, and if people want to use this right away in the mean time they can use it straight out of the git repo temporarily. |
…okathor#132) * Add `allocation::{try_,}cast_{arc,rc}`, and add `{wrap,peel}_{arc,rc}` to `TransparentWrapperAlloc`. * Avoid intermediate slice reference in `try_cast_slice_{arc,rc}`. * remove `unsafe` block; run `cargo +nightly fmt` (ignoring files I didn't modify) * Make `cast_rc` (etc) have the same bounds as `cast_mut`, due to the existence of `Rc::get_mut_unchecked`.
Add
allocation::{try_,}cast_{arc,rc}
(and corresponding slice functions), andallocation::TransparentWrapperAlloc::{wrap,peel}_{arc,rc}
.May fix #131 .
Mostly a copy-paste of the
*_box
functions, with relevant safety comments/changes (and using*const
instead of*mut
).Added tests for
{wrap,peel}_{arc,rc}
where the existing tests for{wrap,peel}_box
are. I didn't add tests for the other functions (yet).Possible future work:
rc::Weak
andsync::Weak
;cast_weak_rc
vscast_rc_weak
){cast,wrap,peel}_weak_{arc,rc}
, these would be mostly copy-pastes of*_{arc,rc}
etc.cast_weak_slice
, these would need manual handling of length, since you can't useinput.len()
zeroed_{arc,rc}
andzeroed_slice_{arc,rc}
. These cannot be implemented manually likezeroed_box
was, and would need to be behind an additional nightly-only feature, since{Rc,Arc}::new_zeroed{,_slice}
are infeature(new_uninit)
try_zeroed_{arc,rc}
. These also cannot be implemented manually, and would need to be behind an additional nightly-only feature(s?), since{Rc,Arc}::new_zeroed_slice
are infeature(allocator_api)
(and/orfeature(new_uninit)
, depending on which gets stabilized first).try_zeroed_slice_{arc,rc}
. The corresponding functions currently do not currently exist in the stdlib.*_zeroed_*
could be implemented (less efficiently) in terms of their_box
counterparts, usingimpl<T: ?Sized> From<Box<T>> for Rc<T>/Arc<T>
. These impls are from1.21.0
, so it would not require a nightly-oly feature nor raise the MSRV of using theextern_crate_alloc
feature (Sidenote: Does this crate keep MSRVs for specific features?).