E08262: every suffixed value in a constraint must carry the SAME suffix — comparing across currencies or units is never satisfied
What went wrong
A constraint compares against literals carrying DIFFERENT suffixes — two currencies, or two units of measure. Nothing can satisfy such a constraint, so the constrained type could never hold a value.
A suffixed value has two parts, and only one of them is a magnitude. '330#GBP' is an amount AND a currency; '500mm' is a magnitude AND a unit. EK9 does not compare across the suffix: an amount in GBP and an amount in USD are not ordered relative to one another, and neither are millimetres and centimetres. A comparison across suffixes yields an UNSET result, an unset result does not satisfy a constraint, and so a value that would have to satisfy both clauses cannot exist.
This is why it is an error at the declaration rather than a surprise later. A cross-suffix comparison is UNDECIDABLE at compile time rather than false, so it is invisible to the constant-violation check (E08260) — a value carrying the wrong suffix passes every compile-time gate and then Panics at run time, at every single construction of the type.
Only literals that are a magnitude followed by a bare suffix take part in this rule. A Date (2024-01-15), a Time (18:30:00), a Duration (P10D) and a Colour (#FF0000) are not suffixed quantities and are never reported here.
Worked examples
Compilable examples demonstrating this error and the correct fix:
- ek9 -q 1376 (Why does my constrained type fail to compile with 'no val...)
- ek9 -q 257 (How do constrained types work in EK9?)
- // Two currencies in one constraint - nothing can be both:
- Budget as Money constrain as
- > 330#GBP and < 450#USD // E08262
- // Two units of measure - the same problem:
- Width as Dimension constrain as
- >= 500mm and <= 90cm // E08262
- // Correct - one suffix throughout:
- Budget as Money constrain as
- > 330#GBP and < 450#GBP // OK
- Width as Dimension constrain as
- >= 500mm and <= 900mm // OK
How to fix it
- Pick ONE currency, or ONE unit, and express every bound in it. Convert the other bound by hand: '<= 90cm' becomes '<= 900mm'.
- If you genuinely need to accept more than one currency, a constraint is the wrong tool — a constrained type has a single admissible value-set, and cross-currency ordering is not defined. Model the currency explicitly (a record pairing an amount with a currency, or one constrained type per currency) rather than trying to express it in one constraint.
- Check for a wrong-but-valid suffix. 'GBP' against 'EUR', or 'mm' against 'm', is reported here. A MISSPELLED currency code such as '#GPB' is not: that is not a currency at all, so the literal itself is rejected before this check is reached.
Common causes
- Copying one bound from elsewhere and leaving its currency or unit unchanged
- Mixing units of the same measure ('500mm' with '90cm') on the assumption they convert automatically
- Reaching for a different but equally valid currency or unit on one of the two bounds
- Expecting a constrained type to accept several currencies
See also
Examples
Every example is compiled by the EK9 compiler: the first fails exactly as captioned, the others fix it.
Fails with E08262: every suffixed value in a constraint must carry the SAME suffix — comparing across currencies or units is never satisfied
#!ek9 defines module error.e08262.bad defines type Budget as Money constrain as > 330#GBP and < 450#USD Width as Dimension constrain as >= 500mm and <= 90cm
Fixed: Write every bound with the same suffix
#!ek9 defines module error.e08262.good defines type Budget as Money constrain as > 330#GBP and < 450#GBP Width as Dimension constrain as >= 500mm and <= 900mm
Questions and answers
These Q&A entries show E08262 and its fix: