Class WitnessEnumerator
This is the ∃-polarity payoff: the census (M1) says an obligation is undischarged; this turns "undischarged" into a specific witnessing input a developer can paste into a test. It rests on the small-model premise (proven by spike S3, cost interactive) — if a contract can be violated at all it can almost always be violated by one of a type's few representative edge values, so enumerating the value-class vocabulary rather than a full domain is both sound-enough and fast.
Two sources of representatives:
- Built-in leaf types — the real
InputVarietyModelliteral pool viaBuiltinTypeClassModels.classIdsFor(String)(Example 1:count != 0→ZERO="0"). - User constrained types over
[lo,hi]— the MIN/NEAR_MIN/NEAR_MAX/MAX edges of the constraint window (Example 3:base + 20 <= 100over[0,100]→NEAR_MAX=99, since99 + 20 > 100).
Proven by spike S3b (see EK9_SYMBOLIC_SCANNER_SPIKE_REFERENCE.md §5.3). Net-new for
production, tracked: seed InputVarietyModel.literalFor(String, String) for the other ~16 built-ins
(mechanical); read the [lo,hi] window from a user constrained type's constraint AST instead
of being handed it.
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic final recordA concrete counterexample: which value-class it came from, its EK9-source literal, and its value. -
Method Summary
Modifier and TypeMethodDescriptionstatic List<WitnessEnumerator.Witness> constraintEdges(long lo, long hi) The MIN/NEAR_MIN/NEAR_MAX/MAX edge witnesses of a[lo,hi]window, de-duplicated by value and clamped to the window.static List<WitnessEnumerator.Witness> constraintEdgesWithNominal(long lo, long hi) The window's edges PLUS a nominal interior value — the boundary-value-analysis set for a range: both bounds, just inside each bound, and one ordinary value that is not near either end.static Optional<WitnessEnumerator.Witness> firstViolatingBuiltin(String typeName, LongPredicate obligation) Built-in leaf: enumerate the realInputVarietyModelpool and return the first value for whichobligationdoes NOT hold (i.e.static Optional<WitnessEnumerator.Witness> firstViolatingConstrained(long lo, long hi, LongPredicate obligation) User constrained type over[lo,hi]: enumerate the constraint-window edges and return the first violator.
-
Method Details
-
firstViolatingBuiltin
public static Optional<WitnessEnumerator.Witness> firstViolatingBuiltin(String typeName, LongPredicate obligation) Built-in leaf: enumerate the realInputVarietyModelpool and return the first value for whichobligationdoes NOT hold (i.e. the first violator).- Parameters:
typeName- the built-in simple type name (e.g."Integer")obligation- the safe condition that should hold for every input; the witness is where it fails- Returns:
- the first violating witness, or empty if every representative satisfies the obligation
-
firstViolatingConstrained
public static Optional<WitnessEnumerator.Witness> firstViolatingConstrained(long lo, long hi, LongPredicate obligation) User constrained type over[lo,hi]: enumerate the constraint-window edges and return the first violator.- Parameters:
lo- the inclusive lower bound of the constraint windowhi- the inclusive upper bound of the constraint windowobligation- the safe condition that should hold; the witness is where it fails- Returns:
- the first violating edge witness, or empty if every edge satisfies the obligation
-
constraintEdges
The MIN/NEAR_MIN/NEAR_MAX/MAX edge witnesses of a[lo,hi]window, de-duplicated by value and clamped to the window.🔑 The clamp is load-bearing, not tidying. On a narrow window the neighbours fall OUTSIDE it —
constrain as == 5folds to[5,5], whoselo + 1andhi - 1are 6 and 4, neither of which the type can hold. Unclamped, the verifier could reportx=6as a counterexample for a value the type makes unrepresentable (a fabricated counterexample — precisely the "prove configurations impossible" soundness question), and the fuzz generator would emit an argument the constraint rejects. The same clamp absorbs theLong-extreme wrap: a window at[Long.MAX_VALUE, Long.MAX_VALUE]has alo + 1that overflows negative, and it is simply dropped for being out of window.- Parameters:
lo- the inclusive lower boundhi- the inclusive upper bound- Returns:
- the in-window edge witnesses, most significant first; empty when
lo > hi
-
constraintEdgesWithNominal
The window's edges PLUS a nominal interior value — the boundary-value-analysis set for a range: both bounds, just inside each bound, and one ordinary value that is not near either end.🔑 Generation policy, not verification. The plain
constraintEdges(long, long)set is what a bounded-model VERIFIER wants (a violation of a monotone obligation shows up at an extreme, and the engine asksCriticalValuesdirectly for anything interior it cares about). A generated TEST suite wants the nominal case too: drivingRatingover[1000,2000]at 1000/1001/ 1999/2000 alone exercises only the boundary handling and never the ordinary path through the code. Hence a separate entry point rather than widening the edge set both consumers share.The midpoint is
(lo & hi) + ((lo ^ hi) >> 1), the branch-free floor of the average, and it is used because the obvious spellings both break at the extremes:(lo + hi) / 2overflows on a window in the upper half of the range, andlo + (hi - lo) / 2overflows inhi - loon a window spanning most of it — measured, that one silently collapsed the fullLongwindow's midpoint back ontolo. The nominal is dropped when it merely repeats a corner (a window narrower than five values is already fully covered by its edges).- Parameters:
lo- the inclusive lower boundhi- the inclusive upper bound- Returns:
- the edge witnesses followed by the nominal one, when it adds anything
-