X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=compiler%2FbasicTypes%2FMkId.lhs;h=54bbae9ea47d9a34c1bdadbaf5c71ac48ec66d7e;hb=d76c18e05f6366c23144624b696a02fbaa6d26e8;hp=93369f5cc33059480933e6b544725e90e2dc3239;hpb=19e64b50409a331ddf816cb4c7f33d646dabd43a;p=ghc-hetmet.git diff --git a/compiler/basicTypes/MkId.lhs b/compiler/basicTypes/MkId.lhs index 93369f5..54bbae9 100644 --- a/compiler/basicTypes/MkId.lhs +++ b/compiler/basicTypes/MkId.lhs @@ -47,7 +47,7 @@ import TysPrim ( openAlphaTyVars, alphaTyVar, alphaTy, import TysWiredIn ( charTy, mkListTy ) import PrelRules ( primOpRules ) import Type ( TyThing(..), mkForAllTy, tyVarsOfTypes, - newTyConInstRhs, mkTopTvSubst, substTyVar ) + newTyConInstRhs, mkTopTvSubst, substTyVar, substTy ) import TcGadt ( gadtRefine, refineType, emptyRefinement ) import HsBinds ( ExprCoFn(..), isIdCoercion ) import Coercion ( mkSymCoercion, mkUnsafeCoercion, isEqPred ) @@ -57,12 +57,14 @@ import TcType ( Type, ThetaType, mkDictTy, mkPredTys, mkPredTy, isUnLiftedType, mkForAllTys, mkTyVarTy, tyVarsOfType, tcSplitFunTys, tcSplitForAllTys, dataConsStupidTheta ) -import CoreUtils ( exprType, dataConOrigInstPat ) +import CoreUtils ( exprType, dataConOrigInstPat, mkCoerce ) import CoreUnfold ( mkTopUnfolding, mkCompulsoryUnfolding ) import Literal ( nullAddrLit, mkStringLit ) import TyCon ( TyCon, isNewTyCon, tyConDataCons, FieldLabel, - tyConStupidTheta, isProductTyCon, isDataTyCon, isRecursiveTyCon, - newTyConCo ) + tyConStupidTheta, isProductTyCon, isDataTyCon, + isRecursiveTyCon, isFamInstTyCon, + tyConFamInst_maybe, tyConFamilyCoercion_maybe, + newTyConCo_maybe ) import Class ( Class, classTyCon, classSelIds ) import Var ( Id, TyVar, Var, setIdType ) import VarSet ( isEmptyVarSet, subVarSet, varSetElems ) @@ -70,12 +72,13 @@ import Name ( mkFCallName, mkWiredInName, Name, BuiltInSyntax(..)) import OccName ( mkOccNameFS, varName ) import PrimOp ( PrimOp, primOpSig, primOpOcc, primOpTag ) import ForeignCall ( ForeignCall ) -import DataCon ( DataCon, DataConIds(..), dataConTyCon, dataConUnivTyVars, +import DataCon ( DataCon, DataConIds(..), dataConTyCon, + dataConUnivTyVars, dataConFieldLabels, dataConRepArity, dataConResTys, dataConRepArgTys, dataConRepType, dataConFullSig, dataConStrictMarks, dataConExStricts, splitProductType, isVanillaDataCon, dataConFieldType, - deepSplitProductType + deepSplitProductType, ) import Id ( idType, mkGlobalId, mkVanillaGlobal, mkSysLocal, mkTemplateLocals, mkTemplateLocalsNum, mkExportedLocalId, @@ -92,6 +95,7 @@ import NewDemand ( mkStrictSig, DmdResult(..), import DmdAnal ( dmdAnalTopRhs ) import CoreSyn import Unique ( mkBuiltinUnique, mkPrimOpIdUnique ) +import Maybe ( fromJust ) import Maybes import PrelNames import Util ( dropList, isSingleton ) @@ -187,22 +191,48 @@ Notice that Making an explicit case expression allows the simplifier to eliminate it in the (common) case where the constructor arg is already evaluated. +[Wrappers for data instance tycons] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +In the case of data instances, the wrapper also applies the coercion turning +the representation type into the family instance type to cast the result of +the wrapper. For example, consider the declarations + + data family Map k :: * -> * + data instance Map (a, b) v = MapPair (Map a (Pair b v)) + +The tycon to which the datacon MapPair belongs gets a unique internal name of +the form :R123Map, and we call it the representation tycon. In contrast, Map +is the family tycon (accessible via tyConFamInst_maybe). The wrapper and work +of MapPair get the types + + $WMapPair :: forall a b v. Map a (Map a b v) -> Map (a, b) v + $wMapPair :: forall a b v. Map a (Map a b v) -> :R123Map a b v + +which implies that the wrapper code will have to apply the coercion moving +between representation and family type. It is accessible via +tyConFamilyCoercion_maybe and has kind + + Co123Map a b v :: {Map (a, b) v :=: :R123Map a b v} + +This coercion is conditionally applied by wrapFamInstBody. \begin{code} mkDataConIds :: Name -> Name -> DataCon -> DataConIds mkDataConIds wrap_name wkr_name data_con | isNewTyCon tycon - = DCIds Nothing nt_work_id -- Newtype, only has a worker + = DCIds Nothing nt_work_id -- Newtype, only has a worker - | any isMarkedStrict all_strict_marks -- Algebraic, needs wrapper - || not (null eq_spec) + | any isMarkedStrict all_strict_marks -- Algebraic, needs wrapper + || not (null eq_spec) -- NB: LoadIface.ifaceDeclSubBndrs + || isFamInstTyCon tycon -- depends on this test = DCIds (Just alg_wrap_id) wrk_id - | otherwise -- Algebraic, no wrapper + | otherwise -- Algebraic, no wrapper = DCIds Nothing wrk_id where - (univ_tvs, ex_tvs, eq_spec, theta, orig_arg_tys) = dataConFullSig data_con - tycon = dataConTyCon data_con + (univ_tvs, ex_tvs, eq_spec, + theta, orig_arg_tys) = dataConFullSig data_con + tycon = dataConTyCon data_con ----------- Wrapper -------------- -- We used to include the stupid theta in the wrapper's args @@ -212,7 +242,13 @@ mkDataConIds wrap_name wkr_name data_con subst = mkTopTvSubst eq_spec dict_tys = mkPredTys theta result_ty_args = map (substTyVar subst) univ_tvs - result_ty = mkTyConApp tycon result_ty_args + result_ty = case tyConFamInst_maybe tycon of + -- ordinary constructor + Nothing -> mkTyConApp tycon result_ty_args + -- family instance constructor + Just (familyTyCon, + instTys) -> + mkTyConApp familyTyCon (map (substTy subst) instTys) wrap_ty = mkForAllTys wrap_tvs $ mkFunTys dict_tys $ mkFunTys orig_arg_tys $ result_ty -- NB: watch out here if you allow user-written equality @@ -256,7 +292,7 @@ mkDataConIds wrap_name wkr_name data_con -- RetCPR is only true for products that are real data types; -- that is, not unboxed tuples or [non-recursive] newtypes - ----------- Wrappers for newtypes -------------- + ----------- Workers for newtypes -------------- nt_work_id = mkGlobalId (DataConWrapId data_con) wkr_name wrap_ty nt_work_info nt_work_info = noCafIdInfo -- The NoCaf-ness is set by noCafIdInfo `setArityInfo` 1 -- Arity 1 @@ -302,10 +338,11 @@ mkDataConIds wrap_name wkr_name data_con (zip (dict_args ++ id_args) all_strict_marks) i3 [] - con_app _ rep_ids = Var wrk_id `mkTyApps` result_ty_args - `mkVarApps` ex_tvs - `mkTyApps` map snd eq_spec - `mkVarApps` reverse rep_ids + con_app _ rep_ids = wrapFamInstBody tycon result_ty_args $ + Var wrk_id `mkTyApps` result_ty_args + `mkVarApps` ex_tvs + `mkTyApps` map snd eq_spec + `mkVarApps` reverse rep_ids (dict_args,i2) = mkLocals 1 dict_tys (id_args,i3) = mkLocals i2 orig_arg_tys @@ -344,6 +381,28 @@ mAX_CPR_SIZE = 10 mkLocals i tys = (zipWith mkTemplateLocal [i..i+n-1] tys, i+n) where n = length tys + +-- If the type constructor is a representation type of a data instance, wrap +-- the expression into a cast adjusting the expression type, which is an +-- instance of the representation type, to the corresponding instance of the +-- family instance type. +-- +wrapFamInstBody :: TyCon -> [Type] -> CoreExpr -> CoreExpr +wrapFamInstBody tycon args result_expr + | Just co_con <- tyConFamilyCoercion_maybe tycon + = mkCoerce (mkSymCoercion (mkTyConApp co_con args)) result_expr + | otherwise + = result_expr + +-- Apply the coercion in the opposite direction. +-- +unwrapFamInstBody :: TyCon -> [Type] -> CoreExpr -> CoreExpr +unwrapFamInstBody tycon args result_expr + | Just co_con <- tyConFamilyCoercion_maybe tycon + = mkCoerce (mkTyConApp co_con args) result_expr + | otherwise + = result_expr + \end{code} @@ -592,7 +651,7 @@ mkRecordSelId tycon field_label -- If we have e = MkT (MkS (PairInt 0 1)) and some body expecting a list of -- ids, we get (modulo int passing) -- --- case (e `cast` (sym CoT)) `cast` (sym CoS) of +-- case (e `cast` CoT) `cast` CoS of -- PairInt a b -> body [a,b] -- -- The Ints passed around are just for creating fresh locals @@ -782,26 +841,39 @@ wrapNewTypeBody :: TyCon -> [Type] -> CoreExpr -> CoreExpr -- The wrapper for the data constructor for a newtype looks like this: -- newtype T a = MkT (a,Int) -- MkT :: forall a. (a,Int) -> T a --- MkT = /\a. \(x:(a,Int)). x `cast` CoT a +-- MkT = /\a. \(x:(a,Int)). x `cast` sym (CoT a) -- where CoT is the coercion TyCon assoicated with the newtype -- -- The call (wrapNewTypeBody T [a] e) returns the -- body of the wrapper, namely --- e `cast` CoT [a] +-- e `cast` (CoT [a]) -- -- If a coercion constructor is prodivided in the newtype, then we use -- it, otherwise the wrap/unwrap are both no-ops -- +-- If the we are dealing with a newtype instance, we have a second coercion +-- identifying the family instance with the constructor of the newtype +-- instance. This coercion is applied in any case (ie, composed with the +-- coercion constructor of the newtype or applied by itself). +-- wrapNewTypeBody tycon args result_expr - | Just co_con <- newTyConCo tycon - = Cast result_expr (mkTyConApp co_con args) - | otherwise - = result_expr + = wrapFamInstBody tycon args inner + where + inner + | Just co_con <- newTyConCo_maybe tycon + = mkCoerce (mkSymCoercion (mkTyConApp co_con args)) result_expr + | otherwise + = result_expr +-- When unwrapping, we do *not* apply any family coercion, because this will +-- be done via a CoPat by the type checker. We have to do it this way as +-- computing the right type arguments for the coercion requires more than just +-- a spliting operation (cf, TcPat.tcConPat). +-- unwrapNewTypeBody :: TyCon -> [Type] -> CoreExpr -> CoreExpr unwrapNewTypeBody tycon args result_expr - | Just co_con <- newTyConCo tycon - = Cast result_expr (mkSymCoercion (mkTyConApp co_con args)) + | Just co_con <- newTyConCo_maybe tycon + = mkCoerce (mkTyConApp co_con args) result_expr | otherwise = result_expr