Refactor TcDeriv to validity-check less in anyclass/via deriving (#13154)
Due to the way DerivEnv
is currently structured, there is an
invariant that every derived instance must consist of a class applied
to a non-empty list of argument types, where the last argument must
be an application of a type constructor to some arguments. This works
for many cases, but there are also some design patterns in standalone
anyclass
/via
deriving that are made impossible due to enforcing
this invariant, as documented in #13154 (closed).
This fixes #13154 (closed) by refactoring TcDeriv
and friends to perform
fewer validity checks when using the anyclass
or via
strategies.
The highlights are as followed:
- Five fields of
DerivEnv
have been factored out into a newDerivInstTys
data type. These fields only make sense for instances that satisfy the invariant mentioned above, soDerivInstTys
is now only used instock
andnewtype
deriving, but not in other deriving strategies. - There is now a
Note [DerivEnv and DerivSpecMechanism]
describing the bullet point above in more detail, as well as explaining the exact requirements that each deriving strategy imposes. - I've refactored
mkEqnHelp
's call graph to be slightly less complicated. Instead of the previousmkDataTypeEqn
/mkNewTypeEqn
dichotomy, there is now a single entrypointmk_eqn
. - Various bits of code were tweaked so as not to use fields that are
specific to
DerivInstTys
so that they may be used by all deriving strategies, since not all deriving strategies useDerivInstTys
.