summaryrefslogtreecommitdiff
path: root/compiler/GHC/Core/DataCon.hs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/GHC/Core/DataCon.hs')
-rw-r--r--compiler/GHC/Core/DataCon.hs56
1 files changed, 56 insertions, 0 deletions
diff --git a/compiler/GHC/Core/DataCon.hs b/compiler/GHC/Core/DataCon.hs
index dc14f2dcc3..e95e68441f 100644
--- a/compiler/GHC/Core/DataCon.hs
+++ b/compiler/GHC/Core/DataCon.hs
@@ -41,6 +41,7 @@ module GHC.Core.DataCon (
dataConOtherTheta,
dataConInstArgTys, dataConOrigArgTys, dataConOrigResTy,
dataConInstOrigArgTys, dataConRepArgTys,
+ dataConInstUnivs,
dataConFieldLabels, dataConFieldType, dataConFieldType_maybe,
dataConSrcBangs,
dataConSourceArity, dataConRepArity,
@@ -71,6 +72,7 @@ import GHC.Core.Type as Type
import GHC.Core.Coercion
import GHC.Core.Unify
import GHC.Core.TyCon
+import GHC.Core.TyCo.Subst
import GHC.Core.Multiplicity
import {-# SOURCE #-} GHC.Types.TyThing
import GHC.Types.FieldLabel
@@ -80,6 +82,7 @@ import GHC.Types.Name
import GHC.Builtin.Names
import GHC.Core.Predicate
import GHC.Types.Var
+import GHC.Types.Var.Env
import GHC.Types.Basic
import GHC.Data.FastString
import GHC.Unit.Types
@@ -1489,6 +1492,59 @@ dataConInstOrigArgTys dc@(MkData {dcOrigArgTys = arg_tys,
tyvars = univ_tvs ++ ex_tvs
subst = zipTCvSubst tyvars inst_tys
+-- | Given a data constructor @dc@ with /n/ universally quantified type
+-- variables @a_{1}@, @a_{2}@, ..., @a_{n}@, and given a list of argument
+-- types @dc_args@ of length /m/ where /m/ <= /n/, then:
+--
+-- @
+-- dataConInstUnivs dc dc_args
+-- @
+--
+-- Will return:
+--
+-- @
+-- [dc_arg_{1}, dc_arg_{2}, ..., dc_arg_{m}, a_{m+1}, ..., a_{n}]
+-- @
+--
+-- That is, return the list of universal type variables with
+-- @a_{1}@, @a_{2}@, ..., @a_{m}@ instantiated with
+-- @dc_arg_{1}@, @dc_arg_{2}@, ..., @dc_arg_{m}@. It is possible for @m@ to
+-- be less than @n@, in which case the remaining @n - m@ elements will simply
+-- be universal type variables (with their kinds possibly instantiated).
+--
+-- Examples:
+--
+-- * Given the data constructor @D :: forall a b. Foo a b@ and
+-- @dc_args@ @[Int, Bool]@, then @dataConInstUnivs D dc_args@ will return
+-- @[Int, Bool]@.
+--
+-- * Given the data constructor @D :: forall a b. Foo a b@ and
+-- @dc_args@ @[Int]@, then @@dataConInstUnivs D dc_args@ will return
+-- @[Int, b]@.
+--
+-- * Given the data constructor @E :: forall k (a :: k). Bar k a@ and
+-- @dc_args@ @[Type]@, then @@dataConInstUnivs D dc_args@ will return
+-- @[Type, (a :: Type)]@.
+--
+-- This is primarily used in @GHC.Tc.Deriv.*@ in service of instantiating data
+-- constructors' field types.
+-- See @Note [Instantiating field types in stock deriving]@ for a notable
+-- example of this.
+dataConInstUnivs :: DataCon -> [Type] -> [Type]
+dataConInstUnivs dc dc_args = chkAppend dc_args $ map mkTyVarTy dc_args_suffix
+ where
+ (dc_univs_prefix, dc_univs_suffix)
+ = -- Assert that m <= n
+ assertPpr (dc_args `leLength` dataConUnivTyVars dc)
+ (text "dataConInstUnivs"
+ <+> ppr dc_args
+ <+> ppr (dataConUnivTyVars dc)) $
+ splitAt (length dc_args) $ dataConUnivTyVars dc
+ (_, dc_args_suffix) = substTyVarBndrs prefix_subst dc_univs_suffix
+ prefix_subst = mkTvSubst prefix_in_scope prefix_env
+ prefix_in_scope = mkInScopeSet $ tyCoVarsOfTypes dc_args
+ prefix_env = zipTyEnv dc_univs_prefix dc_args
+
-- | Returns the argument types of the wrapper, excluding all dictionary arguments
-- and without substituting for any type variables
dataConOrigArgTys :: DataCon -> [Scaled Type]