Fix bug in type checking interface DataAlts
[ghc-hetmet.git] / compiler / coreSyn / CoreUtils.lhs
index 19a44dc..1bd0acd 100644 (file)
@@ -31,7 +31,9 @@ module CoreUtils (
        hashExpr,
 
        -- Equality
-       cheapEqExpr, tcEqExpr, tcEqExprX, applyTypeToArgs, applyTypeToArg
+       cheapEqExpr, tcEqExpr, tcEqExprX, applyTypeToArgs, applyTypeToArg,
+
+        dataConInstPat, dataConOccInstPat
     ) where
 
 #include "HsVersions.h"
@@ -42,10 +44,12 @@ import GLAEXTS              -- For `xori`
 import CoreSyn
 import CoreFVs         ( exprFreeVars )
 import PprCore         ( pprCoreExpr )
-import Var             ( Var, TyVar, isCoVar, tyVarKind )
+import Var             ( Var, TyVar, CoVar, isCoVar, tyVarKind, setVarUnique,
+                          mkCoVar, mkTyVar, mkCoVar )
+import OccName          ( OccName, occNameFS, mkVarOcc )
 import VarSet          ( unionVarSet )
 import VarEnv
-import Name            ( hashName )
+import Name            ( hashName, mkSysTvName )
 #if mingw32_TARGET_OS
 import Packages                ( isDllName )
 #endif
@@ -53,7 +57,7 @@ import Literal                ( hashLiteral, literalType, litIsDupable,
                          litIsTrivial, isZeroLit, Literal( MachLabel ) )
 import DataCon         ( DataCon, dataConRepArity, 
                          isVanillaDataCon, dataConTyCon, dataConRepArgTys,
-                          dataConUnivTyVars, dataConExTyVars )
+                          dataConUnivTyVars, dataConExTyVars, dataConEqSpec )
 import PrimOp          ( PrimOp(..), primOpOkForSpeculation, primOpIsCheap )
 import Id              ( Id, idType, globalIdDetails, idNewStrictness, 
                          mkWildId, idArity, idName, idUnfolding, idInfo,
@@ -67,12 +71,12 @@ import Type         ( Type, mkFunTy, mkForAllTy, splitFunTy_maybe,
                          applyTys, isUnLiftedType, seqType, mkTyVarTy,
                          splitForAllTy_maybe, isForAllTy, splitRecNewType_maybe, 
                          splitTyConApp_maybe, coreEqType, funResultTy, applyTy,
-                          substTyWith
+                          substTyWith, mkPredTy
                        )
 import Coercion         ( Coercion, mkTransCoercion, coercionKind,
                           splitNewTypeRepCo_maybe, mkSymCoercion, mkLeftCoercion,
-                          mkRightCoercion, decomposeCo, coercionKindTyConApp,
-                          splitCoercionKind )
+                          mkRightCoercion, decomposeCo, coercionKindPredTy,
+                          splitCoercionKind, mkEqPred )
 import TyCon           ( tyConArity )
 import TysWiredIn      ( boolTy, trueDataCon, falseDataCon )
 import CostCentre      ( CostCentre )
@@ -83,6 +87,7 @@ import Outputable
 import DynFlags                ( DynFlags, DynFlag(Opt_DictsCheap), dopt )
 import TysPrim         ( alphaTy )     -- Debugging only
 import Util             ( equalLength, lengthAtLeast, foldl2 )
+import FastString       ( mkFastString )
 \end{code}
 
 
@@ -215,7 +220,7 @@ mkCoerce co expr
 --    if to_ty `coreEqType` from_ty
 --    then expr
 --    else 
-        ASSERT2(from_ty `coreEqType` (exprType expr), text "Trying to coerce" <+> text "(" <> ppr expr $$ text "::" <+> ppr (exprType expr) <> text ")" $$ ppr co $$ ppr (coercionKindTyConApp co))
+        ASSERT2(from_ty `coreEqType` (exprType expr), text "Trying to coerce" <+> text "(" <> ppr expr $$ text "::" <+> ppr (exprType expr) <> text ")" $$ ppr co $$ ppr (coercionKindPredTy co))
          (Cast expr co)
 \end{code}
 
@@ -674,6 +679,96 @@ deepCast ty tyVars co
     -- coArgs = [right (left (left co)), right (left co), right co]
     coArgs = decomposeCo (length tyVars) co
 
