[commit: ghc] master: Unique-ify the names of top-level auxiliary bindings in derived instances (Trac #7947) (c41d214)
git at git.haskell.org
git at git.haskell.org
Tue Dec 2 15:13:05 UTC 2014
Repository : ssh://git@git.haskell.org/ghc
On branch : master
Link : http://ghc.haskell.org/trac/ghc/changeset/c41d214a8dd8e2fe7ae9a3446aeda1a07328b831/ghc
>---------------------------------------------------------------
commit c41d214a8dd8e2fe7ae9a3446aeda1a07328b831
Author: Simon Peyton Jones <simonpj at microsoft.com>
Date: Tue Dec 2 15:13:32 2014 +0000
Unique-ify the names of top-level auxiliary bindings in derived instances (Trac #7947)
The problem and its solution are explained in
Note [Auxiliary binders]
in TcGenDeriv
>---------------------------------------------------------------
c41d214a8dd8e2fe7ae9a3446aeda1a07328b831
compiler/typecheck/TcGenDeriv.lhs | 49 +++++++++++++++++++----
testsuite/tests/deriving/should_compile/T7947.hs | 16 ++++++++
testsuite/tests/deriving/should_compile/T7947a.hs | 3 ++
testsuite/tests/deriving/should_compile/T7947b.hs | 3 ++
testsuite/tests/deriving/should_compile/all.T | 1 +
5 files changed, 64 insertions(+), 8 deletions(-)
diff --git a/compiler/typecheck/TcGenDeriv.lhs b/compiler/typecheck/TcGenDeriv.lhs
index 0d4374b..13d8e83 100644
--- a/compiler/typecheck/TcGenDeriv.lhs
+++ b/compiler/typecheck/TcGenDeriv.lhs
@@ -65,6 +65,7 @@ import Pair
import Bag
import Fingerprint
import TcEnv (InstInfo)
+import StaticFlags( opt_PprStyle_Debug )
import ListSetOps ( assocMaybe )
import Data.List ( partition, intersperse )
@@ -2294,6 +2295,11 @@ f_Pat = nlVarPat f_RDR
k_Pat = nlVarPat k_RDR
z_Pat = nlVarPat z_RDR
+minusInt_RDR, tagToEnum_RDR, error_RDR :: RdrName
+minusInt_RDR = getRdrName (primOpId IntSubOp )
+tagToEnum_RDR = getRdrName (primOpId TagToEnumOp)
+error_RDR = getRdrName eRROR_ID
+
con2tag_RDR, tag2con_RDR, maxtag_RDR :: TyCon -> RdrName
-- Generates Orig s RdrName, for the binding positions
con2tag_RDR tycon = mk_tc_deriv_name tycon mkCon2TagOcc
@@ -2304,13 +2310,40 @@ mk_tc_deriv_name :: TyCon -> (OccName -> OccName) -> RdrName
mk_tc_deriv_name tycon occ_fun = mkAuxBinderName (tyConName tycon) occ_fun
mkAuxBinderName :: Name -> (OccName -> OccName) -> RdrName
-mkAuxBinderName parent occ_fun = mkRdrUnqual (occ_fun (nameOccName parent))
--- Was: mkDerivedRdrName name occ_fun, which made an original name
--- But: (a) that does not work well for standalone-deriving
--- (b) an unqualified name is just fine, provided it can't clash with user code
+-- ^ Make a top-level binder name for an auxiliary binding for a parent name
+-- See Note [Auxiliary binders]
+mkAuxBinderName parent occ_fun
+ = mkRdrUnqual (occ_fun uniq_parent_occ)
+ where
+ uniq_parent_occ = mkOccName (occNameSpace parent_occ) uniq_string
-minusInt_RDR, tagToEnum_RDR, error_RDR :: RdrName
-minusInt_RDR = getRdrName (primOpId IntSubOp )
-tagToEnum_RDR = getRdrName (primOpId TagToEnumOp)
-error_RDR = getRdrName eRROR_ID
+ uniq_string
+ | opt_PprStyle_Debug = showSDocSimple (ppr parent_occ <> underscore <> ppr parent_uniq)
+ | otherwise = show parent_uniq
+ -- The debug thing is just to generate longer, but perhaps more perspicuous, names
+
+ parent_uniq = nameUnique parent
+ parent_occ = nameOccName parent
\end{code}
+
+Note [Auxiliary binders]
+~~~~~~~~~~~~~~~~~~~~~~~~
+We often want to make a top-level auxiliary binding. E.g. for comparison we haev
+
+ instance Ord T where
+ compare a b = $con2tag a `compare` $con2tag b
+
+ $con2tag :: T -> Int
+ $con2tag = ...code....
+
+Of course these top-level bindings should all have distinct name, and we are
+generating RdrNames here. We can't just use the TyCon or DataCon to distinguish
+becuase with standalone deriving two imported TyCons might both be called T!
+(See Trac #7947.)
+
+So we use the *unique* from the parent name (T in this example) as part of the
+OccName we generate for the new binding.
+
+In the past we used mkDerivedRdrName name occ_fun, which made an original name
+But: (a) that does not work well for standalone-deriving either
+ (b) an unqualified name is just fine, provided it can't clash with user code
diff --git a/testsuite/tests/deriving/should_compile/T7947.hs b/testsuite/tests/deriving/should_compile/T7947.hs
new file mode 100644
index 0000000..d4df435
--- /dev/null
+++ b/testsuite/tests/deriving/should_compile/T7947.hs
@@ -0,0 +1,16 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE StandaloneDeriving #-}
+
+module T7947 where
+
+import Data.Data
+import Data.Typeable
+
+import T7947a
+import qualified T7947b as B
+
+deriving instance Typeable A
+deriving instance Typeable B.B
+
+deriving instance Data A
+deriving instance Data B.B
diff --git a/testsuite/tests/deriving/should_compile/T7947a.hs b/testsuite/tests/deriving/should_compile/T7947a.hs
new file mode 100644
index 0000000..eb5c747
--- /dev/null
+++ b/testsuite/tests/deriving/should_compile/T7947a.hs
@@ -0,0 +1,3 @@
+module T7947a where
+
+data A = C1 | C2 | C
diff --git a/testsuite/tests/deriving/should_compile/T7947b.hs b/testsuite/tests/deriving/should_compile/T7947b.hs
new file mode 100644
index 0000000..f17f1cd
--- /dev/null
+++ b/testsuite/tests/deriving/should_compile/T7947b.hs
@@ -0,0 +1,3 @@
+module T7947b where
+
+data B = D1 | D2 | C
diff --git a/testsuite/tests/deriving/should_compile/all.T b/testsuite/tests/deriving/should_compile/all.T
index 2234dd5..8d90236 100644
--- a/testsuite/tests/deriving/should_compile/all.T
+++ b/testsuite/tests/deriving/should_compile/all.T
@@ -52,4 +52,5 @@ test('T7269', normal, compile, [''])
test('T9069', normal, compile, [''])
test('T9359', normal, compile, [''])
test('T4896', normal, compile, [''])
+test('T7947', extra_clean(['T7947a.o', 'T7947a.hi', 'T7947b.o', 'T7947b.hi']), multimod_compile, ['T7947', '-v0'])
More information about the ghc-commits
mailing list