Class GenericInputVarietyWidener
- All Implemented Interfaces:
Consumer<CompilableProgram>
The problem. InputVarietyDenominatorRecorder scores each dimension through
EquivalenceClassModel, which has no model for a conceptual T and so returns its
FLOOR — 2 classes at ClassConfidence.SET_UNSET_ONLY. A T-typed dimension
therefore saturates after two calls: Holder.Holder read floor 2, driven 2,
drivenPercent 100.0 however many types the generic was used with. The metric said "fully varied"
about the one dimension it understood least.
The rule. A T dimension's opportunity space is the SUM of the class counts of
every type the generic is actually parameterised with in this program. Driving
Holder of String with a String and Holder of Integer with an Integer are two
genuinely different input situations, and the denominator should say so.
⚠️ The trade-off this accepts. The floor now depends on parameterisations anywhere in the
program, so adding a Holder of Date lowers every Holder percentage — including in
code that never touches Date. That is deliberate: the metric answers "of all the input situations
this generic could be put in, how many did you try?", and a new parameterisation genuinely enlarges
that space. The alternative (a row per parameterisation) keeps rows independent but fragments the
union the numerator achieves. Variety is display-only and never gates, so neither choice can change
a build outcome.
Only conceptual dimensions widen. A receiver typed as the generic itself is NOT widened:
a user class admits set/unset whatever its type argument is, so widening it would inflate without
discriminating. The rule is about T, not about "anything mentioning T".
Why a post-pass, and why here. Parameterisations are created during resolution and live
in whichever module scope first referenced them, so finding them needs a program-wide sweep — and
ModuleScope.getSymbolsForThisScope() is PER FILE, so a per-source listener cannot see them
all. This phase already holds compilableProgramAccess and already runs post-passes, and by
the time it does every per-source recorder has squirrelled its base floor. 🔑 The generic's own
getGenericSymbolReferences() looks like the answer and is NOT — it is never populated
(measured: refs=0 for a generic with two live parameterisations), which its own author's
"still in two minds about adding these references" comment foreshadows.
-
Constructor Details
-
GenericInputVarietyWidener
GenericInputVarietyWidener()
-
-
Method Details
-
accept
- Specified by:
acceptin interfaceConsumer<CompilableProgram>
-