E08260: compile-time constant value violates the type's constraint — this would Panic at runtime
What went wrong
A constrained type was constructed with a value that is KNOWN at compile time and provably violates the type's constraint. At runtime this construction would raise an uncatchable Panic; because the value is known now, the compiler rejects it now instead. This applies to EVERY constrainable base type — Integer, Float, String (equality, ordering, 'matches' regex, 'contains'), Date, Time, DateTime, Duration, Money, Dimension, Colour and Character — the value is evaluated against the real constraint, so a regex or value comparison is checked statically, not deferred to runtime.
The value does NOT have to be written as a literal at the construction. Flow analysis follows the value that ARRIVES there, so all of these are rejected alike: a literal; a named constant; a local assigned a literal, however many times it is reassigned; a value bound by a guard on if/while/switch/try/do; a parameter that a path condition has pinned to an exact value; and an arm of a ternary. An Integer literal reaching a Float-based constraint is promoted first, so Ratio(2) is rejected exactly as Ratio(2.0) is.
If the value cannot be determined — it comes from a call, from arithmetic, or from an un-narrowed parameter or field — nothing is reported and the constraint is checked at runtime as before. The compiler only rejects what it can prove.
Worked examples
Compilable examples demonstrating this error and the correct fix:
- ek9 -q 1185 (Define a Percentage type constrained to 0..100 — carries the worked
- incorrect/correct pair for THIS code, including the laundered form)
- ek9 -q 1241 (Create me a constrained EmailAddress type as String valid...)
- ek9 -q 257 (How do constrained types work in EK9?)
The [EXAMPLE] section below has an Age constrained to '>= 16 and <= 100': Age(15) is provably outside it, Age(16) is in range (boundaries are inclusive). The same holds for every base: an Email constrained to 'matches /^[a-z]+@[a-z]+$/' rejects Email("not an email"), and a Budget of '>= 0#GBP and <= 1000#GBP' rejects Budget(2000#GBP).
How to fix it
- If you have a known-good value, use one that satisfies the constraint (boundaries are inclusive).
- If the value comes from untrusted/external input that MIGHT be invalid, do NOT use a bare constructor (a bare constructor ASSERTS validity and Panics at runtime on a set out-of-range value). Use the fallible factory 'of' instead, which returns an UNSET value on violation and never Panics, and guard on its result (good_checked.ek9 in the [EXAMPLE] section below). The of(baseValue) factory takes the base-type value (Integer here, String for a String-constrained type, Money for Money, the base enum for a constrained enumeration, and so on).
Common causes
- A literal argument outside the declared range (e.g. Age(15) for '>= 16 and <= 100')
- The SAME value moved into a variable or constant first. This does not defer the check: a local 'limit' given 15 then 'Age(limit)', or a constant 'UNDER_AGE' of 15 then 'Age(UNDER_AGE)', are rejected exactly as Age(15) is. Hoisting a value into a constant also disables nothing for later edits — if the constant is changed to a violating value, this error appears at every construction that uses it
- A string literal that fails a 'matches' regex or a 'contains' check (e.g. Email("not an email"))
- A Date/Time/Money/Dimension/Colour literal outside the declared bounds (e.g. Budget(2000#GBP))
- An off-by-one at an inclusive boundary
- A value that falls in a forbidden gap of an 'or' constraint (e.g. Edge(50) for '< 10 or > 90')
- Treating a bare constructor as a validator: it ASSERTS validity (Panics on bad set input) — use of() with untrusted input
See also
Examples
Every example is compiled by the EK9 compiler: the first fails exactly as captioned, the others fix it.
Fails with E08260: compile-time constant value violates the type's constraint — this would Panic at runtime
#!ek9 defines module error.e08260.bad defines type Age as Integer constrain as >= 16 and <= 100 defines program AgeCheck() stdout <- Stdout() tooYoung <- Age(15) stdout.println($tooYoung)
Fixed: Construct a value the constraint admits
#!ek9 defines module error.e08260.good defines type Age as Integer constrain as >= 16 and <= 100 defines program AgeCheck() stdout <- Stdout() youngest <- Age(16) stdout.println($youngest)
Fixed: Or check a value only known at run time with of()
#!ek9 defines module error.e08260.good.checked defines type Age as Integer constrain as >= 16 and <= 100 defines program AgeCheck() -> rawInput as Integer stdout <- Stdout() if validAge <- Age().of(rawInput) stdout.println($validAge) else stdout.println("rejected: out of range")
Questions and answers
These Q&A entries show E08260 and its fix: