Crate clone_cell
source ·Expand description
This crate provides a Cell
implementation that works with types whose clone
methods are guaranteed not to mutate the Cell
content using the &self
reference. This is
enforced with the provided PureClone
trait, which is a subtrait of Clone
(and a logical
supertrait of Copy
). It is only implemented for types with a compliant clone
method.
See the cell
module documentation for more information on how to use it.
Background
To enable interiorly mutating methods on a type stored in an Rc
or
Arc
without the overhead of a RefCell
,
we can wrap each of its fields in a core::cell::Cell
.
But Cell
’s get
method is only implemented for
types that are Copy
. This is because if the clone
method obtains a reference to the
containing Cell
, it may be able to mutate its state. This can cause undefined behavior, as
demonstrated in this example.
By restricting ourselves to a checked subset of Clone
implementations that do not exploit
interior mutability to mutate the Cell
content, it becomes possible to provide a Cell
with a
get
method that does not require the type to be Copy
.
See the documentation for PureClone
for a list of implemented types and the clone
module
documentation for more details.
Soundness
I believe this is sound, because PureClone
is unsafe to implement. In user code, the only ways
to use PureClone
without unsafe
are:
- Use types that already implement
PureClone
. - Use the provided
PureClone
proc macro to derive this trait for user types, which ensures:- Each field/variant of a given user
struct
/enum
is alsoPureClone
. - A
clone
method that does not call anyCell
content accessors is implemented (such as one generated by#[derive(Clone)]
).
- Each field/variant of a given user
Interaction with specialization
The PureClone
proc macro generates:
- A non-
default
Clone
impl with trait bounds that ensure any fields with generic parameters are alsoClone
; and - A
PureClone
impl that only compiles if all fields are alsoPureClone
.
Item 1 is non-default
and hence cannot be further specialized.
The user may attempt to provide a default
Clone
impl (or one with a default
clone
method). But this is fine, because item 2 ensures every field is PureClone
(and therefore
Clone
), so item 1 is always selected even if a user-provided default
Clone
impl with fewer
trait requirements is present.
So I think even with RFC1210 fully implemented, this is still sound.