Description
As part of #44619, one topic that keeps coming up is that we have to find some way to mitigate the risk of large, implicit copies. Indeed, this risk exists today even without any changes to the language:
let x = [0; 1024 * 10];
let y = x; // maybe you meant to copy 10K words, but maybe you didn't.
In addition to performance hazards, implicit copies can have surprising semantics. For example, there are several iterator types that would implement Copy
, but we were afraid that people would be surprised. Another, clearer example is a type like Cell<i32>
, which could certainly be copy, but for this interaction:
let x = Cell::new(22);
let y = x;
x.set(23);
println!("{}", y.get()); // prints 22
For a time before 1.0, we briefly considered introducing a new Pod
trait that acted like Copy
(memcpy is safe) but without the implicit copy semantics. At the time, @eddyb argued persuasively against this, basically saying (and rightly so) that this is more of a linting concern than anything else -- the implicit copies in the example above, after all, don't lead to any sort of unsoundness, they just may not be the semantics you expected.
Since then, a number of use cases have arisen where having some kind of warning against implicit, unexpected copies would be useful:
- Iterators implementing
Copy
- Copy/clone closures (closures that are copy can be surprising just as iterators can be)
Cell
,RefCell
, and other types with interior mutability implementingCopy
- Behavior of
#[derive(PartiallEq)]
and friends with packed structs - A coercion from
&T
toT
(i.e., it'd be nice to be able to dofoo(x)
wherefoo: fn(u32)
andx: &u32
)
I will writeup a more specific proposal in the thread below.