ADR-071: break, continue and loop Are Reserved Words, and None of Them Is a Construct

Status: Superseded by ADR-276 — its D1 and D3 are D9, its D4 is D10 there; D2 is not carried (displaced by ADR-084 D1) Date: September 14, 2026 Target Version: Nikaia 0.0.8 Supersedes: — nothing. It applies ADR-051 D1’s rule to three words that rule had missed Related: ADR-051 D1 (a name may not be a reserved word) and D7’s direction of travel, ADR-050 D2 (overlap reserved before its construct existed) and D7 (seq un-reserved when its construct was withdrawn), ADR-070 D4 (which named this and deliberately did not decide it)


1. Context

ADR-070 D2 found, while answering a different question, that break and continue are not in the language at all: not in the grammar, not in the parser, and not among the reserved words. A loop is left by its condition going false or by a return that leaves the whole function.

That is a language design question in its own right and this record does not answer it. What it answers is the cheap half, which has a deadline: whether the three words stay available as names.

ADR-051 D1’s rule is the one that decides it, and it is about timing rather than taste:

reserving a word costs nothing before programs exist and breaks them afterwards, so the free moment is now

ADR-050 D2 already applied it once, reserving overlap while the grammar had no construct for it. This is the same move for three more words, and the reason to make it now is that the free moment is not permanent.

2. Decisions

D1 — break and continue are reserved words.

The list goes from 29 to 31. A program may not name a value, a type, a field or a parameter either of the two.

D2 — Neither is a construct yet.

Reserving is not adding, and the two are worth keeping apart because the list is read as a promise. break and continue are open questions — a language whose loops can only be left by returning from the enclosing function is unusual, and nothing here says which way that goes.

D3 — A word is reserved for a construct the language may want, and for nothing else.

loop is the word this rule is drawn against. ADR-070 D1 decided the language does not want it, and a word whose only value would be a message to a reader arriving from another language needs no reservation to carry one: a name nothing declares is refused with a help text, which is where that message lives (ADR-117 D2). So loop is a name.

The direction of travel is the reason this is safe. ADR-050 D7 un-reserved seq when its construct was withdrawn, and recorded why that direction is free: reserving narrows what parses and un-reserving widens it, so taking a word off the list breaks no program. A reservation is therefore reversible and its absence is not, which settles the polarity for a word nobody can yet be sure about.

D4 — The grammar gets a third alternation, not two more arms.

The reserved words are one rule in the grammar, split in two because the alternation the backend generates is a tuple and a tuple has a width the library implements Alt up to — twenty-eight was over it, which is what forced the first split. Thirty-one is further over, and the three new words go in a part of their own rather than onto the end of the second, because the width is the thing that broke last time and three arms are not worth testing its edge with.

3. Consequences

No program changes. None of the three appears as a name anywhere in the tree — every occurrence is in a comment about a loop.

The parse error already knows what to say. The note that reads “loop is a reserved word, so it is not a name” is ADR-051’s and is read off the rendered message rather than off the list, so it covers the three without being told about them.

Two questions are now named and open: whether break and continue join the language. They are not on the notes page, because nothing rests on them yet — a loop that can only be left by return is unusual, not blocking — and the page is for questions that hold work up.

4. What is built

Yes, all of it. RESERVED_WORDS carries the three, the grammar has KW_BREAK, KW_CONTINUE and KW_LOOP and a RESERVED_C rule that alternates over them, and Part I 2.1’s table lists them.

The test that covers it is the one ADR-051 already had: it walks RESERVED_WORDS and refuses each as a name, so a word added to the list without a grammar rule would fail it. Run against the compiler, let loop = 1 is now

expected `mut`; found unexpected token `loop` at line 2, column 9
note: `loop` is a reserved word, so it is not a name (Part I, 2.1).
This site is open source. Improve this page.