Class AssignIfUnsetDecidedOrError
java.lang.Object
org.ek9lang.compiler.common.RuleSupport
org.ek9lang.compiler.common.TypedSymbolAccess
org.ek9lang.compiler.phase5.AssignIfUnsetDecidedOrError
- All Implemented Interfaces:
Consumer<EK9Parser.AssignmentStatementContext>
final class AssignIfUnsetDecidedOrError
extends TypedSymbolAccess
implements Consumer<EK9Parser.AssignmentStatementContext>
THE check of an assign-if-unset statement (
:=?) whose outcome the value tracker has DECIDED - both
outcomes, one class, one reading of the target (E08095 and E08097).
:=? assigns ONLY when the target is unset. It is the same ValueTrackingAnalyzer question already
asked by RedundantIsSetCheckOrError, because :=? is an isSet check plus a conditional assign:
- Target surely SET - E08095: the assignment can never apply; the right-hand side is never evaluated and
its value is silently lost. The motivating case is a record property initialised to a set value and then
assigned in a
pureconstructor, where:=?is the only assignment form permitted (E08100):Connections up as Boolean: false // SET Connections() as pure -> isUp as Boolean up :=? isUp // E08095 - never applies, isUp is thrown away - Target surely UNSET - E08097: the assignment always applies, so it is a plain
:=written as a conditional one - a misunderstanding of what:=?is for (a fallback when a value MAY be missing):greeting as String: String() // String() makes an UNSET String greeting :=? "Hello, World" // E08097 - always applies; use ':=' or declare it with the value
Not an error where:=would be refused: in apurescope:=?is the ONLY reassignment (E08100), so a surely-unset target is exactly how a pure constructor initialises its fields - the purity test is the one E08100 uses (isPureReassignmentDisallowed). Not an error in a guard (if x :=? f()): there:=?also gates the body, which:=would not; a decided gate is E08088/E08089's to report. (A dynamic function's capture is not known at the start of its body at all - the body runs on each CALL - so the tracker holds nothing decided about it there:PreIRListener.seedCapturedVariables.) And never on a target DECLARED WITH NO VALUE (x as T?,<- rtn as T?, aT?property filled in a constructor -UninitialisedAtDeclaration.declaredWithNoValue(ISymbol)): filling that never-written slot is the case:=?exists for (Steve, 2026-10-07 and 2026-10-27;EK9_ABSENCE_UNOBSERVABLE.md). E08097 is about a value MADE unset (T(), or narrowed byif not x?) and then filled as if it might not be.
🔑 Steve's rule (2026-10-26): fire ONLY when SURE. UNKNOWN is always silent - EK9 has no warnings, so an error must be certain. The two outcomes are made sure differently inside a loop, because the body is walked once from the pre-loop state:
- E08095 is suppressed in every loop body, mirroring
RedundantIsSetCheckOrError(unchanged). - E08097 waits for every enclosing loop to end (
ValueTrackingAnalyzer.reportWhenSure(ISymbol, Runnable), as E08096 does): the:=?itself writes its target, so in a loop the finding is dropped - the second pass finds it set - unless the target was given its unset value on every path of the SAME pass before it.
-
Field Summary
Fields inherited from class RuleSupport
errorListener, symbolsAndScopes -
Constructor Summary
ConstructorsConstructorDescriptionAssignIfUnsetDecidedOrError(SymbolsAndScopes symbolsAndScopes, ErrorListener errorListener, ValueTrackingAnalyzer valueTracker) -
Method Summary
Methods inherited from class TypedSymbolAccess
emitTypeNotResolvedError, getRecordedAndTypedSymbol, isAlreadyInError, isProcessingScopePure, isPureReassignmentDisallowed, recordATypedSymbol
-
Constructor Details
-
AssignIfUnsetDecidedOrError
AssignIfUnsetDecidedOrError(SymbolsAndScopes symbolsAndScopes, ErrorListener errorListener, ValueTrackingAnalyzer valueTracker)
-
-
Method Details
-
accept
- Specified by:
acceptin interfaceConsumer<EK9Parser.AssignmentStatementContext>
-