Fix show-iface for family instances & add debug ppr for type declarations
[ghc-hetmet.git] / compiler / typecheck / TcGadt.lhs
index 4e71827..5bad13e 100644 (file)
@@ -21,7 +21,6 @@ module TcGadt (
 
 import HsSyn
 import Coercion
-import Type
 import TypeRep
 import DataCon
 import Var
@@ -31,11 +30,11 @@ import ErrUtils
 import Maybes
 import Control.Monad
 import Outputable
+import TcType
 
 #ifdef DEBUG
 import Unique
 import UniqFM
-import TcType
 #endif
 \end{code}
 
@@ -48,6 +47,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
 
@@ -60,16 +61,17 @@ emptyRefinement :: Refinement
 emptyRefinement = (Reft emptyInScopeSet emptyVarEnv)
 
 
-refineType :: Refinement -> Type -> (HsWrapper, Type)
+refineType :: Refinement -> Type -> Maybe (Coercion, Type)
 -- Apply the refinement to the type.
 -- If (refineType r ty) = (co, ty')
 -- Then co :: ty:=:ty'
+-- Nothing => the refinement does nothing to this type
 refineType (Reft in_scope env) ty
   | not (isEmptyVarEnv env),           -- Common case
     any (`elemVarEnv` env) (varSetElems (tyVarsOfType ty))
-  = (WpCo (substTy co_subst ty), substTy tv_subst ty)
+  = Just (substTy co_subst ty, substTy tv_subst ty)
   | otherwise
-  = (idHsWrapper, ty)  -- The type doesn't mention any refined type variables
+  = 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)
@@ -78,11 +80,11 @@ refineResType :: Refinement -> Type -> (HsWrapper, Type)
 -- Like refineType, but returns the 'sym' coercion
 -- If (refineResType r ty) = (co, ty')
 -- Then co :: ty':=:ty
+-- It's convenient to return a HsWrapper here
 refineResType reft ty
   = case refineType reft ty of
-       (WpCo co, ty1) -> (WpCo (mkSymCoercion co), ty1)
-       (id_co,   ty1) -> ASSERT( isIdHsWrapper id_co )
-                         (idHsWrapper, ty1)
+       Just (co, ty1) -> (WpCo (mkSymCoercion co), ty1)
+       Nothing        -> (idHsWrapper,             ty)
 \end{code}
 
 
@@ -139,7 +141,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,9 +159,11 @@ 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
@@ -206,15 +210,13 @@ fixTvCoEnv in_scope env
   where
     fixpt         = mapVarEnv step env
 
-    step (co, ty) = (co1, ty')
+    step (co, ty) = case refineType (Reft in_scope fixpt) ty of
+                       Nothing         -> (co,                     ty)
+                       Just (co', ty') -> (mkTransCoercion co co', ty')
       -- Apply fixpt one step:
       -- Use refineType to get a substituted type, ty', and a coercion, co_fn,
       -- which justifies the substitution.  If the coercion is not the identity
       -- then use transitivity with the original coercion
-      where
-        (co_fn, ty') = refineType (Reft in_scope fixpt) ty
-        co1 | WpCo co'' <- co_fn = mkTransCoercion co co''
-            | otherwise          = ASSERT( isIdHsWrapper co_fn ) co 
 
 -----------------------------
 fixTvSubstEnv :: InScopeSet -> TvSubstEnv -> TvSubstEnv
@@ -254,11 +256,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