ADR-355: List Patterns, and .. as the Rest of Positional Values

Status: Accepted Date: October 14, 2026 Answers: #618 Changes: ADR-349 D3 (a positional rest is decided here) Related: ADR-291 D10, D17 (the shapes of a pattern); ADR-293 D23 (ref Array[T] views); Part I 3.4; Part III 17.1

1. Question

Can a match take a list apart by its shape? A list’s first element, its last, or exactly two elements are today a len() check and indexes, each of which can panic if the check and the index disagree. Every neighbouring language with patterns (Rust, Swift’s arrays via case let, Python 3.10, Haskell, OCaml, Elixir) matches a sequence by its elements.

2. Decisions

D1 — A list pattern matches a list element by element.

[], [x], [a, b], [Op::Times, n] match a Vec[T], an Array[T] or a view of either whose length is the number of parts, each part a pattern against an element of type T. [first, .., last] and [h, ..] match any length at least the number of named parts; the .. binds nothing.

Why. The shape is the length check, so no index is left to panic. It is the tuple pattern applied to a sequence, with the rest a tuple already has.

D2 — ..rest binds the remaining elements as a view, ref Array[T].

[h, ..rest] binds rest to the elements the other parts do not name. It is a view of the list (ADR-293 D23) under the rules of every view: it may be read and lent, and keeping it beyond the list is refused as for any view. A named rest exists only in a list pattern.

Why. Recursion over a list’s tail is the use that makes list patterns worth having; a copy of the tail would make every step cost the rest of the list. The spelling is ..rest and not Rust’s rest @ ..: @ is not part of Nikaia’s patterns, and ..rest reads as the rest, named.

D3 — A positional .. in a tuple or a variant is the remaining values.

(a, ..), (.., z) and E::V(a, ..) match as a list pattern does: the parts before .. from the front, those after it from the back, the rest bound to nothing. E::V(..) (ADR-349 D1) is the case with no named part. NK1255 stays only for .. on a variant without values; naming more parts than the variant carries is NK1253.

Why. One spelling, one meaning: .. is the rest in a struct, a list, a tuple and a variant. Leaving the positional form refused would make a tuple the one shape where the rest cannot be said.

D4 — At most one .. per pattern: NK1258.

[a, .., b, ..] does not say which elements each rest takes.

D5 — A match with a list pattern needs else (NK1151).

A list’s lengths are unbounded, so coverage is not computed: the rule for a match over anything but an enum or bool applies. The lowering matches the subject as a slice, match &(x)[..] { [a, .., z] => …, [h, rest @ ..] => … }, which leaves the list where it was.

3. Rejected alternatives

This site is open source. Improve this page.