Big tidy-up of deriving code
[ghc-hetmet.git] / compiler / typecheck / TcEnv.lhs
index c638c04..e1b9bd3 100644 (file)
@@ -17,7 +17,7 @@ module TcEnv(
        tcLookupLocatedGlobal,  tcLookupGlobal, 
        tcLookupField, tcLookupTyCon, tcLookupClass, tcLookupDataCon,
        tcLookupLocatedGlobalId, tcLookupLocatedTyCon,
-       tcLookupLocatedClass, 
+       tcLookupLocatedClass, tcLookupFamInst,
        
        -- Local environment
        tcExtendKindEnv, tcExtendKindEnvTvs,
@@ -61,6 +61,7 @@ import VarSet
 import VarEnv
 import RdrName
 import InstEnv
+import FamInstEnv
 import DataCon
 import TyCon
 import Class
@@ -157,6 +158,25 @@ tcLookupLocatedClass = addLocM tcLookupClass
 
 tcLookupLocatedTyCon :: Located Name -> TcM TyCon
 tcLookupLocatedTyCon = addLocM tcLookupTyCon
+
+-- Look up the representation tycon of a family instance.
+-- Return the rep tycon and the corresponding rep args
+tcLookupFamInst :: TyCon -> [Type] -> TcM (TyCon, [Type])
+tcLookupFamInst tycon tys
+  | not (isOpenTyCon tycon)
+  = return (tycon, tys)
+  | otherwise
+  = do { env <- getGblEnv
+       ; eps <- getEps
+       ; let instEnv = (eps_fam_inst_env eps, tcg_fam_inst_env env)
+       ; case lookupFamInstEnv instEnv tycon tys of
+          [(subst,fam_inst)] -> return (rep_tc, substTyVars subst (tyConTyVars rep_tc))
+               where   -- NB: assumption is that (tyConTyVars rep_tc) is in 
+                       --     the domain of the substitution
+                 rep_tc = famInstTyCon fam_inst 
+
+          other -> famInstNotFound tycon tys other
+       }
 \end{code}
 
 %************************************************************************
@@ -400,16 +420,21 @@ refineEnvironment :: Refinement -> TcM a -> TcM a
 -- I don't think I have to refine the set of global type variables in scope
 -- Reason: the refinement never increases that set
 refineEnvironment reft thing_inside
+  | isEmptyRefinement reft             -- Common case
+  = thing_inside
+  | otherwise
   = do { env <- getLclEnv
        ; let le' = mapNameEnv refine (tcl_env env)
        ; setLclEnv (env {tcl_env = le'}) thing_inside }
   where
     refine elt@(ATcId { tct_co = Just co, tct_type = ty })
-                         = let (co', ty') = refineType reft ty
-                           in elt { tct_co = Just (co' <.> co), tct_type = ty' }
-    refine (ATyVar tv ty) = ATyVar tv (snd (refineType reft ty))
-                               -- Ignore the coercion that refineType returns
-    refine elt           = elt
+       | Just (co', ty') <- refineType reft ty
+       = elt { tct_co = Just (WpCo co' <.> co), tct_type = ty' }
+    refine (ATyVar tv ty) 
+       | Just (_, ty') <- refineType reft ty
+       = ATyVar tv ty' -- Ignore the coercion that refineType returns
+
+    refine elt = elt   -- Common case
 \end{code}
 
 %************************************************************************
@@ -651,4 +676,11 @@ notFound name
 wrongThingErr expected thing name
   = failWithTc (pprTcTyThingCategory thing <+> quotes (ppr name) <+> 
                ptext SLIT("used as a") <+> text expected)
+
+famInstNotFound tycon tys what
+  = failWithTc (msg <+> quotes (ppr tycon <+> hsep (map pprParendType tys)))
+  where
+    msg = case what of
+               [] -> ptext SLIT("No instance for")
+               xs -> ptext SLIT("More than one instance for")
 \end{code}