E08261: no value of the base type can satisfy this constraint — every construction would Panic
What went wrong
A constrained type declares a constraint that NO value of its base type can satisfy. The type is dead by construction: every constructor call would Panic at runtime, every variable of it would be permanently unset, and no caller, test or code path could ever hold a usable value of it. Because this is decidable from the declaration alone, the compiler rejects it where it is written rather than leaving a Panic to be discovered later.
This is reported only when it can be PROVEN. Two proofs apply today, and both require the parts of the constraint to be joined by 'and' — under an 'or' one branch failing says nothing about the other:
- The bounds narrow to an empty range. Over Integer, '> 0' admits 1 upwards and '< 1' admits 0 downwards, so together they admit nothing at all.
- An '==' pins the value, and that value fails another part of the same constraint. If '== 5' is present then 5 is the only candidate there is, so '== 5 and > 10' admits nothing.
Anything the compiler cannot decide is left alone and the constraint stands as a runtime check, exactly as before. In particular a strict range over a CONTINUOUS base is perfectly satisfiable and is not reported: '> 0.0 and < 1.0' over Float admits 0.5. The emptiness reasoning above holds for a whole-number base, where there is nothing between 0 and 1.
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...)
- carries the worked incorrect/correct pairs for THIS code
- ek9 -q 257 (How do constrained types work in EK9?)
- ek9 -q 1185 (Define a Percentage type constrained to 0..100)
The [EXAMPLE] section below shows bounds that cross ('> 0 and < 1' admits no Integer), a lower bound above the upper ('>= 10 and <= 5'), and an '==' that fails a sibling clause ('== 42 and > 100'); then constraints that admit values, including a gap written with 'or' and a strict range over a Float.
How to fix it
- Read the bounds as a range and check they do not cross. For a whole-number base remember the bounds are the values themselves: '> 0 and < 1' leaves nothing between, whereas '>= 0 and <= 1' admits 0 and 1.
- If you meant to allow values on either side of a gap rather than between two bounds, you want 'or', not 'and': '< 10 or > 90' admits everything outside 10..90.
- If an '==' is present, delete it or delete the clause it contradicts. A constraint containing '==' can admit at most that one value, so any other clause can only take that value away.
- If you wanted a fractional range, constrain a Float (or another continuous base) rather than an Integer.
Common causes
- Strict operators where inclusive ones were meant: '> 0 and < 1' instead of '>= 0 and <= 1'
- The two bounds written in the wrong order, so the lower is above the upper ('>= 10 and <= 5')
- 'and' used where 'or' was meant, turning "outside this range" into "inside two ranges at once"
- An '==' left beside a range clause it contradicts
- Copying a Float range onto an Integer base, where the values between the bounds do not exist
See also
Examples
Every example is compiled by the EK9 compiler: the first fails exactly as captioned, the others fix it.
Fails with E08261: no value of the base type can satisfy this constraint — every construction would Panic
#!ek9 defines module error.e08261.bad defines type Digit as Integer constrain as > 0 and < 1 Bracket as Integer constrain as >= 10 and <= 5 Answer as Integer constrain as == 42 and > 100
Fixed: Write a constraint that some value satisfies
#!ek9 defines module error.e08261.good defines type Digit as Integer constrain as >= 0 and <= 9 Bracket as Integer constrain as >= 5 and <= 10 Outlier as Integer constrain as <= 10 or >= 90 Fraction as Float constrain as > 0.0 and < 1.0
Questions and answers
These Q&A entries show E08261 and its fix: