Instantiate field types properly in stock-derived instances
This MR consists of three commits. The first two commits are preparatory refactorings that pave the way for the third commit (Instantiate field types properly in stock-derived instances
), which is the main thrust of the MR. I've reproduced the commit message for this commit below:
Previously, the deriving
machinery was very loosey-goosey about how it used
the types of data constructor fields when generating code. It would usually
just consult dataConOrigArgTys
, which returns the uninstantiated field
types of each data constructor. Usually, you can get away with this, but
issues #20375 (closed) and #20387 (closed) revealed circumstances where this approach fails.
Instead, when generated code for a stock-derived instance
C (T arg_1 ... arg_n)
, one must take care to instantiate the field types of
each data constructor with arg_1 ... arg_n
. The particulars of how this is
accomplished is described in the new
Note [Instantiating field types in stock deriving]
in
GHC.Tc.Deriv.Generate
. Some highlights:
-
DerivInstTys
now has a newdit_dc_inst_arg_env :: DataConEnv [Type]
field that caches the instantiated field types of each data constructor. Whenever we need to consult the field types somewhere inGHC.Tc.Deriv.*
we avoid usingdataConOrigArgTys
and instead look it up indit_dc_inst_arg_env
. - Because
DerivInstTys
now stores the instantiated field types of each constructor, some of the details of theGHC.Tc.Deriv.Generics.mkBindsRep
function were able to be simplified. In particular, we no longer need to apply a substitution to instantiate the field types in aRep(1)
instance, as that is already done for us byDerivInstTys
. We still need a substitution to implement the "wrinkle" section ofNote [Generating a correctly typed Rep instance]
, but the code is nevertheless much simpler than before. - The
tyConInstArgTys
function has been removed in favor of the newGHC.Core.DataCon.dataConInstUnivs
function, which is really the proper tool for the job.dataConInstUnivs
is much liketyConInstArgTys
except that it takes a data constructor, not a type constructor, as an argument, and it adds extra universal type variables from that data constructor at the end of the returned list if need be.dataConInstUnivs
takes care to instantiate the kinds of the universal type variables at the end, thereby avoiding a bug intyConInstArgTys
discovered in #20387 (closed) (comment 377037).
Fixes #20375 (closed). Fixes #20387 (closed).