Note [Instantiating field types in stock deriving]

GHC/Tc/Deriv/Generate.hs:3027 compiler 2 tickets

Figuring out what the types of data constructor fields are in `deriving` can
be surprisingly tricky. Here are some examples (adapted from #20375) to set
the scene:

  data Ta = MkTa Int#
  data Tb (x :: TYPE IntRep) = MkTb x

  deriving instance Eq Ta        -- 1.
  deriving instance Eq (Tb a)    -- 2.
  deriving instance Eq (Tb Int#) -- 3.

Example (1) is accepted, as `deriving Eq` has a special case for fields of type
Int#. Example (2) is rejected, however, as the special case for Int# does not
extend to all types of kind (TYPE IntRep).

Example (3) ought to typecheck. If you instantiate the field of type `x` in
MkTb to be Int#, then `deriving Eq` is capable of handling that. We must be
careful, however. If we naïvely use, say, `dataConOrigArgTys` to retrieve the
field types, then we would get `b`, which `deriving Eq` would reject. In
order to handle `deriving Eq` (and, more generally, any stock deriving
strategy) correctly, we /must/ instantiate the field types as needed.
Not doing so led to #20375 and #20387.

In fact, we end up needing to instantiate the field types in quite a few
places:

* When performing validity checks for stock deriving strategies (e.g., in
  GHC.Tc.Deriv.Utils.cond_stdOK)

* When inferring the instance context in
  GHC.Tc.Deriv.Infer.inferConstraintStock

* When generating code for stock-derived instances in
  GHC.Tc.Deriv.{Functor,Generate,Generics}

Repeatedly performing these instantiations in multiple places would be
wasteful, so we build a cache of data constructor field instantiations in
the `dit_dc_inst_arg_env` field of DerivInstTys. Specifically:

1. When beginning to generate code for a stock-derived instance
   `T arg_1 ... arg_n`, the `dit_dc_inst_arg_env` field is created by taking
   each data constructor `dc`, instantiating its field types with
   `dataConInstUnivs dc [arg_1, ..., arg_n]`, and mapping `dc` to the
   instantiated field types in the cache. The `buildDataConInstArgEnv` function
   is responsible for orchestrating this.

2. When a part of the code in GHC.Tc.Deriv.* needs to look up the field
   types, we deliberately avoid using `dataConOrigArgTys`. Instead, we use
   `derivDataConInstArgTys`, which looks up a DataCon's instantiated field
   types in the cache.

StandaloneDeriving is one way for the field types to become instantiated.
Another way is by deriving Functor and related classes, as chronicled in
Note [Inferring the instance context] in GHC.Tc.Deriv.Infer. Here is one such
example:

  newtype Compose (f :: k -> Type) (g :: j -> k) (a :: j) = Compose (f (g a))
    deriving Generic1

This ultimately generates the following instance:

  instance forall (f :: Type -> Type) (g :: j -> Type).
    Functor f => Generic1 (Compose f g) where ...

Note that because of the inferred `Functor f` constraint, `k` was instantiated
to be `Type`. GHC's deriving machinery doesn't realize this until it performs
constraint inference (in GHC.Tc.Deriv.Infer.inferConstraintsStock), however,
which is *after* the initial DerivInstTys has been created. As a result, the
`dit_dc_inst_arg_env` field might need to be updated after constraint inference,
as the inferred constraints might instantiate the field types further.

This is accomplished by way of `substDerivInstTys`, which substitutes all of
the fields in a `DerivInstTys`, including the `dit_dc_inst_arg_env`.
It is important to do this in inferConstraintsStock, as the
deriving/should_compile/T20387 test case will not compile otherwise.

References 1

Referenced by 6