[project @ 2000-02-10 18:39:51 by lewie]
[ghc-hetmet.git] / ghc / compiler / typecheck / TcDeriv.lhs
index 9e9a79a..156a180 100644 (file)
@@ -29,13 +29,13 @@ import RnMonad              ( RnNameSupply,
 
 import Bag             ( Bag, emptyBag, unionBags, listToBag )
 import Class           ( classKey, Class )
-import ErrUtils                ( dumpIfSet, Message )
+import ErrUtils                ( dumpIfSet, Message, pprBagOfErrors )
 import MkId            ( mkDictFunId )
 import Id              ( mkVanillaId )
-import DataCon         ( dataConArgTys, isNullaryDataCon )
+import DataCon         ( dataConArgTys, isNullaryDataCon, isExistentialDataCon )
 import PrelInfo                ( needsDataDeclCtxtClassKeys )
-import Maybes          ( maybeToBool )
-import Module          ( Module )
+import Maybes          ( maybeToBool, catMaybes )
+import Module          ( ModuleName )
 import Name            ( isLocallyDefined, getSrcLoc,
                          Name, NamedThing(..),
                          OccName, nameOccName
@@ -49,7 +49,7 @@ import TyCon          ( tyConTyVars, tyConDataCons, tyConDerivings,
                        )
 import Type            ( TauType, mkTyVarTys, mkTyConApp,
                          mkSigmaTy, mkDictTy, isUnboxedType,
-                         splitAlgTyConApp
+                         splitAlgTyConApp, classesToPreds
                        )
 import TysWiredIn      ( voidTy )
 import Var             ( TyVar )
@@ -186,7 +186,7 @@ context to the instance decl.  The "offending classes" are
 %************************************************************************
 
 \begin{code}
-tcDeriving  :: Module                  -- name of module under scrutiny
+tcDeriving  :: ModuleName              -- name of module under scrutiny
            -> Fixities                 -- for the deriving code (Show/Read.)
            -> RnNameSupply             -- for "renaming" bits of generated code
            -> Bag InstInfo             -- What we already know about instances
@@ -234,13 +234,14 @@ tcDeriving modname fixs rn_name_supply inst_decl_infos_in
                        returnRn (dfun_names_w_method_binds, rn_extra_binds)
                  )
        rn_one (cl_nm, tycon_nm, meth_binds) 
-               = newDFunName cl_nm tycon_nm
-                             Nothing mkGeneratedSrcLoc         `thenRn` \ dfun_name ->
-                 rnMethodBinds meth_binds                      `thenRn` \ (rn_meth_binds, _) ->
+               = newDFunName (cl_nm, tycon_nm)
+                             mkGeneratedSrcLoc         `thenRn` \ dfun_name ->
+                 rnMethodBinds meth_binds              `thenRn` \ (rn_meth_binds, _) ->
                  returnRn (dfun_name, rn_meth_binds)
 
-       really_new_inst_infos = map (gen_inst_info modname)
-                                   (new_inst_infos `zip` dfun_names_w_method_binds)
+       really_new_inst_infos = zipWith gen_inst_info
+                                       new_inst_infos
+                                       dfun_names_w_method_binds
 
        ddump_deriv = ddump_deriving really_new_inst_infos rn_extra_binds
     in
@@ -253,9 +254,10 @@ tcDeriving modname fixs rn_name_supply inst_decl_infos_in
       = vcat (map pp_info inst_infos) $$ ppr extra_binds
       where
        pp_info (InstInfo clas tvs [ty] inst_decl_theta _ mbinds _ _)
-         = ppr (mkSigmaTy tvs inst_decl_theta (mkDictTy clas [ty]))
+         = ppr (mkSigmaTy tvs inst_decl_theta' (mkDictTy clas [ty]))
            $$
            ppr mbinds
+           where inst_decl_theta' = classesToPreds inst_decl_theta
 \end{code}
 
 
@@ -296,8 +298,8 @@ makeDerivEqns
     if null local_data_tycons then
        returnTc []     -- Bale out now
     else
-    mapTc chk_out think_about_deriving `thenTc_`
-    returnTc eqns
+    mapTc mk_eqn derive_these `thenTc` \ maybe_eqns ->
+    returnTc (catMaybes maybe_eqns)
   where
     ------------------------------------------------------------------
     need_deriving :: [TyCon] -> [(Class, TyCon)]
@@ -309,45 +311,20 @@ makeDerivEqns
              tycons_to_consider
 
     ------------------------------------------------------------------
-    chk_out :: (Class, TyCon) -> TcM s ()
-    chk_out this_one@(clas, tycon)
-      =        let
-           clas_key = classKey clas
-
-           is_enumeration = isEnumerationTyCon tycon
-           is_single_con  = maybeToBool (maybeTyConSingleCon tycon)
-
-           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")
-
-           chk_clas clas_uniq clas_str clas_why cond
-             = if (clas_uniq == clas_key)
-               then checkTc cond (derivingThingErr clas_str clas_why tycon)
-               else returnTc ()
-       in
-           -- Are things OK for deriving Enum (if appropriate)?
-       chk_clas enumClassKey (SLIT("Enum")) nullary_why is_enumeration `thenTc_`
-
-           -- Are things OK for deriving Bounded (if appropriate)?
-       chk_clas boundedClassKey (SLIT("Bounded")) single_nullary_why
-                (is_enumeration || is_single_con) `thenTc_`
-
-           -- Are things OK for deriving Ix (if appropriate)?
-       chk_clas ixClassKey (SLIT("Ix.Ix")) single_nullary_why 
-                (is_enumeration || is_single_con)
-
-    ------------------------------------------------------------------
     cmp_deriv :: (Class, TyCon) -> (Class, TyCon) -> Ordering
     cmp_deriv (c1, t1) (c2, t2)
       = (c1 `compare` c2) `thenCmp` (t1 `compare` t2)
 
     ------------------------------------------------------------------
-    mk_eqn :: (Class, TyCon) -> DerivEqn
+    mk_eqn :: (Class, TyCon) -> NF_TcM s (Maybe DerivEqn)
        -- we swizzle the tyvars and datacons out of the tycon
        -- to make the rest of the equation
 
     mk_eqn (clas, tycon)
-      = (clas, tycon, tyvars, constraints)
+      = case chk_out clas tycon of
+          Just err ->  addErrTc err    `thenNF_Tc_` 
+                       returnNF_Tc Nothing
+          Nothing  ->  returnNF_Tc (Just (clas, tycon, tyvars, constraints))
       where
        clas_key  = classKey clas
        tyvars    = tyConTyVars tycon   -- ToDo: Do we need new tyvars ???
@@ -370,6 +347,26 @@ makeDerivEqns
             ]
           where
             instd_arg_tys  = dataConArgTys data_con tyvar_tys
+
+    ------------------------------------------------------------------
+    chk_out :: Class -> TyCon -> Maybe Message
+    chk_out clas tycon
+       | clas_key == enumClassKey    && not is_enumeration           = bog_out nullary_why
+       | clas_key == boundedClassKey && not is_enumeration_or_single = bog_out single_nullary_why
+       | clas_key == ixClassKey      && not is_enumeration_or_single = bog_out single_nullary_why
+       | any isExistentialDataCon (tyConDataCons tycon)              = Just (existentialErr clas tycon)
+       | otherwise                                                   = Nothing
+       where
+           clas_key = classKey clas
+
+           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")
+
+           bog_out why = Just (derivingThingErr clas tycon why)
 \end{code}
 
 %************************************************************************
@@ -475,7 +472,8 @@ add_solns inst_infos_in eqns solns
          = mkVanillaId (getName tycon) dummy_dfun_ty
                -- The name is getSrcLoc'd in an error message 
 
-       dummy_dfun_ty = mkSigmaTy tyvars theta voidTy
+       theta' = classesToPreds theta
+       dummy_dfun_ty = mkSigmaTy tyvars theta' voidTy
                -- All we need from the dfun is its "theta" part, used during
                -- equation simplification (tcSimplifyThetas).  The final
                -- dfun_id will have the superclass dictionaries as arguments too,
@@ -583,12 +581,12 @@ gen_bind fixities (InstInfo clas _ [ty] _ _ _ _ _)
       ckey       = classKey clas
            
 
-gen_inst_info :: Module                                        -- Module name
-             -> (InstInfo, (Name, RenamedMonoBinds))           -- the main stuff to work on
+gen_inst_info :: InstInfo
+             -> (Name, RenamedMonoBinds)
              -> InstInfo                               -- the gen'd (filled-in) "instance decl"
 
-gen_inst_info modname
-    (InstInfo clas tyvars tys@(ty:_) inst_decl_theta _ _ locn _, (dfun_name, meth_binds))
+gen_inst_info (InstInfo clas tyvars tys@(ty:_) inst_decl_theta _ _ locn _) 
+             (dfun_name, meth_binds)
   =
        -- Generate the various instance-related Ids
     InstInfo clas tyvars tys inst_decl_theta
@@ -670,7 +668,8 @@ gen_taggery_Names inst_infos
     do_tag2con acc_Names tycon
       | isDataTyCon tycon &&
          (we_are_deriving enumClassKey tycon ||
-         we_are_deriving ixClassKey   tycon)
+         we_are_deriving ixClassKey   tycon
+         && isEnumerationTyCon tycon)
       = returnTc ( (tag2con_RDR tycon, tycon, GenTag2Con)
                 : (maxtag_RDR  tycon, tycon, GenMaxTag)
                 : acc_Names)
@@ -688,12 +687,16 @@ gen_taggery_Names inst_infos
 \end{code}
 
 \begin{code}
-derivingThingErr :: FAST_STRING -> FAST_STRING -> TyCon -> Message
+derivingThingErr :: Class -> TyCon -> FAST_STRING -> Message
+
+derivingThingErr clas tycon why
+  = sep [hsep [ptext SLIT("Can't make a derived instance of"), quotes (ppr clas)],
+        hsep [ptext SLIT("for the type"), quotes (ppr tycon)],
+        parens (ptext why)]
 
-derivingThingErr thing why tycon
-  = hang (hsep [ptext SLIT("Can't make a derived instance of"), ptext thing])
-        0 (hang (hsep [ptext SLIT("for the type"), quotes (ppr tycon)])
-                0 (parens (ptext why)))
+existentialErr clas tycon
+  = sep [ptext SLIT("Can't derive any instances for type") <+> quotes (ppr tycon),
+        ptext SLIT("because it has existentially-quantified constructor(s)")]
 
 derivCtxt tycon
   = ptext SLIT("When deriving classes for") <+> quotes (ppr tycon)