drain() Is on Every Map and Set, as on Vec and HashMapStatus: Accepted (#1130)
Date: November 1, 2026 (architect’s decision under the owner’s rule of
2026-10-31, docs/supervisor.md, Language decisions: an extension nobody
pays for who does not use it, in the form the language already has)
Answers: the C1b move (547e6462, ledger_items_stored) found that a
collections::BTreeMap has no drain() (NK1171), so its fold borrowed each
unit’s map and cloned every set it took over
Related: ADR-094 D4 (a for lends; drain takes the
elements away), ADR-collections-1 (the maps and sets
of std::collections), ADR-384 (the last std counterparts a
C1 move needed), Part III 17.1
Vec::drain and collections::HashMap::drain are in the ledger
(std.contracts): a for over them binds owned elements and the container
goes with them. BTreeMap, HashSet and BTreeSet have no such entry, so a
program that wants to take a sorted map’s values over must clone them. Is
drain() on them, and what does it mean?
drain() takes every element out of a map or setm.drain() on a collections::BTreeMap[K, V] is a Seq[(K, V)] sync sized,
on a HashSet[T] or a BTreeSet[T] a Seq[T] sync sized, with the
signature HashMap::drain has: the receiver is taken (self, not ref), so
what a for over it binds is the program’s own, and a key, a value or an
element may be handed to something that keeps it. The two sorted containers
hand their elements out in key order and say ends as well, as their iter
does.
HashSet lowers to Rust’s drain(). Rust’s BTreeMap and BTreeSet have
no stable drain: they lower to into_iter() of the container, or to
std::mem::take(&mut m).into_iter() where the container is a place the
program still names after the loop (a field, a let mut); either is what D1
means.
drain(); it held for two containers of five only because nobody had needed
the others.drain, into_iter, mem::take); the program writes one word and the
lowering chooses.HashMap::drain and HashSet::drain, and
BTreeMap::extract_if unstable; Swift’s removeAll and Kotlin’s
MutableMap.clear after a copy do it in two steps. One word for every
container is the simpler surface.drain(range) on a Vec (no move has met it); retain beside it is
ADR-collections-1’s.