Why can't None be cloned for a generic Option<T> when T doesn't implement Clone?
As the other answers correctly point ouf, this is due to the way the vec!
-macro is implemented. You can manually create a Vec
of any Option<T>
without requiring T
to be Clone
:
let bar = std::iter::repeat_with(|| Option::<T>::None).take(size).collect::<Vec<_>>();
This will create size
-number of Option::<T>::None
and place them in a Vec
, which will be pre-allocated to the appropriate size. This works for any T
.
If one part can't be cloned, then no parts can be cloned. Think about this from a type perspective: you have a variable called foo
of type Option<T>
, where T
isn't clonable. Sure, None
can be cloned, but Some(_)
can't, and the type of the variable doesn't tell you which it is. So, from a compile-time perspective, you can't clone the option.
Isn't a
None
of typeT
the same as any otherNone
?
Definitely not! Unlike reference-based languages where null is typically implemented as a null-reference, Rust's Option<T>
introduces no indirection and stores T
inline when the option is Some
. Since all enum variants have the same size, the None
variant must still occupy at least as much space as T
.
Having said that, it is technically true that the None
value could be cloned without T
being Clone
simply because the None
variant of the enum doesn't contain the T
, it only stores the discriminator and reserves space that could contain T
if the variant were to change to Some
. But since Rust enum variants are not separate types, a trait bound defined for the enum must cover all variants.
See other answers more detailed explanations and instructions how to create a vector of None
values of a non-cloneable Option
.