[project @ 2001-12-11 12:19:04 by simonpj]
[ghc-hetmet.git] / ghc / compiler / typecheck / TcDeriv.lhs
index 259dd94..ee364ac 100644 (file)
@@ -17,7 +17,7 @@ import RnHsSyn                ( RenamedHsBinds, RenamedMonoBinds, RenamedTyClDecl )
 import CmdLineOpts     ( DynFlag(..), DynFlags )
 
 import TcMonad
-import TcEnv           ( TcEnv, tcSetInstEnv, newDFunName, InstInfo(..), pprInstInfo,
+import TcEnv           ( tcSetInstEnv, newDFunName, InstInfo(..), pprInstInfo,
                          tcLookupClass, tcLookupTyCon
                        )
 import TcGenDeriv      -- Deriv stuff
@@ -30,21 +30,22 @@ import RnMonad              ( renameDerivedCode, thenRn, mapRn, returnRn )
 import HscTypes                ( DFunId, PersistentRenamerState )
 
 import BasicTypes      ( Fixity )
-import Class           ( classKey, Class )
+import Class           ( className, classKey, Class )
 import ErrUtils                ( dumpIfSet_dyn, Message )
 import MkId            ( mkDictFunId )
 import DataCon         ( dataConArgTys, isNullaryDataCon, isExistentialDataCon )
 import PrelInfo                ( needsDataDeclCtxtClassKeys )
 import Maybes          ( maybeToBool, catMaybes )
 import Module          ( Module )
-import Name            ( Name, getSrcLoc )
+import Name            ( Name, getSrcLoc, nameUnique )
 import RdrName         ( RdrName )
 
 import TyCon           ( tyConTyVars, tyConDataCons,
                          tyConTheta, maybeTyConSingleCon, isDataTyCon,
                          isEnumerationTyCon, TyCon
                        )
-import Type            ( TauType, PredType(..), mkTyVarTys, mkTyConApp, isUnboxedType )
+import TcType          ( ThetaType, mkTyVarTys, mkTyConApp, 
+                         isUnLiftedType, mkClassPred )
 import Var             ( TyVar )
 import PrelNames
 import Util            ( zipWithEqual, sortLt )
@@ -142,9 +143,7 @@ type DerivEqn = (Name, Class, TyCon, [TyVar], DerivRhs)
                -- The Name is the name for the DFun we'll build
                -- The tyvars bind all the variables in the RHS
 
-type DerivRhs = [(Class, [TauType])]   -- Same as a ThetaType!
-               --[PredType]   -- ... | Class Class [Type==TauType]
-
+type DerivRhs  = ThetaType
 type DerivSoln = DerivRhs
 \end{code}
 
@@ -193,7 +192,7 @@ tcDeriving prs mod inst_env_in get_fixity tycl_decls
 
        -- Fish the "deriving"-related information out of the TcEnv
        -- and make the necessary "equations".
-    makeDerivEqns mod tycl_decls               `thenTc` \ eqns ->
+    makeDerivEqns tycl_decls           `thenTc` \ eqns ->
     if null eqns then
        returnTc ([], EmptyBinds)
     else
@@ -246,11 +245,10 @@ tcDeriving prs mod inst_env_in get_fixity tycl_decls
        -- Make a Real dfun instead of the dummy one we have so far
     gen_inst_info :: DFunId -> RenamedMonoBinds -> InstInfo
     gen_inst_info dfun binds
-      = InstInfo { iLocal = True,  iDFunId = dfun, 
-                  iBinds = binds, iPrags = [] }
+      = InstInfo { iDFunId = dfun, iBinds = binds, iPrags = [] }
 
-    rn_meths meths = rnMethodBinds [] meths `thenRn` \ (meths', _) -> returnRn meths'
-       -- Ignore the free vars returned
+    rn_meths (cls, meths) = rnMethodBinds cls [] meths `thenRn` \ (meths', _) -> 
+                           returnRn meths'     -- Ignore the free vars returned
 \end{code}
 
 
@@ -276,9 +274,9 @@ or} has just one data constructor (e.g., tuples).
 all those.
 
 \begin{code}
-makeDerivEqns :: Module -> [RenamedTyClDecl] -> TcM [DerivEqn]
+makeDerivEqns :: [RenamedTyClDecl] -> TcM [DerivEqn]
 
-makeDerivEqns this_mod tycl_decls
+makeDerivEqns tycl_decls
   = mapTc mk_eqn derive_these          `thenTc` \ maybe_eqns ->
     returnTc (catMaybes maybe_eqns)
   where
@@ -287,7 +285,7 @@ makeDerivEqns this_mod tycl_decls
        -- Find the (Class,TyCon) pairs that must be `derived'
        -- NB: only source-language decls have deriving, no imported ones do
     derive_these = [ (clas,tycon) 
-                  | TyData _ _ tycon _ _ _ (Just classes) _ _ _ <- tycl_decls,
+                  | TyData {tcdName = tycon, tcdDerivs = Just classes} <- tycl_decls,
                     clas <- nub classes ]
 
     ------------------------------------------------------------------
@@ -315,15 +313,16 @@ makeDerivEqns this_mod tycl_decls
            offensive_class = clas_key `elem` needsDataDeclCtxtClassKeys
     
            mk_constraints data_con
-              = [ (clas, [arg_ty])
+              = [ mkClassPred clas [arg_ty]
                 | arg_ty <- dataConArgTys data_con tyvar_tys,
-                  not (isUnboxedType arg_ty)   -- No constraints for unboxed types?
+                  not (isUnLiftedType arg_ty)  -- No constraints for unlifted types?
                 ]
        in
        case chk_out clas tycon of
-          Just err ->  addErrTc err                            `thenNF_Tc_` 
+          Just err ->  tcAddSrcLoc (getSrcLoc tycon)   $
+                       addErrTc err                    `thenNF_Tc_` 
                        returnNF_Tc Nothing
-          Nothing  ->  newDFunName this_mod clas [ty] locn `thenNF_Tc` \ dfun_name ->
+          Nothing  ->  newDFunName clas [ty] locn `thenNF_Tc` \ dfun_name ->
                        returnNF_Tc (Just (dfun_name, clas, tycon, tyvars, constraints))
 
 
@@ -331,18 +330,21 @@ makeDerivEqns this_mod tycl_decls
     ------------------------------------------------------------------
     chk_out :: Class -> TyCon -> Maybe Message
     chk_out clas tycon
-       | clas `hasKey` enumClassKey    && not is_enumeration         = bog_out nullary_why
+       | clas `hasKey` enumClassKey    && not is_enumeration           = bog_out nullary_why
        | clas `hasKey` boundedClassKey && not is_enumeration_or_single = bog_out single_nullary_why
        | clas `hasKey` ixClassKey      && not is_enumeration_or_single = bog_out single_nullary_why
-       | any isExistentialDataCon (tyConDataCons tycon)              = Just (existentialErr clas tycon)
-       | otherwise                                                   = Nothing
+       | null data_cons                     = bog_out no_cons_why
+       | any isExistentialDataCon data_cons = Just (existentialErr clas tycon)
+       | otherwise                          = Nothing
        where
+           data_cons = tyConDataCons tycon
            is_enumeration = isEnumerationTyCon tycon
            is_single_con  = maybeToBool (maybeTyConSingleCon tycon)
            is_enumeration_or_single = is_enumeration || is_single_con
 
            single_nullary_why = SLIT("one constructor data type or type with all nullary constructors expected")
            nullary_why        = SLIT("data type with all nullary constructors expected")
+           no_cons_why        = SLIT("type has no data constructors")
 
            bog_out why = Just (derivingThingErr clas tycon why)
 \end{code}
@@ -406,7 +408,8 @@ solveDerivEqns inst_env_in orig_eqns
         in
            -- Simplify each RHS
        tcSetInstEnv inst_env (
-         listTc [ tcAddErrCtxt (derivCtxt tc) $
+         listTc [ tcAddSrcLoc (getSrcLoc tc)   $
+                  tcAddErrCtxt (derivCtxt tc)  $
                   tcSimplifyThetas deriv_rhs
                 | (_, _,tc,_,deriv_rhs) <- orig_eqns ]  
        )                                       `thenTc` \ next_solns ->
@@ -435,10 +438,9 @@ add_solns dflags inst_env_in eqns solns
        -- They'll appear later, when we do the top-level extendInstEnvs
 
       mk_deriv_dfun (dfun_name, clas, tycon, tyvars, _) theta
-        = mkDictFunId dfun_name clas tyvars [mkTyConApp tycon (mkTyVarTys tyvars)] 
-                     (map pair2PredType theta)
-
-      pair2PredType (clas, tautypes) = Class clas tautypes
+        = mkDictFunId dfun_name clas tyvars 
+                     [mkTyConApp tycon (mkTyVarTys tyvars)] 
+                     theta
 \end{code}
 
 %************************************************************************
@@ -505,24 +507,26 @@ the renamer.  What a great hack!
 
 \begin{code}
 -- Generate the method bindings for the required instance
--- (paired with class name, as we need that when generating dict
---  names.)
-gen_bind :: (Name -> Maybe Fixity) -> DFunId -> RdrNameMonoBinds
+-- (paired with class name, as we need that when renaming
+--  the method binds)
+gen_bind :: (Name -> Maybe Fixity) -> DFunId -> (Name, RdrNameMonoBinds)
 gen_bind get_fixity dfun
-  | clas `hasKey` showClassKey   = gen_Show_binds get_fixity tycon
-  | clas `hasKey` readClassKey   = gen_Read_binds get_fixity tycon
-  | otherwise
-  = assoc "gen_bind:bad derived class"
-          [(eqClassKey,      gen_Eq_binds)
-          ,(ordClassKey,     gen_Ord_binds)
-          ,(enumClassKey,    gen_Enum_binds)
-          ,(boundedClassKey, gen_Bounded_binds)
-          ,(ixClassKey,      gen_Ix_binds)
-          ]
-          (classKey clas)
-          tycon
+  = (cls_nm, binds)
   where
+    cls_nm       = className clas
     (clas, tycon) = simpleDFunClassTyCon dfun
+
+    binds = assoc "gen_bind:bad derived class" gen_list 
+                 (nameUnique cls_nm) tycon
+
+    gen_list = [(eqClassKey,      gen_Eq_binds)
+              ,(ordClassKey,     gen_Ord_binds)
+              ,(enumClassKey,    gen_Enum_binds)
+              ,(boundedClassKey, gen_Bounded_binds)
+              ,(ixClassKey,      gen_Ix_binds)
+              ,(showClassKey,    gen_Show_binds get_fixity)
+              ,(readClassKey,    gen_Read_binds get_fixity)
+              ]
 \end{code}
 
 
@@ -537,7 +541,7 @@ data Foo ... = ...
 
 con2tag_Foo :: Foo ... -> Int#
 tag2con_Foo :: Int -> Foo ...  -- easier if Int, not Int#
-maxtag_Foo  :: Int             -- ditto (NB: not unboxed)
+maxtag_Foo  :: Int             -- ditto (NB: not unlifted)
 
 
 We have a @con2tag@ function for a tycon if: