Closed joshlf closed 1 month ago
Reopening; we still need to allow TryFromBytes
on UnsafeCell
and move the NoCell
bound to try_from_ref
.
@korran Just wanted to let you know that this is available in 0.8.0-alpha.1. The NoCell
trait itself is still #[doc(hidden)]
, but you can use it. FromZeros
, FromBytes
, and AsBytes
are now implemented for UnsafeCell
, and so you can derive those traits on types with UnsafeCell
fields. If you're able to try it out, we'd love to hear how it works for you!
Will this work also enable some zerocopy functionality for Atomic* types?
Will this work also enable some zerocopy functionality for Atomic* types?
Good point! I've filed https://github.com/google/zerocopy/issues/1009 to track.
@korran This is now available stably in our 0.8 release train.
The sole remaining concern is now in its own issue:
Summary
Introduce a
Immutable
trait which indicates that a type contains noUnsafeCell
s. AllowFromZeros
,FromBytes
, andAsBytes
on types withUnsafeCell
s and useImmutable
as a bound on individual methods/functions.This enables by-value transmutations such as
transmute!
on types containingUnsafeCell
s.See also https://github.com/google/zerocopy/issues/694.
Progress
Immutable
traitImmutable
FromZeros
,FromBytes
, andAsBytes
onUnsafeCell
; addImmutable
bound on methods as neededTryFromBytes
,FromZeros
, andFromBytes
for unsizedUnsafeCell
. See the discussion below for why we originally limited these impls to sizedUnsafeCell
s only.1619
TryFromBytes
onUnsafeCell
; addImmutable
bound ontry_from_ref
method#[doc(hidden)]
fromImmutable
andpub use zerocopy_derive::Immutable
Immutable
as merely a polyfill for that traitUnsafeCell
s, but not necessary, and that callers cannot assume thatT: Immutable
implies thatT
contains noUnsafeCell
s. Note that our code will need to rely on this implication, and all safety comments should be updated to point at an issue that tracks this change.Consider adding blanket traits:RefFromZeros
forFromZeros + Immutable
,RefFromBytes
forFromBytes + Immutable
, andRefAsBytes
forAsBytes + Immutable
Details
We require that
FromZeros
,FromBytes
, andAsBytes
types don't permit interior mutability. This is a requirement in order for reference casts (e.g.,&T
to&[u8]
or vice-versa) to be valid, but is not a requirement for value casts. As a result, we don't support some transmutations that are sound (namely, value transmutations on types with interior mutability).If we added a separate
Immutable
trait to describe this "has noUnsafeCell
s" property, then we could decouple it from the other traits and allow them to support types withUnsafeCell
s.Immutable
would then be required as a bound on some functions/methods/macros. This would make our API somewhat more complicated, but would unlock a new class of use cases.Note that
Immutable
would be equivalent to the stdlib-internalFreeze
trait. There is a proposal to make that trait public, but we shouldn't bank on that happening any time soon.TryFromBytes
and unsizedUnsafeCell
In principle, there's no reason we couldn't implement
FromZeros
,FromBytes
, andAsBytes
forUnsafeCell<T>
even whenT: ?Sized
. However, this would not play nicely withTryFromBytes
(currently in progress in #5), which we want to eventually be a super-trait ofFromZeros
.In particular, in order to implement
TryFromBytes
for a type, we have to implement theis_bit_valid
method. ForUnsafeCell<T>
whereT: Sized
, we can make a copy of the referentUnsafeCell<T>
, transmute it to aMaybeUninit<T>
, and then construct aPtr<T>
to that value. This workaround isn't possible for unsizedUnsafeCell
s.Given that the whole problem with
UnsafeCell
s arises when they're handled by-reference, and given that the only way to operate on unsized values in Rust (at least today) is by reference, supporting unsizedUnsafeCell
s is unlikely to be useful to any of our users. Thus, by implementingTryFromBytes
(and, by implication, the other traits) only for sizedUnsafeCell
, we get most of the benefit.Motivation
This was originally motivated by https://github.com/chipsalliance/caliptra-sw/pull/634. @korran has provided this minimized example to motivate the feature request:
If
FromBytes
didn't forbid interior mutability, the API offrom_address
would be the same, but it would not require the authors offrom_address
to justify that it's sound to construct aPrng
at the given memory location regardless of its previous contents. Instead, the safety argument can just be "Prng: FromBytes
, so it's sound regardless of the memory contents".