E08265: a constraint's literal must match the operator's parameter type exactly — a constraint is never converted, so write the literal in that type or add the operator taking this one
What went wrong
The literal in a constraint does not match the parameter type of the operator it is compared with. A constraint is never converted: its literal is compared with the base type's operator exactly as it is written, so there is no promotion inside a 'constrain as'. A 'Ratio as Float' constrained '>= 1 and <= 100' compares Integers with Float's '>=', which takes a Float.
In an ordinary expression 'ratio >= 1' promotes the Integer to a Float and works. A constraint is a DECLARATION of the values a type admits, and the check generated from it uses the literal as written. Before this error existed such a constraint compiled and then failed at the FIRST construction of the type - the generated check called a Float comparison taking an Integer, which does not exist. The declaration must say exactly what it means instead.
The rule holds for every comparison operator ('==', '<>', '<', '<=', '>', '>=') and for every promotable pair - an Integer does not become a Float, and a Character does not become a String.
Worked examples
Compilable examples demonstrating this error and the correct fix:
- ek9 -q 1391 (Why is 'Ratio as Float constrain as >= 1' rejected with E08265?)
- ek9 -q 257 (How do constrained types work in EK9?)
The [EXAMPLE] section below shows a Float base given Integer literals, a String base given a Character, and a user-defined Price whose '>=' takes only a Float; then the literals respelt ('1.0', '"x"'), and Price given a '>=' that takes an Integer.
How to fix it
- For a built-in base (Float, String, ...), respell the literal in the operator's parameter type - the error message gives it: '1' becomes '1.0', 'x' becomes "x". Built-in types cannot gain operators.
- For a user-defined base you can choose: respell the literal to match the operator that already exists, or ADD a comparison taking the literal's type (good_operator.ek9 below).
- Do not look for a way to make the constraint convert its literal. The exact match is deliberate: what the declaration states and what is checked at construction are then the same thing.
Common causes
- Writing whole-number bounds on a Float constraint ('>= 1' instead of '>= 1.0')
- Using a Character literal ('x') where a String constraint needs a String ("x")
- A user-defined base whose comparison operators take a different type from the literals used
See also
- E08265: a constraint's literal does not match the operator's type (this error)
- E08260: a compile-time constant value violates the type's constraint
- E08261: no value of the base type can satisfy this constraint
- E08262: a constraint mixes suffixes
- E50060: the operator does not exist for the literal's type at all, even with promotion
Examples
Every example is compiled by the EK9 compiler: the first fails exactly as captioned, the others fix it.
Fails with E08265: a constraint's literal must match the operator's parameter type exactly — a constraint is never converted, so write the literal in that type or add the operator taking this one
#!ek9 defines module error.e08265.bad defines type //Built-in base: Float's '>=' takes a Float, so the Integer literal must be written 1.0. Ratio as Float constrain as >= 1 and <= 100 //The same constraint written in the operator's own type is fine - the false-positive guard. GoodRatio as Float constrain as >= 1.0 and <= 100.0 //User-defined base: either add 'operator >= as pure -> limit as Integer' to Price, or write 1.0. Bounded as Price constrain as >= 1 and <= 100.0 //Not just Float: a Character does not silently become a String either - write "x". NotInitial as String constrain as <> 'x' defines record //A user-defined base whose comparison operators take a Float, not an Integer. Price amount as Float? Price() amount: Float() Price() -> initial as Float amount: initial Price() -> other as Price amount: other.amount operator <= as pure -> limit as Float <- rtn as Boolean: amount <= limit operator >= as pure -> limit as Float <- rtn as Boolean: amount >= limit override operator ? as pure <- rtn as Boolean: amount? operator :=: -> other as Price amount :=: other.amount
Fixed: Write each literal in the type the operator takes
#!ek9 defines module error.e08265.good defines type Ratio as Float constrain as >= 1.0 and <= 100.0 NotInitial as String constrain as <> "x"
Fixed: A user-defined base can instead ADD the operator that takes the literal's type
#!ek9 defines module error.e08265.good.operator defines type Bounded as Price constrain as >= 1 defines record Price amount as Float? Price() amount: Float() Price() -> initial as Float amount: initial Price() -> other as Price amount: other.amount operator >= as pure -> limit as Float <- rtn as Boolean: amount >= limit //Takes an Integer, so the constraint below may compare with '1' operator >= as pure -> threshold as Integer <- rtn as Boolean: amount >= #^threshold override operator ? as pure <- rtn as Boolean: amount? operator :=: -> other as Price amount :=: other.amount
Questions and answers
These Q&A entries show E08265 and its fix: