E08266: an injected component is always set, so checking that it is set is always true - use the injected value directly; for a fallback, use a new variable ('chosen <- supplied' then 'chosen :=? injected')
What went wrong
You are checking whether an INJECTED component is set. An injected variable ('name as T!') is always set: the compiler proves that every injection a program can reach is registered in its application (E08210, E08220), so the application always supplies the component. The check is always true - it is dead code that reads as though the injection might not arrive, and any 'else' it guards never runs.
Every form of the check is rejected: 'logger?' as an if/while condition, in 'require' or 'assert', as a returned value or as a ternary's control; the coalescing operator '?:' with the injected variable on the left; a guard on the injected variable itself ('if log <- logger'); and a re-point checked in the head ('if log := logger then log?').
Worked examples
Compilable examples demonstrating this error and the correct fix:
- ek9 -q 669 (Why can't I reassign an injected component variable?)
How to fix it
- Remove the check and use the injected value directly - it is always there.
- If you wanted a fallback, the fallback runs the other way round: keep the injected component as the default and assign it to a NEW variable only when another value is not set (good_fallback.ek9 in the [EXAMPLE] section below). The injected variable itself is never assigned (E08170).
- If the component may genuinely be absent, it should not be injected: pass it as a parameter, or hold it in an ordinary variable or property that can be unset.
Common causes
- Defensive null-checking habit from Spring/Guice, where an optional injection can be null
- 'require injected?' written to "touch" the variable - use it instead
- The idiom 'x <- injected? <- injected else Default()', which looks like a fallback but never takes it
- Checking a component property declared 'as T!' before calling it
See also
- E08266: checking that an injected component is set (this error)
- E08170: an injected variable is never assigned, ':=?' included
- E08210: an injection reachable from a program is not registered in its application
- E08220: a program reaches an injection but has no application
- E08088: an isSet check that data flow proves is always true
Examples
Every example is compiled by the EK9 compiler: the first fails exactly as captioned, the others fix it.
Fails with E08266: an injected component is always set, so checking that it is set is always true - use the injected value directly; for a fallback, use a new variable ('chosen <- supplied' then 'chosen :=? injected')
#!ek9 defines module error.e08266.bad defines function report() logger as Logger! if logger? logger.log("report") defines component Logger as abstract log() as abstract -> message as String
Fixed: Use the injected component directly - it is always set
#!ek9 defines module error.e08266.good defines function report() logger as Logger! logger.log("report") defines component Logger as abstract log() as abstract -> message as String
Fixed: For a fallback, start from the other value and fill in with :=?
#!ek9 defines module error.e08266.good.fallback defines component Logger as abstract log() as abstract -> message as String defines function choose() -> supplied as Logger logger as Logger! chosen <- supplied chosen :=? logger chosen.log("choose")
Questions and answers
These Q&A entries show E08266 and its fix: