summaryrefslogtreecommitdiff
path: root/compiler/GHC/Core
diff options
context:
space:
mode:
authorSimon Peyton Jones <simon.peytonjones@gmail.com>2023-03-02 11:26:17 +0000
committerMarge Bot <ben+marge-bot@smart-cactus.org>2023-03-03 11:41:23 -0500
commitbd0536afee5d5f91d99af2ab193b6eee5b1da07a (patch)
treef0db4e794192865368cf8529477a111897e7ad73 /compiler/GHC/Core
parent0c6948957f62d96a8234683fdf67b34369aad240 (diff)
downloadhaskell-bd0536afee5d5f91d99af2ab193b6eee5b1da07a.tar.gz
More fixes for `type data` declarations
This MR fixes #23022 and #23023. Specifically * Beef up Note [Type data declarations] in GHC.Rename.Module, to make invariant (I1) explicit, and to name the several wrinkles. And add references to these specific wrinkles. * Add a Lint check for invariant (I1) above. See GHC.Core.Lint.checkTypeDataConOcc * Disable the `caseRules` for dataToTag# for `type data` values. See Wrinkle (W2c) in the Note above. Fixes #23023. * Refine the assertion in dataConRepArgTys, so that it does not complain about the absence of a wrapper for a `type data` constructor Fixes #23022. Acked-by: Simon Peyton Jones <simon.peytonjones@gmail.com>
Diffstat (limited to 'compiler/GHC/Core')
-rw-r--r--compiler/GHC/Core/DataCon.hs20
-rw-r--r--compiler/GHC/Core/Lint.hs19
-rw-r--r--compiler/GHC/Core/Opt/ConstantFold.hs4
-rw-r--r--compiler/GHC/Core/Utils.hs3
4 files changed, 36 insertions, 10 deletions
diff --git a/compiler/GHC/Core/DataCon.hs b/compiler/GHC/Core/DataCon.hs
index a9e540769e..f54f42d99d 100644
--- a/compiler/GHC/Core/DataCon.hs
+++ b/compiler/GHC/Core/DataCon.hs
@@ -1669,13 +1669,25 @@ dataConOtherTheta dc = dcOtherTheta dc
-- evidence, after any flattening has been done and without substituting for
-- any type variables
dataConRepArgTys :: DataCon -> [Scaled Type]
-dataConRepArgTys (MkData { dcRep = rep
- , dcEqSpec = eq_spec
+dataConRepArgTys (MkData { dcRep = rep
+ , dcEqSpec = eq_spec
, dcOtherTheta = theta
- , dcOrigArgTys = orig_arg_tys })
+ , dcOrigArgTys = orig_arg_tys
+ , dcRepTyCon = tc })
= case rep of
- NoDataConRep -> assert (null eq_spec) $ map unrestricted theta ++ orig_arg_tys
DCR { dcr_arg_tys = arg_tys } -> arg_tys
+ NoDataConRep
+ | isTypeDataTyCon tc -> assert (null theta) $
+ orig_arg_tys
+ -- `type data` declarations can be GADTs (and hence have an eq_spec)
+ -- but no wrapper. They cannot have a theta.
+ -- See Note [Type data declarations] in GHC.Rename.Module
+ -- You might wonder why we ever call dataConRepArgTys for `type data`;
+ -- I think it's because of the call in mkDataCon, which in turn feeds
+ -- into dcRepArity, which in turn is used in mkDataConWorkId.
+ -- c.f. #23022
+ | otherwise -> assert (null eq_spec) $
+ map unrestricted theta ++ orig_arg_tys
-- | The string @package:module.name@ identifying a constructor, which is attached
-- to its info table and used by the GHCi debugger and the heap profiler
diff --git a/compiler/GHC/Core/Lint.hs b/compiler/GHC/Core/Lint.hs
index 2f7ab56b5b..2465a2ffdf 100644
--- a/compiler/GHC/Core/Lint.hs
+++ b/compiler/GHC/Core/Lint.hs
@@ -1021,6 +1021,9 @@ lintIdOcc var nargs
; checkDeadIdOcc var
; checkJoinOcc var nargs
+ ; case isDataConId_maybe var of
+ Nothing -> return ()
+ Just dc -> checkTypeDataConOcc "expression" dc
; usage <- varCallSiteUsage var
@@ -1107,6 +1110,13 @@ checkJoinOcc var n_args
| otherwise
= return ()
+checkTypeDataConOcc :: String -> DataCon -> LintM ()
+-- Check that the Id is not a data constructor of a `type data` declaration
+-- Invariant (I1) of Note [Type data declarations] in GHC.Rename.Module
+checkTypeDataConOcc what dc
+ = checkL (not (isTypeDataTyCon (dataConTyCon dc))) $
+ (text "type data constructor found in a" <+> text what <> colon <+> ppr dc)
+
-- | This function checks that we are able to perform eta expansion for
-- functions with no binding, in order to satisfy invariant I3
-- from Note [Representation polymorphism invariants] in GHC.Core.
@@ -1561,10 +1571,11 @@ lintCoreAlt case_bndr scrut_ty _scrut_mult alt_ty alt@(Alt (DataAlt con) args rh
= zeroUE <$ addErrL (mkNewTyDataConAltMsg scrut_ty alt)
| Just (tycon, tycon_arg_tys) <- splitTyConApp_maybe scrut_ty
= addLoc (CaseAlt alt) $ do
- { -- First instantiate the universally quantified
- -- type variables of the data constructor
- -- We've already check
- lintL (tycon == dataConTyCon con) (mkBadConMsg tycon con)
+ { checkTypeDataConOcc "pattern" con
+ ; lintL (tycon == dataConTyCon con) (mkBadConMsg tycon con)
+
+ -- Instantiate the universally quantified
+ -- type variables of the data constructor
; let { con_payload_ty = piResultTys (dataConRepType con) tycon_arg_tys
; binderMult (Named _) = ManyTy
; binderMult (Anon st _) = scaledMult st
diff --git a/compiler/GHC/Core/Opt/ConstantFold.hs b/compiler/GHC/Core/Opt/ConstantFold.hs
index 2e5c6aabf6..86fdc5cdb5 100644
--- a/compiler/GHC/Core/Opt/ConstantFold.hs
+++ b/compiler/GHC/Core/Opt/ConstantFold.hs
@@ -55,7 +55,7 @@ import GHC.Core.TyCo.Compare( eqType )
import GHC.Core.TyCon
( tyConDataCons_maybe, isAlgTyCon, isEnumerationTyCon
, isNewTyCon, tyConDataCons
- , tyConFamilySize )
+ , tyConFamilySize, isTypeDataTyCon )
import GHC.Core.Map.Expr ( eqCoreExpr )
import GHC.Builtin.PrimOps ( PrimOp(..), tagToEnumKey )
@@ -3184,6 +3184,8 @@ caseRules _ (App (App (Var f) (Type ty)) v) -- dataToTag x
| Just DataToTagOp <- isPrimOpId_maybe f
, Just (tc, _) <- tcSplitTyConApp_maybe ty
, isAlgTyCon tc
+ , not (isTypeDataTyCon tc) -- See wrinkle (W2c) in GHC.Rename.Module
+ -- Note [Type data declarations]
= Just (v, tx_con_dtt ty
, \v -> App (App (Var f) (Type ty)) (Var v))
diff --git a/compiler/GHC/Core/Utils.hs b/compiler/GHC/Core/Utils.hs
index 89824889ef..21ceb2a7bb 100644
--- a/compiler/GHC/Core/Utils.hs
+++ b/compiler/GHC/Core/Utils.hs
@@ -845,7 +845,8 @@ There are two exceptions where we avoid refining a DEFAULT case:
__DEFAULT -> ()
Namely, we do _not_ want to match on `A`, as it doesn't exist at the value
- level!
+ level! See wrinkle (W2b) in Note [Type data declarations] in GHC.Rename.Module
+
Note [Combine identical alternatives]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~