summaryrefslogtreecommitdiff
path: root/compiler
diff options
context:
space:
mode:
authorRichard Eisenberg <rae@cs.brynmawr.edu>2017-08-15 17:22:50 -0400
committerRichard Eisenberg <rae@cs.brynmawr.edu>2017-09-28 21:02:38 -0400
commit7aa000b625c677534c87da43de31c27a2b969183 (patch)
treea8f0f64ff2160ec187e1052433b7c5a75768d718 /compiler
parent5935acdb1302263011c2023d5e7f4ec496c972c0 (diff)
downloadhaskell-7aa000b625c677534c87da43de31c27a2b969183.tar.gz
Fix #13391 by checking for kind-GADTs
The check is a bit gnarly, but I couldn't think of a better way. See the new code in TcTyClsDecls. test case: polykinds/T13391
Diffstat (limited to 'compiler')
-rw-r--r--compiler/basicTypes/DataCon.hs2
-rw-r--r--compiler/typecheck/TcTyClsDecls.hs35
2 files changed, 37 insertions, 0 deletions
diff --git a/compiler/basicTypes/DataCon.hs b/compiler/basicTypes/DataCon.hs
index 9366c2ba11..9b8c527b97 100644
--- a/compiler/basicTypes/DataCon.hs
+++ b/compiler/basicTypes/DataCon.hs
@@ -312,6 +312,8 @@ data DataCon
-- Universally-quantified type vars [a,b,c]
-- INVARIANT: length matches arity of the dcRepTyCon
-- INVARIANT: result type of data con worker is exactly (T a b c)
+ -- COROLLARY: The dcUnivTyVars are always in one-to-one correspondence with
+ -- the tyConTyVars of the parent TyCon
dcUnivTyVars :: [TyVarBinder],
-- Existentially-quantified type vars [x,y]
diff --git a/compiler/typecheck/TcTyClsDecls.hs b/compiler/typecheck/TcTyClsDecls.hs
index f2b60dece3..876784378c 100644
--- a/compiler/typecheck/TcTyClsDecls.hs
+++ b/compiler/typecheck/TcTyClsDecls.hs
@@ -2513,6 +2513,32 @@ checkValidDataCon dflags existential_ok tc con
; checkTc (existential_ok || isVanillaDataCon con)
(badExistential con)
+ ; typeintype <- xoptM LangExt.TypeInType
+ ; let (_, _, eq_specs, _, _, _) = dataConFullSig con
+ -- dataConEqSpec retrieves both the real GADT equalities
+ -- plus any user-written GADT-like equalities. But we don't
+ -- want anything user-written. If we don't exclude user-written
+ -- ones, test case polykinds/T13391a fails.
+
+ invisible_gadt_eq_specs = filter is_invisible_eq_spec eq_specs
+ univ_tvs = dataConUnivTyVars con
+ tc_bndrs = tyConBinders tc
+
+ vis_map :: VarEnv ArgFlag
+ vis_map = zipVarEnv univ_tvs (map tyConBinderArgFlag tc_bndrs)
+
+ -- See Note [Wrong visibility for GADTs] for why we have to build the map
+ -- above instead of just looking at the datacon tyvar binder
+ is_invisible_eq_spec eq_spec
+ = isInvisibleArgFlag arg_flag
+ where
+ eq_tv = eqSpecTyVar eq_spec
+ arg_flag = expectJust "checkValidDataCon" $
+ lookupVarEnv vis_map eq_tv
+
+ ; checkTc (typeintype || null invisible_gadt_eq_specs)
+ (badGADT con invisible_gadt_eq_specs)
+
-- Check that UNPACK pragmas and bangs work out
-- E.g. reject data T = MkT {-# UNPACK #-} Int -- No "!"
-- data T = MkT {-# UNPACK #-} !a -- Can't unpack
@@ -3226,6 +3252,15 @@ badExistential con
2 (vcat [ ppr con <+> dcolon <+> ppr (dataConUserType con)
, parens $ text "Use ExistentialQuantification or GADTs to allow this" ])
+badGADT :: DataCon -> [EqSpec] -> SDoc
+badGADT con eq_specs
+ = hang (text "Data constructor" <+> quotes (ppr con) <+>
+ text "constrains the choice of kind parameter" <> plural eq_specs <> colon)
+ 2 (vcat (map ppr_eq_spec eq_specs)) $$
+ text "Use TypeInType to allow this"
+ where
+ ppr_eq_spec eq_spec = ppr (eqSpecTyVar eq_spec) <+> char '~' <+> ppr (eqSpecType eq_spec)
+
badStupidTheta :: Name -> SDoc
badStupidTheta tc_name
= text "A data type declared in GADT style cannot have a context:" <+> quotes (ppr tc_name)