[commit: ghc] master: Do not generate duplicate instances with AutoDeriveTypeable (2154b82)

José Pedro Magalhães jpm at cs.uu.nl
Fri Mar 8 11:44:11 CET 2013


Repository : http://darcs.haskell.org/ghc.git/

On branch  : master

http://hackage.haskell.org/trac/ghc/changeset/2154b82e97632abef64e73cc0f6c5cd13ab8e71c

>---------------------------------------------------------------

commit 2154b82e97632abef64e73cc0f6c5cd13ab8e71c
Author: Jose Pedro Magalhaes <jpm at cs.ox.ac.uk>
Date:   Fri Mar 8 10:42:39 2013 +0000

    Do not generate duplicate instances with AutoDeriveTypeable

>---------------------------------------------------------------

 compiler/typecheck/TcDeriv.lhs | 46 +++++++++++++++++++++++++-----------------
 1 file changed, 27 insertions(+), 19 deletions(-)

diff --git a/compiler/typecheck/TcDeriv.lhs b/compiler/typecheck/TcDeriv.lhs
index c52be42..1244aca 100644
--- a/compiler/typecheck/TcDeriv.lhs
+++ b/compiler/typecheck/TcDeriv.lhs
@@ -313,14 +313,7 @@ tcDeriving tycl_decls inst_decls deriv_decls
           is_boot <- tcIsHsBoot
         ; traceTc "tcDeriving" (ppr is_boot)
 
-        -- If -XAutoDeriveTypeable is on, add Typeable instances for each
-        -- datatype and class defined in this module
-        ; isAutoDeriveTypeable <- xoptM Opt_AutoDeriveTypeable
-        ; let deriv_decls' = deriv_decls ++ if isAutoDeriveTypeable
-                                              then deriveTypeable tycl_decls
-                                              else []
-
-        ; early_specs <- makeDerivSpecs is_boot tycl_decls inst_decls deriv_decls'
+        ; early_specs <- makeDerivSpecs is_boot tycl_decls inst_decls deriv_decls
         ; traceTc "tcDeriving 1" (ppr early_specs)
 
         -- for each type, determine the auxliary declarations that are common
@@ -376,12 +369,6 @@ tcDeriving tycl_decls inst_decls deriv_decls
 
     hangP s x = text "" $$ hang (ptext (sLit s)) 2 x
 
-    deriveTypeable :: [LTyClDecl Name] -> [LDerivDecl Name]
-    deriveTypeable tys =
-      [ L l (DerivDecl (L l (HsAppTy (noLoc (HsTyVar typeableClassName))
-                                     (L l (HsTyVar (tcdName t))))))
-      | L l t <- tys, not (isSynDecl t), not (isTypeFamilyDecl t) ]
-
 -- Prints the representable type family instance
 pprRepTy :: FamInst Unbranched -> SDoc
 pprRepTy fi@(FamInst { fi_branches = FirstBranch (FamInstBranch { fib_lhs = lhs
@@ -492,17 +479,38 @@ makeDerivSpecs is_boot tycl_decls inst_decls deriv_decls
         ; eqns2 <- concatMapM (recoverM (return []) . deriveInstDecl) inst_decls
         ; eqns3 <- mapAndRecoverM deriveStandalone deriv_decls
         ; let eqns = eqns1 ++ eqns2 ++ eqns3
+
+        -- If AutoDeriveTypeable is set, we automatically add Typeable instances
+        -- for every data type and type class declared in the module
+        ; isAutoTypeable <- xoptM Opt_AutoDeriveTypeable
+        ; let eqns4 = if isAutoTypeable then deriveTypeable tycl_decls eqns else []
+        ; eqns4' <- mapAndRecoverM deriveStandalone eqns4
+        ; let eqns' = eqns ++ eqns4'
+
         ; if is_boot then   -- No 'deriving' at all in hs-boot files
-              do { unless (null eqns) (add_deriv_err (head eqns))
+              do { unless (null eqns') (add_deriv_err (head eqns'))
                  ; return [] }
-          else return eqns }
+          else return eqns' }
   where
+    deriveTypeable :: [LTyClDecl Name] -> [EarlyDerivSpec] -> [LDerivDecl Name]
+    deriveTypeable tys dss =
+      [ L l (DerivDecl (L l (HsAppTy (noLoc (HsTyVar typeableClassName))
+                                     (L l (HsTyVar (tcdName t))))))
+      | L l t <- tys
+        -- Don't add Typeable instances for type synonyms and type families
+      , not (isSynDecl t), not (isTypeFamilyDecl t)
+        -- ... nor if the user has already given a deriving clause
+      , not (hasInstance (tcdName t) dss) ]
+
+    -- Check if an automatically generated DS for deriving Typeable should be
+    -- ommitted because the user had manually requested for an instance
+    hasInstance :: Name -> [EarlyDerivSpec] -> Bool
+    hasInstance n = any (\ds -> n == tyConName (either ds_tc ds_tc ds))
+
     add_deriv_err eqn
-       = setSrcSpan loc $
+       = setSrcSpan (either ds_loc ds_loc eqn) $
          addErr (hang (ptext (sLit "Deriving not permitted in hs-boot file"))
                     2 (ptext (sLit "Use an instance declaration instead")))
-       where
-         loc = case eqn of  { Left ds -> ds_loc ds; Right ds -> ds_loc ds }
 
 ------------------------------------------------------------------
 deriveTyDecl :: LTyClDecl Name -> TcM [EarlyDerivSpec]





More information about the ghc-commits mailing list