It's been established (e.g. in this question) that Rust's Cell is not usable for non-Copy types, because the .get() operation is only safe if it can guarantee that the process of cloning/copying the data out of the Cell is not going to be interrupted by something that assigns to the Cell.
The current restriction in Rust, therefore, is that Cell.get() is usable only if the type inside the cell is Copy; Clone is not enough, because there can't be any guarantee that the .clone() call doesn't somehow manage to access the Cell being cloned from and write to it while it's in the middle of being read. So code like this is illegal, because the compiler doesn't know for certain that CloneableObject.clone() doesn't do something absurd:
use std::cell::Cell;
#[derive(Debug, Clone)]
struct CloneableObject {}
fn main() {
let x = Cell::new(CloneableObject {});
println!("{:?}", x.get());
}
My question is about the special case where the type wrapped by the Cell is the standard library type Rc. Rc is special in that Rc.clone() doesn't actually do any copying, and doesn't inspect the value that the Rc points to; it just increments an integer inside the Rc, something that can't possibly write to a Cell that contains an Rc.
Presumably, this would imply that code like the following could safely be legal:
use std::cell::Cell;
use std::rc::Rc;
fn main() {
let x = Cell::new(Rc::new(0i32));
println!("{:?}", x.get());
}
However, it doesn't compile at present, because there isn't a special case for Cell together with Rc.
My question is: Is there any safety/soundness reason not to add such a special case for Cell? Or is this simply a case of "this would be perfectly safe, but we haven't taught the compiler how to recognise that it's safe yet"? (If doing this would be safe, I may submit it as a feature suggestion – it would be more efficient than RefCell due to not needing runtime checks – but want to make sure that there isn't some unsoundness that I'm missing.)
To avoid any confusion: I am intentionally asking about Cell in this question, not the more commonly used Rc/Rc.