Improve the error message when we cannot derive Generic.
authorJose Pedro Magalhaes <jpm@cs.uu.nl>
Mon, 9 May 2011 09:52:47 +0000 (11:52 +0200)
committerJose Pedro Magalhaes <jpm@cs.uu.nl>
Mon, 9 May 2011 09:52:47 +0000 (11:52 +0200)
compiler/typecheck/TcDeriv.lhs
compiler/types/Generics.lhs

index 4d80631..a3ce1a9 100644 (file)
@@ -993,8 +993,11 @@ no_cons_why rep_tc = quotes (pprSourceTyCon rep_tc) <+>
 
 -- JPM TODO: should give better error message
 cond_RepresentableOk :: Condition
+{-
 cond_RepresentableOk (_,t) | canDoGenerics t = Nothing
                            | otherwise       = Just (ptext (sLit "Cannot derive Generic for type") <+> ppr t)
+-}
+cond_RepresentableOk (_,t) = canDoGenerics t
 
 cond_enumOrProduct :: Condition
 cond_enumOrProduct = cond_isEnumeration `orCond` 
index 940f36f..2adcc58 100644 (file)
@@ -42,29 +42,47 @@ import FastString
 %************************************************************************
 
 \begin{code}
-canDoGenerics :: TyCon -> Bool
+canDoGenerics :: TyCon -> Maybe SDoc
 -- Called on source-code data types, to see if we should generate
 -- generic functions for them.
+-- Nothing == yes
+-- Just s  == no, because of `s`
 
 canDoGenerics tycon
-  =  let result = not (any bad_con (tyConDataCons tycon))      -- See comment below
-                  -- We do not support datatypes with context (for now)
-                  && null (tyConStupidTheta tycon)
-                  -- We don't like type families
-                  && not (isFamilyTyCon tycon)
-
-     in {- pprTrace "canDoGenerics" (ppr (tycon,result)) -} result
+  =  mergeErrors (
+          -- We do not support datatypes with context
+              (if (not (null (tyConStupidTheta tycon)))
+                then (Just (ppr tycon <+> text "has a datatype context"))
+                else Nothing)
+          -- We don't like type families
+            : (if (isFamilyTyCon tycon)
+                then (Just (ppr tycon <+> text "is a family instance"))
+                else Nothing)
+          -- See comment below
+            : (map bad_con (tyConDataCons tycon)))
   where
-    bad_con dc = any bad_arg_type (dataConOrigArgTys dc) || not (isVanillaDataCon dc)
-       -- If any of the constructor has an unboxed type as argument,
-       -- then we can't build the embedding-projection pair, because
-       -- it relies on instantiating *polymorphic* sum and product types
-       -- at the argument types of the constructors
+        -- If any of the constructor has an unboxed type as argument,
+        -- then we can't build the embedding-projection pair, because
+        -- it relies on instantiating *polymorphic* sum and product types
+        -- at the argument types of the constructors
+    bad_con dc = if (any bad_arg_type (dataConOrigArgTys dc))
+                  then (Just (ppr dc <+> text "has unlifted or polymorphic arguments"))
+                  else (if (not (isVanillaDataCon dc))
+                          then (Just (ppr dc <+> text "is not a vanilla data constructor"))
+                          else Nothing)
+
 
        -- Nor can we do the job if it's an existential data constructor,
 
        -- Nor if the args are polymorphic types (I don't think)
     bad_arg_type ty = isUnLiftedType ty || not (isTauTy ty)
+    
+    mergeErrors :: [Maybe SDoc] -> Maybe SDoc
+    mergeErrors []           = Nothing
+    mergeErrors ((Just s):t) = case mergeErrors t of
+                                 Nothing -> Just s
+                                 Just s' -> Just (s $$ s')
+    mergeErrors (Nothing :t) = mergeErrors t
 \end{code}
 
 %************************************************************************