More refactoring of constraint simplification
[ghc-hetmet.git] / compiler / typecheck / TcGadt.lhs
index 5bad13e..3761c68 100644 (file)
@@ -11,8 +11,9 @@
 
 \begin{code}
 module TcGadt (
-       Refinement, emptyRefinement, gadtRefine, 
-       refineType, refineResType,
+       Refinement, emptyRefinement, isEmptyRefinement, 
+       gadtRefine, 
+       refineType, refinePred, refineResType,
        dataConCanMatch,
        tcUnifyTys, BindFlag(..)
   ) where
@@ -21,6 +22,8 @@ module TcGadt (
 
 import HsSyn
 import Coercion
+import Type
+
 import TypeRep
 import DataCon
 import Var
@@ -60,6 +63,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.
@@ -76,6 +81,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')
@@ -168,7 +184,7 @@ gadtRefine (Reft in_scope env1)
     do_one reft co_var = unify reft (TyVarTy co_var) ty1 ty2
        where
           (ty1,ty2) = splitCoercionKind (tyVarKind co_var)
-\end{code} 
+\end{code}
 
 %************************************************************************
 %*                                                                     *
@@ -226,12 +242,15 @@ fixTvSubstEnv in_scope env
     fixpt = mapVarEnv (substTy (mkTvSubst in_scope fixpt)) env
 
 ----------------------------
-dataConCanMatch :: DataCon -> [Type] -> Bool
+dataConCanMatch :: [Type] -> DataCon -> 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
+dataConCanMatch tys con
+  | null eq_spec      = True   -- Common
+  | all isTyVarTy tys = True   -- Also common
+  | otherwise
   = isJust (tcUnifyTys (\tv -> BindMe) 
                       (map (substTyVar subst . fst) eq_spec)
                       (map snd eq_spec))