[commit: ghc] master: Fix another bug in deriving( Data ) for data families; Trac #4896 (863854a)

git at git.haskell.org git at git.haskell.org
Tue Dec 2 13:27:46 UTC 2014


Repository : ssh://git@git.haskell.org/ghc

On branch  : master
Link       : http://ghc.haskell.org/trac/ghc/changeset/863854a3a490afd9e3ecf0da6294a3b078f4a6a1/ghc

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

commit 863854a3a490afd9e3ecf0da6294a3b078f4a6a1
Author: Simon Peyton Jones <simonpj at microsoft.com>
Date:   Tue Dec 2 13:20:33 2014 +0000

    Fix another bug in deriving( Data ) for data families; Trac #4896
    
    If we have
    
       data family D a
       data instance D (a,b,c) = ... deriving( Data )
    
    then we want to generate
    
       instance ... => Data (D (a,b,c)) where
         ...
         dataCast1 x = gcast1 x
    
    The "1" here comes from the kind of D.  But the kind of the
    *representation* TyCon is
    
       data Drep a b c = ....
    
    ie Drep :: * -> * -> * -> *
    
    So we must look for the *family* TyCon in this (rather horrible)
    dataCast1 / dataCast2 binding.


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

863854a3a490afd9e3ecf0da6294a3b078f4a6a1
 compiler/typecheck/TcGenDeriv.lhs                | 34 +++++++++++++++++-------
 testsuite/tests/deriving/should_compile/T4896.hs | 19 +++++++++++++
 testsuite/tests/deriving/should_compile/all.T    |  2 ++
 3 files changed, 46 insertions(+), 9 deletions(-)

diff --git a/compiler/typecheck/TcGenDeriv.lhs b/compiler/typecheck/TcGenDeriv.lhs
index 9b5ef8b..0d4374b 100644
--- a/compiler/typecheck/TcGenDeriv.lhs
+++ b/compiler/typecheck/TcGenDeriv.lhs
@@ -1323,18 +1323,19 @@ we generate
 
 \begin{code}
 gen_Data_binds :: DynFlags
-                -> SrcSpan
-               -> TyCon
+               -> SrcSpan
+               -> TyCon                 -- For data families, this is the
+                                        --  *representation* TyCon
                -> (LHsBinds RdrName,    -- The method bindings
                    BagDerivStuff)       -- Auxiliary bindings
-gen_Data_binds dflags loc tycon
+gen_Data_binds dflags loc rep_tc
   = (listToBag [gfoldl_bind, gunfold_bind, toCon_bind, dataTypeOf_bind]
      `unionBags` gcast_binds,
                 -- Auxiliary definitions: the data type and constructors
      listToBag ( DerivHsBind (genDataTyCon)
                : map (DerivHsBind . genDataDataCon) data_cons))
   where
-    data_cons  = tyConDataCons tycon
+    data_cons  = tyConDataCons rep_tc
     n_cons     = length data_cons
     one_constr = n_cons == 1
 
@@ -1343,11 +1344,11 @@ gen_Data_binds dflags loc tycon
       = (mkHsVarBind loc rdr_name rhs,
          L loc (TypeSig [L loc rdr_name] sig_ty PlaceHolder))
       where
-        rdr_name = mk_data_type_name tycon
+        rdr_name = mk_data_type_name rep_tc
         sig_ty   = nlHsTyVar dataType_RDR
-        constrs  = [nlHsVar (mk_constr_name con) | con <- tyConDataCons tycon]
+        constrs  = [nlHsVar (mk_constr_name con) | con <- tyConDataCons rep_tc]
         rhs = nlHsVar mkDataType_RDR
-              `nlHsApp` nlHsLit (mkHsString (showSDocOneLine dflags (ppr tycon)))
+              `nlHsApp` nlHsLit (mkHsString (showSDocOneLine dflags (ppr rep_tc)))
               `nlHsApp` nlList constrs
 
     genDataDataCon :: DataCon -> (LHsBind RdrName, LSig RdrName)
@@ -1418,10 +1419,25 @@ gen_Data_binds dflags loc tycon
                         loc
                         dataTypeOf_RDR
                         [nlWildPat]
-                        (nlHsVar (mk_data_type_name tycon))
+                        (nlHsVar (mk_data_type_name rep_tc))
 
         ------------ gcast1/2
-    tycon_kind = tyConKind tycon
+        -- Make the binding    dataCast1 x = gcast1 x  -- if T :: * -> *
+        --               or    dataCast2 x = gcast2 s  -- if T :: * -> * -> *
+        -- (or nothing if T has neither of these two types)
+
+        -- But care is needed for data families:
+        -- If we have   data family D a
+        --              data instance D (a,b,c) = A | B deriving( Data )
+        -- and we want  instance ... => Data (D [(a,b,c)]) where ...
+        -- then we need     dataCast1 x = gcast1 x
+        -- because D :: * -> *
+        -- even though rep_tc has kind * -> * -> * -> *
+        -- Hence looking for the kind of fam_tc not rep_tc
+        -- See Trac #4896
+    tycon_kind = case tyConFamInst_maybe rep_tc of
+                    Just (fam_tc, _) -> tyConKind fam_tc
+                    Nothing          -> tyConKind rep_tc
     gcast_binds | tycon_kind `tcEqKind` kind1 = mk_gcast dataCast1_RDR gcast1_RDR
                 | tycon_kind `tcEqKind` kind2 = mk_gcast dataCast2_RDR gcast2_RDR
                 | otherwise                 = emptyBag
diff --git a/testsuite/tests/deriving/should_compile/T4896.hs b/testsuite/tests/deriving/should_compile/T4896.hs
new file mode 100644
index 0000000..18fcc7c
--- /dev/null
+++ b/testsuite/tests/deriving/should_compile/T4896.hs
@@ -0,0 +1,19 @@
+{-# LANGUAGE FlexibleInstances, FlexibleContexts, UndecidableInstances, TypeFamilies, DeriveDataTypeable, StandaloneDeriving #-}
+
+module T4896 where
+
+import Data.Data
+import Data.Typeable
+
+--instance Typeable1 Bar where
+--  typeOf1 _ = mkTyConApp (mkTyCon "Main.Bar") []
+deriving instance Typeable Bar
+
+class Foo a where
+  data Bar a
+
+data D a b = D Int a deriving (Typeable, Data)
+
+instance Foo (D a b) where
+  data Bar (D a b) = B { l :: a } deriving (Eq, Ord, Read, Show, Data)
+
diff --git a/testsuite/tests/deriving/should_compile/all.T b/testsuite/tests/deriving/should_compile/all.T
index 3bf871d..2234dd5 100644
--- a/testsuite/tests/deriving/should_compile/all.T
+++ b/testsuite/tests/deriving/should_compile/all.T
@@ -51,3 +51,5 @@ test('T8963', normal, compile, [''])
 test('T7269', normal, compile, [''])
 test('T9069', normal, compile, [''])
 test('T9359', normal, compile, [''])
+test('T4896', normal, compile, [''])
+



More information about the ghc-commits mailing list