ADR-356: A let and a for Head Take a Nested Tuple of Names — No Variant

Status: Accepted Date: October 14, 2026 Answers: #611 (a for head and a let take only one level of tuple) Related: ADR-291 D1-D6 (the flat tuple this widens, its readers, NK1136, _); ADR-291 D10 (match takes nested patterns); Part I 2.1, 3.3; Part III C.1

1. Question

How deep may a let and a for head take a tuple apart, and may either name a variant?

ADR-291 D1 let a let bind one name or a flat tuple of names, and D5 refused a tuple inside the tuple with a sentence. A for head took the same flat list. match takes nested patterns (ADR-291 D10), so the same tuple (name, (line, col)) could be taken apart in an arm and not at a binding.

2. How others do it

Language Its answer
Rust Any irrefutable pattern at let and for, nested; a refutable one needs let … else or if let
Python Nested tuple targets at assignment and for
Swift, Kotlin Swift nests tuple patterns at let and for; Kotlin’s destructuring is one level

3. Options, weighed

Option Why it won or lost
A1 — both sites take a nested tuple of names, _ and tuples, recursively Chosen: one pattern grammar for both binding sites, the one match already nests
A2 — only the for head nests A let that stays flat would be the one binding site that takes a tuple apart differently from its neighbour
B — one level of nesting An arbitrary depth: the second level is no different in kind from the first
A variant in the head A variant can fail to match, and a binding has no branch to go to; that is match’s job

ADR-291 D1’s reason was what the programs of the day needed. That is not how the language is decided: what it offers follows from what it is for and the coherence of its forms, and a tuple taken apart in one place and not in another is not coherent.

4. Decision

D1 — A let and a for head take one irrefutable tuple pattern, nested as deep as it is written.

let (a, (b, c)) = (1, (2, 3))
for (name, (line, col)) in places { … }
for (key, (_, count)) in totals { … }

The pattern is a name, _, or a parenthesised list of two or more patterns. (p) is p. Each name takes the part at its position; a part whose type is not known is ?, and a width is not compared where it is unknown (ADR-291 D3). _ binds nothing (ADR-291 D6). A written type on a destructuring let stays NK1136 (ADR-291 D4). Every reader that declined several names (ADR-291 D2) declines a nested pattern the same way. Changes ADR-291 D1 and D5.

D2 — A variant in a let or a for head is refused, NK1259, naming match.

let Some(x) = o and for Ok(v) in results can fail to match, and neither site has another branch. The refusal says to take the value apart with a match.

This site is open source. Improve this page.