Class RangeNeverProgressesOrError

All Implemented Interfaces:
Consumer<EK9Parser.ForRangeContext>

final class RangeNeverProgressesOrError extends TypedSymbolAccess implements Consumer<EK9Parser.ForRangeContext>
A for-range whose start, end and step are all KNOWN when the program is compiled, and whose step can never take the counter from the start to the end, is an error - E08276 (Steve, D49 compile-time half, 2026-10-21).

At run time such a loop runs ZERO iterations, silently: the range's direction is counter <=> end and a stepped range only runs when the step moves the counter TOWARD the end, so 1 ... 10 by -1, 10 ... 1 by 2 and 1 ... 5 by 0 all fall through every case. A program cannot intend that, so a known one is an error. Reported: a step of ZERO, a step whose sign moves AWAY from the end, and a Time range that crosses midnight (Steve: "a Time range never crosses midnight" - a Time wraps round the clock, so a step that passes 00:00 before the end either never reaches it or goes round forever). Never reported: a range whose start equals its end (one iteration, whatever the step), a step larger than the span that stays within the day (one iteration), and anything the compiler cannot read - a parameter, a call, a property.

🔑 What counts as known (one reader, valueOf(EK9Parser.ExpressionContext, boolean)): a literal (Integer, Float, Time, Duration, and the suffixed Money and Dimension literals, read as magnitude plus suffix through ConstraintLiterals), a value the flow state proves constant here (TrackedValues.knownValueOf(EK9Parser.ExpressionContext): a defines constant, a local only given literals), and a CONSTRUCTION of a constrained type, or of a Time, from one of those (Age(148), resolved through ConstrainedConstructionResolver - the same reading E08260 uses). A constrained type orders by its base, so its magnitude orders the range. Suffixed values are decided only when EVERY suffix present agrees (1mm ... 3mm by 1m compares across units, which is UNKNOWN - see ConstraintLiterals) - otherwise nothing is said. A Duration range is read like a number (Duration orders by its length). No constraint WINDOW is needed: a bound outside the constraint is already E08260 at its construction, and the question here is only the order of three known values.

🔑 Inside the body of an enclosing loop a variable is NOT read, only literals and constants: the body is walked once, so the flow state there is the FIRST pass's (D41), and a later pass may see a value the body gave it afterwards (step <- 0, then a loop whose body ranges by step and then sets step := 1).

Not read, so never reported (listed, deliberately): a Date or DateTime range, a Millisecond range, a Duration written in weeks, months or years, a Character or enumeration range, and a user type's range - there is no reader of their ordering or their step here, and a guess could reject a valid program.