diff options
author | Ryan Scott <ryan.gl.scott@gmail.com> | 2022-02-11 08:49:05 -0500 |
---|---|---|
committer | Ryan Scott <ryan.gl.scott@gmail.com> | 2022-03-08 18:09:28 -0500 |
commit | af72d8961bb1717e2741ab68e6380683b2129bc6 (patch) | |
tree | 092d8857ed2b5d1e7737e27dd8a50833673bba5d /compiler/GHC/Tc/Deriv/Functor.hs | |
parent | a60ddffd75b9ff07b948ea8cdc71f677a4f8d167 (diff) | |
download | haskell-wip/deriving-refactor.tar.gz |
Refactor tcDeriving to generate tyfam insts before any bindingswip/deriving-refactor
Previously, there was an awful hack in `genInst` (now called `genInstBinds`
after this patch) where we had to return a continutation rather than directly
returning the bindings for a derived instance. This was done for staging
purposes, as we had to first infer the instance contexts for derived instances
and then feed these contexts into the continuations to ensure the generated
instance bindings had accurate instance contexts.
`Note [Staging of tcDeriving]` in `GHC.Tc.Deriving` described this confusing
state of affairs.
The root cause of this confusing design was the fact that `genInst` was trying
to generate instance bindings and associated type family instances for derived
instances simultaneously. This really isn't possible, however: as
`Note [Staging of tcDeriving]` explains, one needs to have access to the
associated type family instances before one can properly infer the instance
contexts for derived instances. The use of continuation-returning style was an
attempt to circumvent this dependency, but it did so in an awkward way.
This patch detangles this awkwardness by splitting up `genInst` into two
functions: `genFamInsts` (for associated type family instances) and
`genInstBinds` (for instance bindings). Now, the `tcDeriving` function calls
`genFamInsts` and brings all the family instances into scope before calling
`genInstBinds`. This removes the need for the awkward continuation-returning
style seen in the previous version of `genInst`, making the code easier to
understand.
There are some knock-on changes as well:
1. `hasStockDeriving` now needs to return two separate functions: one that
describes how to generate family instances for a stock-derived instance,
and another that describes how to generate the instance bindings. I factored
out this pattern into a new `StockGenFns` data type.
2. While documenting `StockGenFns`, I realized that there was some
inconsistency regarding which `StockGenFns` functions needed which
arguments. In particular, the function in `GHC.Tc.Deriv.Generics` which
generates `Rep(1)` instances did not take a `SrcSpan` like other `gen_*`
functions did, and it included an extra `[Type]` argument that was entirely
redundant. As a consequence, I refactored the code in
`GHC.Tc.Deriv.Generics` to more closely resemble other `gen_*` functions.
A happy result of all this is that all `StockGenFns` functions now take
exactly the same arguments, which makes everything more uniform.
This is purely a refactoring that should not have any effect on user-observable
behavior. The new design paves the way for an eventual fix for #20719.
Diffstat (limited to 'compiler/GHC/Tc/Deriv/Functor.hs')
-rw-r--r-- | compiler/GHC/Tc/Deriv/Functor.hs | 6 |
1 files changed, 3 insertions, 3 deletions
diff --git a/compiler/GHC/Tc/Deriv/Functor.hs b/compiler/GHC/Tc/Deriv/Functor.hs index 1f781398ca..b3e9fb775c 100644 --- a/compiler/GHC/Tc/Deriv/Functor.hs +++ b/compiler/GHC/Tc/Deriv/Functor.hs @@ -149,7 +149,7 @@ is a similar algorithm for generating `p <$ x` (for some constant `p`): $(coreplace 'a '(tb -> tc) x) = \(y:tb[b/a]) -> $(coreplace 'a' 'tc' (x $(replace 'a 'tb y))) -} -gen_Functor_binds :: SrcSpan -> DerivInstTys -> (LHsBinds GhcPs, BagDerivStuff) +gen_Functor_binds :: SrcSpan -> DerivInstTys -> (LHsBinds GhcPs, Bag AuxBindSpec) -- When the argument is phantom, we can use fmap _ = coerce -- See Note [Phantom types with Functor, Foldable, and Traversable] gen_Functor_binds loc (DerivInstTys{dit_rep_tc = tycon}) @@ -784,7 +784,7 @@ could surprise users if they switch to other types, but Ryan Scott seems to think it's okay to do it for now. -} -gen_Foldable_binds :: SrcSpan -> DerivInstTys -> (LHsBinds GhcPs, BagDerivStuff) +gen_Foldable_binds :: SrcSpan -> DerivInstTys -> (LHsBinds GhcPs, Bag AuxBindSpec) -- When the parameter is phantom, we can use foldMap _ _ = mempty -- See Note [Phantom types with Functor, Foldable, and Traversable] gen_Foldable_binds loc (DerivInstTys{dit_rep_tc = tycon}) @@ -1018,7 +1018,7 @@ removes all such types from consideration. See Note [Generated code for DeriveFoldable and DeriveTraversable]. -} -gen_Traversable_binds :: SrcSpan -> DerivInstTys -> (LHsBinds GhcPs, BagDerivStuff) +gen_Traversable_binds :: SrcSpan -> DerivInstTys -> (LHsBinds GhcPs, Bag AuxBindSpec) -- When the argument is phantom, we can use traverse = pure . coerce -- See Note [Phantom types with Functor, Foldable, and Traversable] gen_Traversable_binds loc (DerivInstTys{dit_rep_tc = tycon}) |