diff options
author | Richard Eisenberg <rae@cs.brynmawr.edu> | 2017-08-15 17:22:50 -0400 |
---|---|---|
committer | Richard Eisenberg <rae@cs.brynmawr.edu> | 2017-09-28 21:02:38 -0400 |
commit | 7aa000b625c677534c87da43de31c27a2b969183 (patch) | |
tree | a8f0f64ff2160ec187e1052433b7c5a75768d718 /compiler | |
parent | 5935acdb1302263011c2023d5e7f4ec496c972c0 (diff) | |
download | haskell-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.hs | 2 | ||||
-rw-r--r-- | compiler/typecheck/TcTyClsDecls.hs | 35 |
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) |