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
PureCloneproc macro to derive this trait for user types, which ensures:- Each field/variant of a given user
struct/enumis alsoPureClone. - A
clonemethod that does not call anyCellcontent 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-
defaultCloneimpl with trait bounds that ensure any fields with generic parameters are alsoClone; and - A
PureCloneimpl 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.