When a constraint references a family unapplied (passed as a
higher-kinded argument, e.g. @CanUpgradeLedgerTables LedgerState@),
the FamilyApp at the use site has no args. The placeholder
synthesizer would emit @LedgerState = ?@ — informationless beyond
the family name itself, which the family node already shows on its
own. Skip these empty-args use sites so the family node sits in the
graph cleanly without a tautological placeholder hanging off it.
Concretizing the bare reference to e.g. @LedgerState (ShelleyBlock
proto era) mk@ would require constraint-solver-like propagation
across the constraint set (matching @l ~ LedgerState (ShelleyBlock
proto era)@ from elsewhere) — work GHC does at typecheck time but
that we don't preserve in the dump.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
if (!anyRelevant) {
const useSites = collectFamilyAppArgs(args, fa);
for (const ua of useSites) {
+ // Skip placeholder synthesis when the family is referenced
+ // *unapplied* (passed as a higher-kinded argument: e.g.
+ // `CanUpgradeLedgerTables LedgerState`). The use-site args
+ // are empty, so the placeholder would say `Family = ?`
+ // — informationless beyond the family name itself, which
+ // the family node already shows.
+ if (!ua || ua.length === 0) continue;
const synFi = {
fiFamily: fa,
fiArgs: ua,