We can use the compiler to prove if something implements Copy
. Using the list of primitives from The Rust Programming Language:
fn is_copy<T: Copy>() {}
fn main() {
is_copy::<bool>();
is_copy::<char>();
is_copy::<i8>();
is_copy::<i16>();
is_copy::<i32>();
is_copy::<i64>();
is_copy::<u8>();
is_copy::<u16>();
is_copy::<u32>();
is_copy::<u64>();
is_copy::<isize>();
is_copy::<usize>();
is_copy::<f32>();
is_copy::<f64>();
is_copy::<fn()>();
}
There are a few other types I'd consider "primitive":
- Immutable references (
&T
)
- Mutable references (
&mut T
)
- Raw pointers (
*const T
/ *mut T
)
Immutable references always implement Copy
, mutable references never implement Copy
, and raw pointers always implement Copy
:
// OK
is_copy::<&String>();
is_copy::<*const String>();
is_copy::<*mut String>();
// Not OK
is_copy::<&mut i32>();
There are a few other types from the book's list:
These types can contain many types; they are parameterized over a generic. They are only Copy
if all the contained values are Copy
:
// OK
is_copy::<[i32; 1]>();
is_copy::<(i32, i32)>();
// Not OK
is_copy::<[Vec<i32>; 1]>();
is_copy::<(Vec<i32>, Vec<i32>)>();
Slices are doubly special. The slice type itself ([T]
) and string slices (str
) are unsized types. It's very rare to see them without an indirection of some kind, often a reference (&[T]
/ &str
). The unsized values cannot exist by themselves. The version behind a reference behaves like references do.
// OK
is_copy::<&str>();
is_copy::<&[i32]>();
// Not OK
is_copy::<str>();
is_copy::<[i32]>();
And as always, the documentation for a trait lists everything that implements that trait. (Except when there are bugs in the documentation).
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…