+-- This goes here to avoid circularity between DataCon and Id
+dataConInstPat :: [Unique]                  -- A long enough list of uniques, at least one for each binder
+               -> DataCon
+              -> [Type]                    -- Types to instantiate the universally quantified tyvars
+              -> ([TyVar], [CoVar], [Id])  -- Return instantiated variables
+-- dataConInstPat us con inst_tys returns a triple (ex_tvs, co_tvs, arg_ids),
+--
+--   ex_tvs are intended to be used as binders for existential type args
+--
+--   co_tvs are intended to be used as binders for coercion args and the kinds
+--     of these vars have been instantiated by the inst_tys and the ex_tys
+--
+--   arg_ids are indended to be used as binders for value arguments, including
+--     dicts, and have their types instantiated with inst_tys and ex_tys
+--
+-- Example.
+--  The following constructor T1
+--
+--  data T a where
+--    T1 :: forall b. Int -> b -> T(a,b)
+--    ...
+--
+--  has representation type 
+--   forall a. forall a1. forall a2. forall b. (a :=: (a1,a2)) => 
+--     Int -> b -> T a
+--
+--  dataConInstPat us T1 (a1',a2') will return
+--
+--  ([a1'', a2'', b''],[c :: (a1',a2'):=:(a1'',a2'')],[x :: Int,y :: b''])
+--
+--  where the double-primed variables are created from the unique list input
+dataConInstPat uniqs con inst_tys 
+  = dataConOccInstPat uniqs occs con inst_tys
+  where
+     -- dataConOccInstPat doesn't actually make use of the OccName directly for
+     -- existential and coercion variable binders, so it is right to just
+     -- use the VarName namespace for all of the OccNames
+    occs      = mk_occs 1
+    mk_occs n = mkVarOcc ("ipv" ++ show n) : mk_occs (n+1)
+
+dataConOccInstPat :: [Unique]                  -- A long enough list of uniques, at least one for each binder
+                  -> [OccName]                 -- An equally long list of OccNames to use
+                  -> DataCon
+                 -> [Type]                    -- Types to instantiate the universally quantified tyvars
+              -> ([TyVar], [CoVar], [Id])  -- Return instantiated variables
+-- This function actually does the job specified in the comment for 
+-- dataConInstPat, but uses the specified list of OccNames.  This is 
+-- is necessary for use in e.g. tcIfaceDataAlt
+dataConOccInstPat uniqs occs con inst_tys 
+  = (ex_bndrs, co_bndrs, id_bndrs)
+  where 
+    univ_tvs = dataConUnivTyVars con
+    ex_tvs   = dataConExTyVars con
+    arg_tys  = dataConRepArgTys con
+    eq_spec  = dataConEqSpec con
+    eq_preds = [ mkEqPred (mkTyVarTy tv, ty) | (tv,ty) <- eq_spec ]
+
+    n_ex = length ex_tvs
+    n_co = length eq_spec
+    n_id = length arg_tys
+
+      -- split the Uniques and OccNames
+    (ex_uniqs, uniqs')   = splitAt n_ex uniqs
+    (co_uniqs, id_uniqs) = splitAt n_co uniqs'
+
+    (ex_occs, occs')     = splitAt n_ex occs
+    (co_occs, id_occs)   = splitAt n_co occs'
+
+      -- make existential type variables
+    mk_ex_var uniq occ var = mkTyVar new_name kind
+      where
+        new_name = mkSysTvName uniq (occNameFS occ)
+        kind     = tyVarKind var
+
+    ex_bndrs = zipWith3 mk_ex_var ex_uniqs ex_occs ex_tvs
+
+      -- make the instantiation substitution
+    inst_subst = substTyWith (univ_tvs ++ ex_tvs) (inst_tys ++ map mkTyVarTy ex_bndrs)
+
+      -- make new coercion vars, instantiating kind
+    mk_co_var uniq occ eq_pred = mkCoVar new_name (inst_subst (mkPredTy eq_pred))
+       where
+         new_name = mkSysTvName uniq (occNameFS occ)
+
+    co_bndrs               = zipWith3 mk_co_var co_uniqs co_occs eq_preds
+
+      -- make value vars, instantiating types
+    mk_id_var uniq occ ty = mkUserLocal occ uniq (inst_subst ty) noSrcLoc
+    id_bndrs = zipWith3 mk_id_var id_uniqs id_occs arg_tys
+
 exprIsConApp_maybe :: CoreExpr -> Maybe (DataCon, [CoreExpr])
 -- Returns (Just (dc, [x1..xn])) if the argument expression is 
 -- a constructor application of the form (dc x1 .. xn)
@@ -1061,7 +1156,12 @@ eta_expand n us (Lam v body) ty
 eta_expand n us expr ty
   = ASSERT2 (exprType expr `coreEqType` ty, ppr (exprType expr) $$ ppr ty)
     case splitForAllTy_maybe ty of { 
-         Just (tv,ty') -> Lam tv (eta_expand n us (App expr (Type (mkTyVarTy tv))) ty')
+         Just (tv,ty') -> 
+
+              Lam lam_tv (eta_expand n us2 (App expr (Type (mkTyVarTy lam_tv))) (substTyWith [tv] [mkTyVarTy lam_tv] ty'))
+                  where 
+                    lam_tv = mkTyVar (mkSysTvName uniq FSLIT("etaT")) (tyVarKind tv)
+                    (uniq:us2) = us
 
        ; Nothing ->