Abilities: Copy
In the Ownership and Scope section, we saw that primitive values are copied rather than moved: assigning a number to a new variable leaves both variables usable. The copy ability is precisely what enables this behavior - and while it is built into the primitive types, it is not the default for custom types. Move is designed to express digital assets and resources, and a resource that could be freely duplicated would not be much of a resource. Duplication is therefore something a type must explicitly opt into:
public struct Copyable has copy {}
Once a type has the copy ability, its values are copied wherever a move would otherwise happen and the original is still needed - implicitly, without any special syntax. The copy keyword can be used to spell the copy out explicitly:
let a = Copyable {};
// `a` is copied into `b` implicitly - both are usable afterwards.
let b = a;
// The `copy` keyword makes the copy explicit.
let c = copy a;
// `Copyable` does not have the `drop` ability, so every instance -
// `a`, `b`, and `c` - has to be used. Here, we unpack all of them.
let Copyable {} = a;
let Copyable {} = b;
let Copyable {} = c;
In the example above, a is copied into b implicitly - the compiler sees that a is used again afterwards, and copies the value instead of moving it. Then a is copied into c explicitly with the copy keyword. After the three assignments, there are three independent instances of Copyable - and each of them has to be dealt with separately.
Note the unpacking at the end of the example: Copyable has copy, but not drop, so every instance - including each copy - must be used, and the test unpacks all three. Copying a value never bypasses the usage rules; it just creates more values to which those rules apply.
Copying and Drop
As the example shows, copy without drop is a rather inconvenient combination: duplication is allowed, but every duplicate still demands explicit handling. This is why the two abilities almost always go together - a value that is cheap to duplicate is, in practice, always fine to discard. Types that carry plain data, rather than assets, typically declare both:
public struct Value has copy, drop {}
All of the primitive types behave as if they have copy and drop: they are copied on assignment and discarded without a second thought - with the compiler managing all of it.
Copying is not the only way to let several parts of a program read the same value. In the References section, we show how a value can be borrowed instead, avoiding the duplication altogether; and how the dereference operator * turns a reference back into a copy, which is only permitted for types with the copy ability.
Types with the copy Ability
All native types in Move have the copy ability. This includes:
- bool
- unsigned integers
- vector<T> when T has copy
- address
All of the types defined in the standard library have the copy ability as well. This includes:
Just like with drop, container types are only copyable when their contents are: a vector<T> can be duplicated only if duplicating T is allowed in the first place.
Further Reading
- Type Abilities in the Move Reference.