[project @ 2005-10-27 14:34:32 by simonpj]
[ghc-hetmet.git] / ghc / compiler / types / Type.lhs
index d7fa64d..b911493 100644 (file)
@@ -54,6 +54,7 @@ module Type (
        tidyTyVarBndr, tidyFreeTyVars,
        tidyOpenTyVar, tidyOpenTyVars,
        tidyTopType,   tidyPred,
+       tidyKind,
 
        -- Comparison
        coreEqType, tcEqType, tcEqTypes, tcCmpType, tcCmpTypes, 
@@ -63,15 +64,15 @@ module Type (
        seqType, seqTypes,
 
        -- Type substitutions
-       TvSubst(..),    -- Representation visible to a few friends
-       TvSubstEnv, emptyTvSubst,
-       mkTvSubst, zipTvSubst, zipTopTvSubst, mkTopTvSubst,
+       TvSubstEnv, emptyTvSubstEnv,    -- Representation widely visible
+       TvSubst(..), emptyTvSubst,      -- Representation visible to a few friends
+       mkTvSubst, mkOpenTvSubst, zipOpenTvSubst, zipTopTvSubst, mkTopTvSubst, notElemTvSubst,
        getTvSubstEnv, setTvSubstEnv, getTvInScope, extendTvInScope,
-       extendTvSubst, extendTvSubstList, isInScope,
+       extendTvSubst, extendTvSubstList, isInScope, composeTvSubst,
 
        -- Performing substitution on types
-       substTy, substTys, substTyWith, substTheta, substTyVar, 
-       deShadowTy,
+       substTy, substTys, substTyWith, substTheta, 
+       substPred, substTyVar, substTyVarBndr, deShadowTy, 
 
        -- Pretty-printing
        pprType, pprParendType, pprTyThingCategory,
@@ -87,7 +88,7 @@ import TypeRep
 
 -- friends:
 import Kind
-import Var     ( Var, TyVar, tyVarKind, tyVarName, setTyVarName )
+import Var     ( Var, TyVar, tyVarKind, tyVarName, setTyVarName, mkTyVar )
 import VarEnv
 import VarSet
 
@@ -101,7 +102,7 @@ import TyCon        ( TyCon, isRecursiveTyCon, isPrimTyCon,
                )
 
 -- others
-import CmdLineOpts     ( opt_DictsStrict )
+import StaticFlags     ( opt_DictsStrict )
 import SrcLoc          ( noSrcLoc )
 import Unique          ( Uniquable(..) )
 import Util            ( mapAccumL, seqList, lengthIs, snocView, thenCmp, isEqual )
@@ -588,8 +589,9 @@ splitRecNewType_maybe (TyConApp tc tys)
                                                --      to *types* (of kind *)
     ASSERT( isRecursiveTyCon tc )              -- Guaranteed by coreView
     case newTyConRhs tc of
-       (tvs, rep_ty) -> Just (substTyWith tvs tys rep_ty)
-
+       (tvs, rep_ty) -> ASSERT( length tvs == length tys )
+                        Just (substTyWith tvs tys rep_ty)
+       
 splitRecNewType_maybe other = Nothing
 \end{code}
 
@@ -748,6 +750,43 @@ tidyTopType ty = tidyType emptyTidyEnv ty
 \end{code}
 
 
+%************************************************************************
+%*                                                                     *
+               Tidying Kinds
+%*                                                                     *
+%************************************************************************
+
+We use a grevious hack for tidying KindVars.  A TidyEnv contains
+a (VarEnv Var) substitution, to express the renaming; but
+KindVars are not Vars.  The Right Thing ultimately is to make them
+into Vars (and perhaps make Kinds into Types), but I just do a hack
+here: I make up a TyVar just to remember the new OccName for the
+renamed KindVar
+
+\begin{code}
+tidyKind :: TidyEnv -> Kind -> (TidyEnv, Kind)
+tidyKind env@(tidy_env, subst) (KindVar kvar)
+  | Just tv <- lookupVarEnv_Directly subst uniq
+  = (env, KindVar (setKindVarOcc kvar (getOccName tv)))
+  | otherwise
+  = ((tidy', subst'), KindVar kvar')
+  where
+    uniq = kindVarUniq kvar
+    (tidy', occ') = tidyOccName tidy_env (kindVarOcc kvar)
+    kvar'   = setKindVarOcc kvar occ'
+    fake_tv = mkTyVar tv_name (panic "tidyKind:fake tv kind")
+    tv_name = mkInternalName uniq occ' noSrcLoc
+    subst'  = extendVarEnv subst fake_tv fake_tv
+
+tidyKind env (FunKind k1 k2) 
+  = (env2, FunKind k1' k2')
+  where
+    (env1, k1') = tidyKind env  k1
+    (env2, k2') = tidyKind env1 k2
+
+tidyKind env k = (env, k)      -- Atomic kinds
+\end{code}
+
 
 %************************************************************************
 %*                                                                     *
@@ -961,7 +1000,7 @@ cmpTypeX env _ _ = LT
 -------------
 cmpTypesX :: RnEnv2 -> [Type] -> [Type] -> Ordering
 cmpTypesX env []        []        = EQ
-cmpTypesX env (t1:tys1) (t2:tys2) = cmpTypeX env t1 t2 `compare` cmpTypesX env tys1 tys2
+cmpTypesX env (t1:tys1) (t2:tys2) = cmpTypeX env t1 t2 `thenCmp` cmpTypesX env tys1 tys2
 cmpTypesX env []        tys       = LT
 cmpTypesX env ty        []        = GT
 
@@ -972,7 +1011,7 @@ cmpPredX env (IParam n1 ty1) (IParam n2 ty2) = (n1 `compare` n2) `thenCmp` cmpTy
        -- This comparison is used exclusively (I think) for the
        -- finite map built in TcSimplify
 cmpPredX env (ClassP c1 tys1) (ClassP c2 tys2) = (c1 `compare` c2) `thenCmp` cmpTypesX env tys1 tys2
-cmpPredX env (IParam _ _)     (ClassP _ _)     = LT
+cmpPredX env (IParam _ _)     (ClassP _ _)     = LT
 cmpPredX env (ClassP _ _)     (IParam _ _)     = GT
 \end{code}
 
@@ -994,7 +1033,7 @@ instance Ord PredType where { compare = tcCmpPred }
 \begin{code}
 data TvSubst           
   = TvSubst InScopeSet         -- The in-scope type variables
-           TvSubstEnv  -- The substitution itself; guaranteed idempotent
+           TvSubstEnv  -- The substitution itself
                        -- See Note [Apply Once]
 
 {- ----------------------------------------------------------
@@ -1025,11 +1064,29 @@ type TvSubstEnv = TyVarEnv Type
        -- in the middle of matching, and unification (see Types.Unify)
        -- So you have to look at the context to know if it's idempotent or
        -- apply-once or whatever
+emptyTvSubstEnv :: TvSubstEnv
+emptyTvSubstEnv = emptyVarEnv
+
+composeTvSubst :: InScopeSet -> TvSubstEnv -> TvSubstEnv -> TvSubstEnv
+-- (compose env1 env2)(x) is env1(env2(x)); i.e. apply env2 then env1
+-- It assumes that both are idempotent
+-- Typically, env1 is the refinement to a base substitution env2
+composeTvSubst in_scope env1 env2
+  = env1 `plusVarEnv` mapVarEnv (substTy subst1) env2
+       -- First apply env1 to the range of env2
+       -- Then combine the two, making sure that env1 loses if
+       -- both bind the same variable; that's why env1 is the
+       --  *left* argument to plusVarEnv, because the right arg wins
+  where
+    subst1 = TvSubst in_scope env1
 
 emptyTvSubst = TvSubst emptyInScopeSet emptyVarEnv
 isEmptyTvSubst :: TvSubst -> Bool
 isEmptyTvSubst (TvSubst _ env) = isEmptyVarEnv env
 
+mkTvSubst :: InScopeSet -> TvSubstEnv -> TvSubst
+mkTvSubst = TvSubst
+
 getTvSubstEnv :: TvSubst -> TvSubstEnv
 getTvSubstEnv (TvSubst _ env) = env
 
@@ -1039,6 +1096,9 @@ getTvInScope (TvSubst in_scope _) = in_scope
 isInScope :: Var -> TvSubst -> Bool
 isInScope v (TvSubst in_scope _) = v `elemInScopeSet` in_scope
 
+notElemTvSubst :: TyVar -> TvSubst -> Bool
+notElemTvSubst tv (TvSubst _ env) = not (tv `elemVarEnv` env)
+
 setTvSubstEnv :: TvSubst -> TvSubstEnv -> TvSubst
 setTvSubstEnv (TvSubst in_scope _) env = TvSubst in_scope env
 
@@ -1052,16 +1112,20 @@ extendTvSubstList :: TvSubst -> [TyVar] -> [Type] -> TvSubst
 extendTvSubstList (TvSubst in_scope env) tvs tys 
   = TvSubst in_scope (extendVarEnvList env (tvs `zip` tys))
 
--- mkTvSubst and zipTvSubst generate the in-scope set from
+-- mkOpenTvSubst and zipOpenTvSubst generate the in-scope set from
 -- the types given; but it's just a thunk so with a bit of luck
 -- it'll never be evaluated
 
-mkTvSubst :: TvSubstEnv -> TvSubst
-mkTvSubst env 
-  = TvSubst (mkInScopeSet (tyVarsOfTypes (varEnvElts env))) env
+mkOpenTvSubst :: TvSubstEnv -> TvSubst
+mkOpenTvSubst env = TvSubst (mkInScopeSet (tyVarsOfTypes (varEnvElts env))) env
 
-zipTvSubst :: [TyVar] -> [Type] -> TvSubst
-zipTvSubst tyvars tys 
+zipOpenTvSubst :: [TyVar] -> [Type] -> TvSubst
+zipOpenTvSubst tyvars tys 
+#ifdef DEBUG
+  | length tyvars /= length tys
+  = pprTrace "zipOpenTvSubst" (ppr tyvars $$ ppr tys) emptyTvSubst
+  | otherwise
+#endif
   = TvSubst (mkInScopeSet (tyVarsOfTypes tys)) (zipTyEnv tyvars tys)
 
 -- mkTopTvSubst is called when doing top-level substitutions.
@@ -1071,7 +1135,13 @@ mkTopTvSubst :: [(TyVar, Type)] -> TvSubst
 mkTopTvSubst prs = TvSubst emptyInScopeSet (mkVarEnv prs)
 
 zipTopTvSubst :: [TyVar] -> [Type] -> TvSubst
-zipTopTvSubst tyvars tys = TvSubst emptyInScopeSet (zipTyEnv tyvars tys)
+zipTopTvSubst tyvars tys 
+#ifdef DEBUG
+  | length tyvars /= length tys
+  = pprTrace "zipOpenTvSubst" (ppr tyvars $$ ppr tys) emptyTvSubst
+  | otherwise
+#endif
+  = TvSubst emptyInScopeSet (zipTyEnv tyvars tys)
 
 zipTyEnv :: [TyVar] -> [Type] -> TvSubstEnv
 zipTyEnv tyvars tys
@@ -1098,6 +1168,8 @@ zip_ty_env (tv:tvs) (ty:tys) env = zip_ty_env tvs tys (extendVarEnv env tv ty)
        -- and so generated a rep type mentioning t not t2.  
        --
        -- Simplest fix is to nuke the "optimisation"
+zip_ty_env tvs      tys      env   = pprTrace "Var/Type length mismatch: " (ppr tvs $$ ppr tys) env
+-- zip_ty_env _ _ env = env
 
 instance Outputable TvSubst where
   ppr (TvSubst ins env) 
@@ -1114,7 +1186,8 @@ instance Outputable TvSubst where
 
 \begin{code}
 substTyWith :: [TyVar] -> [Type] -> Type -> Type
-substTyWith tvs tys = substTy (zipTvSubst tvs tys)
+substTyWith tvs tys = ASSERT( length tvs == length tys )
+                     substTy (zipOpenTvSubst tvs tys)
 
 substTy :: TvSubst -> Type  -> Type
 substTy subst ty | isEmptyTvSubst subst = ty
@@ -1138,13 +1211,10 @@ substPred subst (ClassP clas tys) = ClassP clas (map (subst_ty subst) tys)
 
 -- Note that the in_scope set is poked only if we hit a forall
 -- so it may often never be fully computed 
-subst_ty subst@(TvSubst in_scope env) ty
+subst_ty subst ty
    = go ty
   where
-    go ty@(TyVarTy tv)            = case (lookupVarEnv env tv) of
-                                       Nothing  -> ty
-                                               Just ty' -> ty' -- See Note [Apply Once]
-                                       
+    go (TyVarTy tv)               = substTyVar subst tv
     go (TyConApp tc tys)          = let args = map go tys
                                     in  args `seqList` TyConApp tc args
 
@@ -1158,11 +1228,17 @@ subst_ty subst@(TvSubst in_scope env) ty
                -- The mkAppTy smart constructor is important
                -- we might be replacing (a Int), represented with App
                -- by [Int], represented with TyConApp
-    go (ForAllTy tv ty)                   = case substTyVar subst tv of
+    go (ForAllTy tv ty)                   = case substTyVarBndr subst tv of
                                        (subst', tv') -> ForAllTy tv' $! (subst_ty subst' ty)
 
-substTyVar :: TvSubst -> TyVar -> (TvSubst, TyVar)     
-substTyVar subst@(TvSubst in_scope env) old_var
+substTyVar :: TvSubst -> TyVar  -> Type
+substTyVar (TvSubst in_scope env) tv
+  = case (lookupVarEnv env tv) of
+       Nothing  -> TyVarTy tv
+               Just ty' -> ty' -- See Note [Apply Once]
+
+substTyVarBndr :: TvSubst -> TyVar -> (TvSubst, TyVar) 
+substTyVarBndr subst@(TvSubst in_scope env) old_var
   | old_var == new_var -- No need to clone
                        -- But we *must* zap any current substitution for the variable.
                        --  For example:
@@ -1171,7 +1247,8 @@ substTyVar subst@(TvSubst in_scope env) old_var
                        --
                        -- The new_id isn't cloned, but it may have a different type
                        -- etc, so we must return it, not the old id
-  = (TvSubst (in_scope `extendInScopeSet` new_var) (delVarEnv env old_var),
+  = (TvSubst (in_scope `extendInScopeSet` new_var) 
+            (delVarEnv env old_var),
      new_var)
 
   | otherwise  -- The new binder is in scope so
@@ -1179,11 +1256,10 @@ substTyVar subst@(TvSubst in_scope env) old_var
                -- Extending the substitution to do this renaming also
                -- has the (correct) effect of discarding any existing
                -- substitution for that variable
-  = (TvSubst (in_scope `extendInScopeSet` new_var) (extendVarEnv env old_var (TyVarTy new_var)),
+  = (TvSubst (in_scope `extendInScopeSet` new_var) 
+            (extendVarEnv env old_var (TyVarTy new_var)),
      new_var)
   where
     new_var = uniqAway in_scope old_var
        -- The uniqAway part makes sure the new variable is not already in scope
 \end{code}
-
-