llms.txt
Skip to main content

Abilities: Drop

In most programming languages, doing nothing with a value is not a problem: an unused variable may trigger a warning at most, and is forgotten the moment it goes out of scope. In Move, as we saw in the Struct section, the default is the opposite: a struct value must be used - stored somewhere, passed on, or unpacked - and a program that silently discards a value does not compile.

The drop ability - the simplest ability of the four - is the opt-out from this rule. A struct with drop is allowed to be ignored or discarded: bound to a variable that is never read, ignored with the _ wildcard, or simply left behind when its scope ends. In other words, drop makes a Move type behave the way values behave in most other languages:

module book::drop_ability;

/// This struct has the `drop` ability.
public struct IgnoreMe has drop {
a: u8,
b: u8,
}

/// This struct does not have the `drop` ability.
public struct NoDrop {}

#[test]
// Create an instance of the `IgnoreMe` struct and ignore it.
// Even though we constructed the instance, we don't need to unpack it.
fun test_ignore() {
let no_drop = NoDrop {};
let _ = IgnoreMe { a: 1, b: 2 }; // no need to unpack

// The value must be unpacked for the code to compile.
let NoDrop {} = no_drop; // OK
}

In the example above, the IgnoreMe instance is assigned to _ and never unpacked - the code compiles because IgnoreMe has the drop ability. The NoDrop instance cannot be treated this way: the only two options are to keep it or to unpack it, and the test unpacks it in the last line.

The drop ability only permits discarding a value. It does not permit copying it or storing it - those are governed by the separate copy and store abilities.

When to Use drop

A good rule of thumb: drop belongs on types that represent data, and its absence protects types that represent assets or obligations.

Configuration values, metadata, intermediate results of a computation - none of these are worth protecting, and forcing the programmer to explicitly destroy each one would be pure ceremony. Giving such types the drop ability keeps the code clean. Collection types are a good example: because vector has drop (when its contents do), a vector of numbers can simply be forgotten when it is no longer needed.

The absence of drop, on the other hand, is one of the defining features of Move's type system. A coin, a ticket, a receipt, an obligation to repay - a value like this must never silently vanish, and a type without drop gives that guarantee at the compiler level: whoever holds the value is forced to do something meaningful with it. The compiler-enforced handling of values is the foundation of the Hot Potato pattern mentioned in the previous section, and we explore the full rules of how values move between scopes in the Ownership and Scope section.

A struct with drop as its single ability is called a Witness. We explain the concept of a Witness in the Witness and Abstract Implementation section.

Types with the drop Ability

All native types in Move have the drop ability. This includes:

All of the types defined in the standard library have the drop ability as well. This includes:

Note the pattern in the list: a container type like vector or Option can only be dropped when its contents can. If the elements of a vector are protected from being discarded, the vector holding them is protected too - otherwise dropping the container would be a loophole for dropping the contents.

Further Reading

llms.txt