clone_cell/
lib.rs

1//! This crate provides a [`Cell`](cell::Cell) implementation that works with types whose `clone`
2//! methods are guaranteed not to mutate the `Cell` content using the `&self` reference. This is
3//! enforced with the provided [`PureClone`] trait, which is a subtrait of [`Clone`] (and a logical
4//! supertrait of [`Copy`]). It is only implemented for types with a compliant `clone` method.
5//!
6//! See the [`cell`](module@cell) module documentation for more information on how to use it.
7//!
8//! # Background
9//!
10//! To enable interiorly mutating methods on a type stored in an [`Rc`](alloc::rc::Rc) or
11//! [`Arc`](alloc::sync::Arc) without the overhead of a [`RefCell`](core::cell::RefCell),
12//! we can wrap each of its fields in a [`core::cell::Cell`].
13//! But `Cell`'s [`get`](core::cell::Cell::get) method is only implemented for
14//! types that are `Copy`. This is because if the `clone` method obtains a reference to the
15//! containing `Cell`, it may be able to mutate its state. This can cause undefined behavior, as
16//! demonstrated in this [example].
17//!
18//! By restricting ourselves to a checked subset of `Clone` implementations that do not exploit
19//! interior mutability to mutate the `Cell` content, it becomes possible to provide a `Cell` with a
20//! `get` method that does not require the type to be `Copy`.
21//!
22//! See the documentation for [`PureClone`] for a list of implemented types and the [`clone`] module
23//! documentation for more details.
24//!
25//! # Soundness
26//!
27//! I believe this is sound, because `PureClone` is unsafe to implement. In user code, the only ways
28//! to use `PureClone` without `unsafe` are:
29//! 1. Use types that already implement `PureClone`.
30//! 1. Use the provided [`PureClone`](derive@clone::PureClone) proc macro to derive this trait for
31//! user types, which ensures:
32//!     - Each field/variant of a given user `struct`/`enum` is also `PureClone`.
33//!     - A `clone` method that does not call any `Cell` content accessors is implemented (such as
34//!     one generated by `#[derive(Clone)]`).
35//!
36//! ## Interaction with specialization
37//!
38//! The [`PureClone`](derive@clone::PureClone) proc macro generates:
39//! 1. A non-`default` `Clone` impl with trait bounds that ensure any fields with generic parameters
40//! are also `Clone`; and
41//! 1. A `PureClone` impl that only compiles if all fields are also `PureClone`.
42//!
43//! Item 1 is non-`default` and hence cannot be further specialized.
44//!
45//! The user may attempt to provide a `default` `Clone` impl (or one with a `default` `clone`
46//! method). But this is fine, because item 2 ensures every field is `PureClone` (and therefore
47//! `Clone`), so item 1 is always selected even if a user-provided `default` `Clone` impl with fewer
48//! trait requirements is present.
49//!
50//! So I think even with [RFC1210] fully implemented, this is still sound.
51//!
52//! [`PureClone`]: clone::PureClone
53//! [example]:
54//! https://users.rust-lang.org/t/why-does-cell-require-copy-instead-of-clone/5769/3
55//! [RFC1210]: https://github.com/rust-lang/rfcs/blob/master/text/1210-impl-specialization.md
56
57#![no_std]
58
59extern crate alloc;
60
61pub mod cell;
62pub mod clone;
63#[cfg(feature = "derive")]
64use clone_cell_derive as derive;