diff --git a/compiler/basicTypes/DataCon.lhs b/compiler/basicTypes/DataCon.lhs index d46759c7fdfde142c1d700be7a913bf333813752..c82f018962cbbd818b0b999817b65a234f396ab7 100644 --- a/compiler/basicTypes/DataCon.lhs +++ b/compiler/basicTypes/DataCon.lhs @@ -45,8 +45,8 @@ module DataCon ( deepSplitProductType_maybe, -- ** Promotion related functions - promoteType, isPromotableType, isPromotableTyCon, - buildPromotedTyCon, buildPromotedDataCon, + isPromotableTyCon, promoteTyCon, + promoteDataCon, promoteDataCon_maybe ) where #include "HsVersions.h" @@ -386,9 +386,11 @@ data DataCon -- An entirely separate wrapper function is built in TcTyDecls dcIds :: DataConIds, - dcInfix :: Bool -- True <=> declared infix + dcInfix :: Bool, -- True <=> declared infix -- Used for Template Haskell and 'deriving' only -- The actual fixity is stored elsewhere + + dcPromoted :: Maybe TyCon -- The promoted TyCon if this DataCon is promotable } deriving Data.Typeable.Typeable @@ -519,10 +521,7 @@ mkDataCon name declared_infix -- so the error is detected properly... it's just that asaertions here -- are a little dodgy. - = -- ASSERT( not (any isEqPred theta) ) - -- We don't currently allow any equality predicates on - -- a data constructor (apart from the GADT ones in eq_spec) - con + = con where is_vanilla = null ex_tvs && null eq_spec && null theta con = MkData {dcName = name, dcUnique = nameUnique name, @@ -537,7 +536,8 @@ mkDataCon name declared_infix dcStrictMarks = arg_stricts, dcRepStrictness = rep_arg_stricts, dcFields = fields, dcTag = tag, dcRepType = ty, - dcIds = ids } + dcIds = ids, + dcPromoted = mb_promoted } -- Strictness marks for source-args -- *after unboxing choices*, @@ -559,6 +559,16 @@ mkDataCon name declared_infix mkFunTys rep_arg_tys $ mkTyConApp rep_tycon (mkTyVarTys univ_tvs) + mb_promoted + | is_vanilla -- No existentials or context + , all (isLiftedTypeKind . tyVarKind) univ_tvs + , all isPromotableType orig_arg_tys + = Just (mkPromotedDataCon con name (getUnique name) prom_kind arity) + | otherwise + = Nothing + prom_kind = promoteType (dataConUserType con) + arity = dataConSourceArity con + eqSpecPreds :: [(TyVar,Type)] -> ThetaType eqSpecPreds spec = [ mkEqPred (mkTyVarTy tv) ty | (tv,ty) <- spec ] @@ -978,24 +988,22 @@ computeRep stricts tys %* * %************************************************************************ -These two 'buildPromoted..' functions are here because +These two 'promoted..' functions are here because * They belong together - * 'buildPromotedTyCon' is used by promoteType - * 'buildPromotedTyCon' depends on DataCon stuff + * 'promoteTyCon' is used by promoteType + * 'prmoteDataCon' depends on DataCon stuff \begin{code} -buildPromotedTyCon :: TyCon -> TyCon -buildPromotedTyCon tc - = mkPromotedTyCon tc (promoteKind (tyConKind tc)) +promoteDataCon :: DataCon -> TyCon +promoteDataCon (MkData { dcPromoted = Just tc }) = tc +promoteDataCon dc = pprPanic "promoteDataCon" (ppr dc) + +promoteDataCon_maybe :: DataCon -> Maybe TyCon +promoteDataCon_maybe (MkData { dcPromoted = mb_tc }) = mb_tc -buildPromotedDataCon :: DataCon -> TyCon -buildPromotedDataCon dc - = ASSERT ( isPromotableType ty ) - mkPromotedDataCon dc (getName dc) (getUnique dc) kind arity - where - ty = dataConUserType dc - kind = promoteType ty - arity = dataConSourceArity dc +promoteTyCon :: TyCon -> TyCon +promoteTyCon tc + = mkPromotedTyCon tc (promoteKind (tyConKind tc)) \end{code} Note [Promoting a Type to a Kind] @@ -1017,16 +1025,11 @@ The transformation from type to kind is done by promoteType \begin{code} isPromotableType :: Type -> Bool -isPromotableType ty - = all (isLiftedTypeKind . tyVarKind) tvs - && go rho - where - (tvs, rho) = splitForAllTys ty - go (TyConApp tc tys) | Just n <- isPromotableTyCon tc - = tys `lengthIs` n && all go tys - go (FunTy arg res) = go arg && go res - go (TyVarTy tvar) = tvar `elem` tvs - go _ = False +isPromotableType (TyConApp tc tys) + | Just n <- isPromotableTyCon tc = tys `lengthIs` n && all isPromotableType tys +isPromotableType (FunTy arg res) = isPromotableType arg && isPromotableType res +isPromotableType (TyVarTy {}) = True +isPromotableType _ = False -- If tc's kind is [ *^n -> * ] returns [ Just n ], else returns [ Nothing ] isPromotableTyCon :: TyCon -> Maybe Int @@ -1048,7 +1051,7 @@ promoteType ty kvs = [ mkKindVar (tyVarName tv) superKind | tv <- tvs ] env = zipVarEnv tvs kvs - go (TyConApp tc tys) = mkTyConApp (buildPromotedTyCon tc) (map go tys) + go (TyConApp tc tys) = mkTyConApp (promoteTyCon tc) (map go tys) go (FunTy arg res) = mkArrowKind (go arg) (go res) go (TyVarTy tv) | Just kv <- lookupVarEnv env tv = TyVarTy kv diff --git a/compiler/iface/TcIface.lhs b/compiler/iface/TcIface.lhs index 55b997853c2cc9f1446ec9781ffac7a1866ca327..ae7abf41b998d8811c60d0faea67adcd71b2dc3a 100644 --- a/compiler/iface/TcIface.lhs +++ b/compiler/iface/TcIface.lhs @@ -1362,7 +1362,7 @@ tcIfaceTyCon (IfaceTc name) ; case thing of -- A "type constructor" can be a promoted data constructor -- c.f. Trac #5881 ATyCon tc -> return tc - ADataCon dc -> return (buildPromotedDataCon dc) + ADataCon dc -> return (promoteDataCon dc) _ -> pprPanic "tcIfaceTyCon" (ppr name $$ ppr thing) } tcIfaceKindCon :: IfaceTyCon -> IfL TyCon @@ -1372,7 +1372,7 @@ tcIfaceKindCon (IfaceTc name) -- c.f. Trac #5881 ATyCon tc | isSuperKind (tyConKind tc) -> return tc -- Mainly just '*' or 'AnyK' - | otherwise -> return (buildPromotedTyCon tc) + | otherwise -> return (promoteTyCon tc) _ -> pprPanic "tcIfaceKindCon" (ppr name $$ ppr thing) } diff --git a/compiler/prelude/TysWiredIn.lhs b/compiler/prelude/TysWiredIn.lhs index 78e1f74b4d9833616e2506e513175d57068f954f..5071b33e9a55b5a8c612de165782ea2492983c6e 100644 --- a/compiler/prelude/TysWiredIn.lhs +++ b/compiler/prelude/TysWiredIn.lhs @@ -322,10 +322,10 @@ tupleTyCon UnboxedTuple i = fst (unboxedTupleArr ! i) tupleTyCon ConstraintTuple i = fst (factTupleArr ! i) promotedTupleTyCon :: TupleSort -> Arity -> TyCon -promotedTupleTyCon sort i = buildPromotedTyCon (tupleTyCon sort i) +promotedTupleTyCon sort i = promoteTyCon (tupleTyCon sort i) promotedTupleDataCon :: TupleSort -> Arity -> TyCon -promotedTupleDataCon sort i = buildPromotedDataCon (tupleCon sort i) +promotedTupleDataCon sort i = promoteDataCon (tupleCon sort i) tupleCon :: TupleSort -> Arity -> DataCon tupleCon sort i | i > mAX_TUPLE_SIZE = snd (mk_tuple sort i) -- Build one specially @@ -605,7 +605,7 @@ mkPromotedListTy :: Type -> Type mkPromotedListTy ty = mkTyConApp promotedListTyCon [ty] promotedListTyCon :: TyCon -promotedListTyCon = buildPromotedTyCon listTyCon +promotedListTyCon = promoteTyCon listTyCon nilDataCon :: DataCon nilDataCon = pcDataCon nilDataConName alpha_tyvar [] listTyCon diff --git a/compiler/types/TyCon.lhs b/compiler/types/TyCon.lhs index 147e16dbe1dbc3ab03bf3bb91cee8f14e754c1c4..5398adc8f1fdea0f519089527926b539b4e682a5 100644 --- a/compiler/types/TyCon.lhs +++ b/compiler/types/TyCon.lhs @@ -595,7 +595,7 @@ via the PromotedTyCon alternative in TyCon. kind signature on the forall'd variable; so the tc_kind field of PromotedTyCon is not identical to the dataConUserType of the DataCon. But it's the same modulo changing the variable kinds, - done by Kind.promoteType. + done by DataCon.promoteType. * Small note: We promote the *user* type of the DataCon. Eg data T = MkT {-# UNPACK #-} !(Bool, Bool)