E08262: every suffixed value in a constraint must carry the SAME suffix — comparing across currencies or units is never satisfied

Category: E08xxx Pre-IR checks (flow analysis) · Reported in phase: FULL_RESOLUTION · Classification: CONSTRAINT_MIXED_SUFFIXES · All error codes

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

  1. Pick ONE currency, or ONE unit, and express every bound in it. Convert the other bound by hand: '<= 90cm' becomes '<= 900mm'.
  2. 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.
  3. 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

  • E08262: a constraint mixes suffixes (this error)
  • E08261: no value of the base type can satisfy this constraint
  • E08260: a compile-time constant value violates the type's constraint

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: