break, continue and loop Are Reserved Words, and None of Them Is a ConstructStatus: 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)
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.
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.
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.
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.
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.
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.
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).