ad86061e
by Simon Peyton Jones at 2026-10-06T16:21:03+01:00
Fixing perf regressions in T27336, T9872d, T14683
What caused each regression
1. T27336 and T9872d: mkKindCo lost its "kinds are equal ⇒ Refl" case when it
moved into TyCo/Make.hs. As a result, toPhantomCo kept the whole type-family
proof inside phantom UnivCos, which reached 22M coercion nodes on T27336.
2. T14683, first part: mkUnivCo lost its eqType short cut, which left reflexive
phantom casts in place.
3. T14683, second part: isReflForAllCo used == instead of eqForAllVis. That
turned a forall {a} vs forall a coercion into a real cast, and the cast caused
the extra simplifier iteration.
4. T27336 residual: zonk_tcapp took mk as an unknown function, so each result
thunk was one word bigger. {-# INLINE zonk_tcapp #-} fixed it.
What changed
- mkKindCo and mkUnivCo moved to GHC.Core.Coercion, with Note [mkKindCo and
mkUnivCo] explaining why they live there. Make.hs gets them via
Coercion.hs-boot, and I removed three unused declarations from that boot file.
- ForAllTyFlag moved, with all its functions and its Outputable/Binary
instances, from L.H.S.Specificity into GHC.Types.Var. That module also now holds:
- eqForAllVis and cmpForAllVis, still re-exported from Compare
- the new isCoreTyLamForAllTyFlag
- the new cmpForAllTyFlagExactly
- ForAllTyFlag has no Eq or Ord, so the compiler now checks that every
comparison follows Note [Comparing visibility].
- IfaceForAllTyFlag is a new newtype in GHC.Iface.Type with exact Eq/Ord (via
cmpForAllTyFlagExactly), which the interface deduplication table needs. Its
Binary instance delegates to ForAllTyFlag's, so the .hi format is unchanged.
- Eq (HieType a) is now hand-written, so that the public HIE API keeps its ForAllTyFlag field.
Plus:
- (FT2)/(FC7) covar-binder checks in mkForAllTy, assertGoodForAllCo and Lint now
use isCoreTyLamForAllTyFlag. These checks are slightly weaker than before: they
no longer catch an Inferred covar binder.
- ty_co_match now compares visibilities with eqForAllVis. It's slightly more
permissive, but consistent with eqType.
- mkEtaForAllMCo now returns MRefl for any invisible flag. That matches what
mkForAllCo produces now anyway.
- Unchanged behaviour: comparisons against a fixed flag (in Type.hs,
Tc/Gen/App.hs, Tc/Errors/Ppr.hs, Tc/TyCl/Instance.hs, and the Iface printing
code) use the exact predicates, such as isInferredForAllTyFlag and
isSpecifiedForAllTyFlag. They behave exactly as before.