Make various assertions work when !DEBUG
[ghc-hetmet.git] / compiler / typecheck / TcGadt.lhs
index 4129df5..b556e89 100644 (file)
 %************************************************************************
 
 \begin{code}
+{-# OPTIONS -w #-}
+-- The above warning supression flag is a temporary kludge.
+-- While working on this module you are encouraged to remove it and fix
+-- any warnings in the module. See
+--     http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#Warnings
+-- for details
+
 module TcGadt (
-       Refinement, emptyRefinement, gadtRefine, 
-       refineType, refineResType,
-       dataConCanMatch,
+       Refinement, emptyRefinement, isEmptyRefinement, 
+       gadtRefine, 
+       refineType, refinePred, refineResType,
        tcUnifyTys, BindFlag(..)
   ) where
 
@@ -21,8 +28,9 @@ module TcGadt (
 
 import HsSyn
 import Coercion
+import Type
+
 import TypeRep
-import DataCon
 import Var
 import VarEnv
 import VarSet
@@ -30,12 +38,9 @@ import ErrUtils
 import Maybes
 import Control.Monad
 import Outputable
-
-#ifdef DEBUG
+import TcType
 import Unique
 import UniqFM
-import TcType
-#endif
 \end{code}
 
 
@@ -47,6 +52,8 @@ import TcType
 
 \begin{code}
 data Refinement = Reft InScopeSet InternalReft 
+
+type InternalReft = TyVarEnv (Coercion, Type)
 -- INVARIANT:   a->(co,ty)   then   co :: (a:=:ty)
 -- Not necessarily idemopotent
 
@@ -58,6 +65,8 @@ instance Outputable Refinement where
 emptyRefinement :: Refinement
 emptyRefinement = (Reft emptyInScopeSet emptyVarEnv)
 
+isEmptyRefinement :: Refinement -> Bool
+isEmptyRefinement (Reft _ env) = isEmptyVarEnv env
 
 refineType :: Refinement -> Type -> Maybe (Coercion, Type)
 -- Apply the refinement to the type.
@@ -74,6 +83,17 @@ refineType (Reft in_scope env) ty
     tv_subst = mkTvSubst in_scope (mapVarEnv snd env)
     co_subst = mkTvSubst in_scope (mapVarEnv fst env)
  
+refinePred :: Refinement -> PredType -> Maybe (Coercion, PredType)
+refinePred (Reft in_scope env) pred
+  | not (isEmptyVarEnv env),           -- Common case
+    any (`elemVarEnv` env) (varSetElems (tyVarsOfPred pred))
+  = Just (mkPredTy (substPred co_subst pred), substPred tv_subst pred)
+  | otherwise
+  = Nothing    -- The type doesn't mention any refined type variables
+  where
+    tv_subst = mkTvSubst in_scope (mapVarEnv snd env)
+    co_subst = mkTvSubst in_scope (mapVarEnv fst env)
 refineResType :: Refinement -> Type -> (HsWrapper, Type)
 -- Like refineType, but returns the 'sym' coercion
 -- If (refineResType r ty) = (co, ty')
@@ -139,7 +159,7 @@ gadtRefine (Reft in_scope env1)
           ex_tvs co_vars
 -- Precondition: fvs( co_vars ) # env1
 -- That is, the kinds of the co_vars are a
--- fixed point of the  incoming refinement
+-- fixed point of the incoming refinement
 
   = ASSERT2( not $ any (`elemVarEnv` env1) (varSetElems $ tyVarsOfTypes $ map tyVarKind co_vars),
             ppr env1 $$ ppr co_vars $$ ppr (map tyVarKind co_vars) )
@@ -157,14 +177,16 @@ gadtRefine (Reft in_scope env1)
   where
     tv_set = mkVarSet ex_tvs
     in_scope' = foldr extend in_scope co_vars
+
+       -- For each co_var, add it *and* the tyvars it mentions, to in_scope
     extend co_var in_scope
-       = extendInScopeSetSet (extendInScopeSet in_scope co_var)
-                             (tyVarsOfType (tyVarKind co_var))
+       = extendInScopeSetSet in_scope $
+         extendVarSet (tyVarsOfType (tyVarKind co_var)) co_var
        
     do_one reft co_var = unify reft (TyVarTy co_var) ty1 ty2
        where
           (ty1,ty2) = splitCoercionKind (tyVarKind co_var)
-\end{code} 
+\end{code}
 
 %************************************************************************
 %*                                                                     *
@@ -222,26 +244,10 @@ fixTvSubstEnv in_scope env
     fixpt = mapVarEnv (substTy (mkTvSubst in_scope fixpt)) env
 
 ----------------------------
-dataConCanMatch :: DataCon -> [Type] -> Bool
--- Returns True iff the data con can match a scrutinee of type (T tys)
---                 where T is the type constructor for the data con
---
--- Instantiate the equations and try to unify them
-dataConCanMatch con tys
-  = isJust (tcUnifyTys (\tv -> BindMe) 
-                      (map (substTyVar subst . fst) eq_spec)
-                      (map snd eq_spec))
-  where
-    dc_tvs  = dataConUnivTyVars con
-    eq_spec = dataConEqSpec con
-    subst   = zipTopTvSubst dc_tvs tys
-
-----------------------------
 tryToBind :: TyVarSet -> TyVar -> BindFlag
 tryToBind tv_set tv | tv `elemVarSet` tv_set = BindMe
                    | otherwise              = AvoidMe
 
-
 \end{code}
 
 
@@ -252,12 +258,6 @@ tryToBind tv_set tv | tv `elemVarSet` tv_set = BindMe
 %************************************************************************
 
 \begin{code}
-type InternalReft = TyVarEnv (Coercion, Type)
-
--- INVARIANT:   a->(co,ty)   then   co :: (a:=:ty)
--- Not necessarily idemopotent
-
-#ifdef DEBUG
 badReftElts :: InternalReft -> [(Unique, (Coercion,Type))]
 -- Return the BAD elements of the refinement
 -- Should be empty; used in asserions only
@@ -270,7 +270,6 @@ badReftElts env
                     | otherwise = False
        where
          (ty1,ty2) = coercionKind co
-#endif
 
 emptyInternalReft :: InternalReft
 emptyInternalReft = emptyVarEnv