Use addToUFM_Acc where appropriate
[ghc-hetmet.git] / compiler / basicTypes / OccName.lhs
index ba17c02..8248b5f 100644 (file)
@@ -4,63 +4,89 @@
 %
 
 \begin{code}
 %
 
 \begin{code}
+-- |
+-- #name_types#
+-- GHC uses several kinds of name internally:
+--
+-- * 'OccName.OccName' represents names as strings with just a little more information:
+--   the \"namespace\" that the name came from, e.g. the namespace of value, type constructors or
+--   data constructors
+--
+-- * 'RdrName.RdrName': see "RdrName#name_types"
+--
+-- * 'Name.Name': see "Name#name_types"
+--
+-- * 'Id.Id': see "Id#name_types"
+--
+-- * 'Var.Var': see "Var#name_types"
 module OccName (
 module OccName (
-       -- * The NameSpace type; abstact
-       NameSpace, tcName, clsName, tcClsName, dataName, varName, 
+       -- * The 'NameSpace' type
+       NameSpace, -- Abstract
+       
+       -- ** Construction
+       -- $real_vs_source_data_constructors
+       tcName, clsName, tcClsName, dataName, varName, 
        tvName, srcDataName,
 
        tvName, srcDataName,
 
-       -- ** Printing
+       -- ** Pretty Printing
        pprNameSpace, pprNonVarNameSpace, pprNameSpaceBrief,
 
        pprNameSpace, pprNonVarNameSpace, pprNameSpaceBrief,
 
-       -- * The OccName type
+       -- * The 'OccName' type
        OccName,        -- Abstract, instance of Outputable
        pprOccName, 
 
        -- ** Construction      
        mkOccName, mkOccNameFS, 
        mkVarOcc, mkVarOccFS,
        OccName,        -- Abstract, instance of Outputable
        pprOccName, 
 
        -- ** Construction      
        mkOccName, mkOccNameFS, 
        mkVarOcc, mkVarOccFS,
-       mkTyVarOcc,
+       mkDataOcc, mkDataOccFS,
+       mkTyVarOcc, mkTyVarOccFS,
+       mkTcOcc, mkTcOccFS,
+       mkClsOcc, mkClsOccFS,
        mkDFunOcc,
        mkTupleOcc, 
        setOccNameSpace,
 
        mkDFunOcc,
        mkTupleOcc, 
        setOccNameSpace,
 
-       -- ** Derived OccNames
+       -- ** Derived 'OccName's
+        isDerivedOccName,
        mkDataConWrapperOcc, mkWorkerOcc, mkDefaultMethodOcc,
        mkDataConWrapperOcc, mkWorkerOcc, mkDefaultMethodOcc,
-       mkDerivedTyConOcc, mkNewTyCoOcc,
+       mkDerivedTyConOcc, mkNewTyCoOcc, mkClassOpAuxOcc,
+        mkCon2TagOcc, mkTag2ConOcc, mkMaxTagOcc,
        mkClassTyConOcc, mkClassDataConOcc, mkDictOcc, mkIPOcc, 
        mkSpecOcc, mkForeignExportOcc, mkGenOcc1, mkGenOcc2,
        mkDataTOcc, mkDataCOcc, mkDataConWorkerOcc,
        mkSuperDictSelOcc, mkLocalOcc, mkMethodOcc, mkInstTyTcOcc,
        mkInstTyCoOcc, mkEqPredCoOcc,
         mkVectOcc, mkVectTyConOcc, mkVectDataConOcc, mkVectIsoOcc,
        mkClassTyConOcc, mkClassDataConOcc, mkDictOcc, mkIPOcc, 
        mkSpecOcc, mkForeignExportOcc, mkGenOcc1, mkGenOcc2,
        mkDataTOcc, mkDataCOcc, mkDataConWorkerOcc,
        mkSuperDictSelOcc, mkLocalOcc, mkMethodOcc, mkInstTyTcOcc,
        mkInstTyCoOcc, mkEqPredCoOcc,
         mkVectOcc, mkVectTyConOcc, mkVectDataConOcc, mkVectIsoOcc,
-        mkPArrayTyConOcc, mkPArrayDataConOcc,
-        mkPReprTyConOcc,
+        mkPDataTyConOcc, mkPDataDataConOcc,
+        mkPReprTyConOcc, 
         mkPADFunOcc,
 
        -- ** Deconstruction
        occNameFS, occNameString, occNameSpace, 
 
        isVarOcc, isTvOcc, isTcOcc, isDataOcc, isDataSymOcc, isSymOcc, isValOcc,
         mkPADFunOcc,
 
        -- ** Deconstruction
        occNameFS, occNameString, occNameSpace, 
 
        isVarOcc, isTvOcc, isTcOcc, isDataOcc, isDataSymOcc, isSymOcc, isValOcc,
-       parenSymOcc, reportIfUnused, isTcClsName, isVarName,
+       parenSymOcc, startsWithUnderscore, 
+       
+       isTcClsNameSpace, isTvNameSpace, isDataConNameSpace, isVarNameSpace, isValNameSpace,
 
        isTupleOcc_maybe,
 
 
        isTupleOcc_maybe,
 
-       -- The OccEnv type
+       -- * The 'OccEnv' type
        OccEnv, emptyOccEnv, unitOccEnv, extendOccEnv, mapOccEnv,
        lookupOccEnv, mkOccEnv, mkOccEnv_C, extendOccEnvList, elemOccEnv,
        occEnvElts, foldOccEnv, plusOccEnv, plusOccEnv_C, extendOccEnv_C,
        OccEnv, emptyOccEnv, unitOccEnv, extendOccEnv, mapOccEnv,
        lookupOccEnv, mkOccEnv, mkOccEnv_C, extendOccEnvList, elemOccEnv,
        occEnvElts, foldOccEnv, plusOccEnv, plusOccEnv_C, extendOccEnv_C,
-        filterOccEnv, delListFromOccEnv, delFromOccEnv,
+        extendOccEnv_Acc, filterOccEnv, delListFromOccEnv, delFromOccEnv,
 
 
-       -- The OccSet type
+       -- * The 'OccSet' type
        OccSet, emptyOccSet, unitOccSet, mkOccSet, extendOccSet, 
        extendOccSetList,
        unionOccSets, unionManyOccSets, minusOccSet, elemOccSet, occSetElts, 
        foldOccSet, isEmptyOccSet, intersectOccSet, intersectsOccSet,
                   
        OccSet, emptyOccSet, unitOccSet, mkOccSet, extendOccSet, 
        extendOccSetList,
        unionOccSets, unionManyOccSets, minusOccSet, elemOccSet, occSetElts, 
        foldOccSet, isEmptyOccSet, intersectOccSet, intersectsOccSet,
                   
-       -- Tidying up
+       -- * Tidying up
        TidyOccEnv, emptyTidyOccEnv, tidyOccName, initTidyOccEnv,
 
        TidyOccEnv, emptyTidyOccEnv, tidyOccName, initTidyOccEnv,
 
-       -- The basic form of names
+       -- * Lexical characteristics of Haskell names
        isLexCon, isLexVar, isLexId, isLexSym,
        isLexConId, isLexConSym, isLexVarId, isLexVarSym,
        startsVarSym, startsVarId, startsConSym, startsConId
        isLexCon, isLexVar, isLexId, isLexSym,
        isLexConId, isLexConSym, isLexVarId, isLexVarSym,
        startsVarSym, startsVarId, startsConSym, startsConId
@@ -69,17 +95,15 @@ module OccName (
 import Util
 import Unique
 import BasicTypes
 import Util
 import Unique
 import BasicTypes
-import StaticFlags
 import UniqFM
 import UniqSet
 import FastString
 import UniqFM
 import UniqSet
 import FastString
-import FastTypes
 import Outputable
 import Binary
 import Outputable
 import Binary
-
-import GHC.Exts
 import Data.Char
 import Data.Char
+\end{code}
 
 
+\begin{code}
 -- Unicode TODO: put isSymbol in libcompat
 #if !defined(__GLASGOW_HASKELL__) || __GLASGOW_HASKELL__ > 604
 #else
 -- Unicode TODO: put isSymbol in libcompat
 #if !defined(__GLASGOW_HASKELL__) || __GLASGOW_HASKELL__ > 604
 #else
@@ -106,19 +130,21 @@ data NameSpace = VarName  -- Variables, including "real" data constructors
 
 -- Note [Data Constructors]  
 -- see also: Note [Data Constructor Naming] in DataCon.lhs
 
 -- Note [Data Constructors]  
 -- see also: Note [Data Constructor Naming] in DataCon.lhs
--- 
---     "Source" data constructors are the data constructors mentioned
---     in Haskell source code
 --
 --
---     "Real" data constructors are the data constructors of the
---     representation type, which may not be the same as the source
---     type
-
--- Example:
---     data T = T !(Int,Int)
+-- $real_vs_source_data_constructors
+-- There are two forms of data constructor:
+--
+--     [Source data constructors] The data constructors mentioned in Haskell source code
+--
+--     [Real data constructors] The data constructors of the representation type, which may not be the same as the source type
+--
+-- For example:
+--
+-- > data T = T !(Int, Int)
+--
+-- The source datacon has type @(Int, Int) -> T@
+-- The real   datacon has type @Int -> Int -> T@
 --
 --
--- The source datacon has type (Int,Int) -> T
--- The real   datacon has type Int -> Int -> T
 -- GHC chooses a representation based on the strictness etc.
 
 tcName, clsName, tcClsName :: NameSpace
 -- GHC chooses a representation based on the strictness etc.
 
 tcName, clsName, tcClsName :: NameSpace
@@ -138,14 +164,27 @@ srcDataName = DataName    -- Haskell-source data constructors should be
 tvName      = TvName
 varName     = VarName
 
 tvName      = TvName
 varName     = VarName
 
-isTcClsName :: NameSpace -> Bool
-isTcClsName TcClsName = True
-isTcClsName _        = False
+isDataConNameSpace :: NameSpace -> Bool
+isDataConNameSpace DataName = True
+isDataConNameSpace _        = False
+
+isTcClsNameSpace :: NameSpace -> Bool
+isTcClsNameSpace TcClsName = True
+isTcClsNameSpace _         = False
+
+isTvNameSpace :: NameSpace -> Bool
+isTvNameSpace TvName = True
+isTvNameSpace _      = False
 
 
-isVarName :: NameSpace -> Bool -- Variables or type variables, but not constructors
-isVarName TvName  = True
-isVarName VarName = True
-isVarName _       = False
+isVarNameSpace :: NameSpace -> Bool    -- Variables or type variables, but not constructors
+isVarNameSpace TvName  = True
+isVarNameSpace VarName = True
+isVarNameSpace _       = False
+
+isValNameSpace :: NameSpace -> Bool
+isValNameSpace DataName = True
+isValNameSpace VarName  = True
+isValNameSpace _        = False
 
 pprNameSpace :: NameSpace -> SDoc
 pprNameSpace DataName  = ptext (sLit "data constructor")
 
 pprNameSpace :: NameSpace -> SDoc
 pprNameSpace DataName  = ptext (sLit "data constructor")
@@ -230,8 +269,29 @@ mkVarOcc s = mkOccName varName s
 mkVarOccFS :: FastString -> OccName
 mkVarOccFS fs = mkOccNameFS varName fs
 
 mkVarOccFS :: FastString -> OccName
 mkVarOccFS fs = mkOccNameFS varName fs
 
-mkTyVarOcc :: FastString -> OccName
-mkTyVarOcc fs = mkOccNameFS tvName fs
+mkDataOcc :: String -> OccName
+mkDataOcc = mkOccName dataName
+
+mkDataOccFS :: FastString -> OccName
+mkDataOccFS = mkOccNameFS dataName
+
+mkTyVarOcc :: String -> OccName
+mkTyVarOcc = mkOccName tvName
+
+mkTyVarOccFS :: FastString -> OccName
+mkTyVarOccFS fs = mkOccNameFS tvName fs
+
+mkTcOcc :: String -> OccName
+mkTcOcc = mkOccName tcName
+
+mkTcOccFS :: FastString -> OccName
+mkTcOccFS = mkOccNameFS tcName
+
+mkClsOcc :: String -> OccName
+mkClsOcc = mkOccName clsName
+
+mkClsOccFS :: FastString -> OccName
+mkClsOccFS = mkOccNameFS clsName
 \end{code}
 
 
 \end{code}
 
 
@@ -243,22 +303,24 @@ mkTyVarOcc fs = mkOccNameFS tvName fs
 
 OccEnvs are used mainly for the envts in ModIfaces.
 
 
 OccEnvs are used mainly for the envts in ModIfaces.
 
+Note [The Unique of an OccName]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 They are efficient, because FastStrings have unique Int# keys.  We assume
 They are efficient, because FastStrings have unique Int# keys.  We assume
-this key is less than 2^24, so we can make a Unique using
+this key is less than 2^24, and indeed FastStrings are allocated keys 
+sequentially starting at 0.
+
+So we can make a Unique using
        mkUnique ns key  :: Unique
 where 'ns' is a Char reprsenting the name space.  This in turn makes it
 easy to build an OccEnv.
 
 \begin{code}
 instance Uniquable OccName where
        mkUnique ns key  :: Unique
 where 'ns' is a Char reprsenting the name space.  This in turn makes it
 easy to build an OccEnv.
 
 \begin{code}
 instance Uniquable OccName where
-  getUnique (OccName ns fs)
-      = mkUnique char (iBox (uniqueOfFS fs))
-      where    -- See notes above about this getUnique function
-        char = case ns of
-               VarName   -> 'i'
-               DataName  -> 'd'
-               TvName    -> 'v'
-               TcClsName -> 't'
+      -- See Note [The Unique of an OccName]
+  getUnique (OccName VarName   fs) = mkVarOccUnique  fs
+  getUnique (OccName DataName  fs) = mkDataOccUnique fs
+  getUnique (OccName TvName    fs) = mkTvOccUnique   fs
+  getUnique (OccName TcClsName fs) = mkTcOccUnique   fs
 
 newtype OccEnv a = A (UniqFM a)
 
 
 newtype OccEnv a = A (UniqFM a)
 
@@ -273,6 +335,7 @@ elemOccEnv   :: OccName -> OccEnv a -> Bool
 foldOccEnv   :: (a -> b -> b) -> b -> OccEnv a -> b
 occEnvElts   :: OccEnv a -> [a]
 extendOccEnv_C :: (a->a->a) -> OccEnv a -> OccName -> a -> OccEnv a
 foldOccEnv   :: (a -> b -> b) -> b -> OccEnv a -> b
 occEnvElts   :: OccEnv a -> [a]
 extendOccEnv_C :: (a->a->a) -> OccEnv a -> OccName -> a -> OccEnv a
+extendOccEnv_Acc :: (a->b->b) -> (a->b) -> OccEnv b -> OccName -> a -> OccEnv b
 plusOccEnv     :: OccEnv a -> OccEnv a -> OccEnv a
 plusOccEnv_C   :: (a->a->a) -> OccEnv a -> OccEnv a -> OccEnv a
 mapOccEnv      :: (a->b) -> OccEnv a -> OccEnv b
 plusOccEnv     :: OccEnv a -> OccEnv a -> OccEnv a
 plusOccEnv_C   :: (a->a->a) -> OccEnv a -> OccEnv a -> OccEnv a
 mapOccEnv      :: (a->b) -> OccEnv a -> OccEnv b
@@ -292,6 +355,7 @@ occEnvElts (A x)     = eltsUFM x
 plusOccEnv (A x) (A y)  = A $ plusUFM x y 
 plusOccEnv_C f (A x) (A y)      = A $ plusUFM_C f x y 
 extendOccEnv_C f (A x) y z   = A $ addToUFM_C f x y z
 plusOccEnv (A x) (A y)  = A $ plusUFM x y 
 plusOccEnv_C f (A x) (A y)      = A $ plusUFM_C f x y 
 extendOccEnv_C f (A x) y z   = A $ addToUFM_C f x y z
+extendOccEnv_Acc f g (A x) y z   = A $ addToUFM_Acc f g x y z
 mapOccEnv f (A x)       = A $ mapUFM f x
 mkOccEnv_C comb l = A $ addListToUFM_C comb emptyUFM l
 delFromOccEnv (A x) y    = A $ delFromUFM x y
 mapOccEnv f (A x)       = A $ mapUFM f x
 mkOccEnv_C comb l = A $ addListToUFM_C comb emptyUFM l
 delFromOccEnv (A x) y    = A $ delFromUFM x y
@@ -348,7 +412,7 @@ occNameString (OccName _ s) = unpackFS s
 setOccNameSpace :: NameSpace -> OccName -> OccName
 setOccNameSpace sp (OccName _ occ) = OccName sp occ
 
 setOccNameSpace :: NameSpace -> OccName -> OccName
 setOccNameSpace sp (OccName _ occ) = OccName sp occ
 
-isVarOcc, isTvOcc, isDataSymOcc, isSymOcc, isTcOcc, isValOcc, isDataOcc :: OccName -> Bool
+isVarOcc, isTvOcc, isTcOcc, isDataOcc :: OccName -> Bool
 
 isVarOcc (OccName VarName _) = True
 isVarOcc _                   = False
 
 isVarOcc (OccName VarName _) = True
 isVarOcc _                   = False
@@ -359,45 +423,52 @@ isTvOcc _                  = False
 isTcOcc (OccName TcClsName _) = True
 isTcOcc _                     = False
 
 isTcOcc (OccName TcClsName _) = True
 isTcOcc _                     = False
 
+-- | /Value/ 'OccNames's are those that are either in 
+-- the variable or data constructor namespaces
+isValOcc :: OccName -> Bool
 isValOcc (OccName VarName  _) = True
 isValOcc (OccName DataName _) = True
 isValOcc _                    = False
 
 isValOcc (OccName VarName  _) = True
 isValOcc (OccName DataName _) = True
 isValOcc _                    = False
 
--- Data constructor operator (starts with ':', or '[]')
--- Pretty inefficient!
-isDataSymOcc (OccName DataName s) = isLexConSym s
-isDataSymOcc (OccName VarName s)  
-  | isLexConSym s = pprPanic "isDataSymOcc: check me" (ppr s)
-               -- Jan06: I don't think this should happen
-isDataSymOcc _                    = False
-
 isDataOcc (OccName DataName _) = True
 isDataOcc (OccName VarName s)  
   | isLexCon s = pprPanic "isDataOcc: check me" (ppr s)
                -- Jan06: I don't think this should happen
 isDataOcc _                    = False
 
 isDataOcc (OccName DataName _) = True
 isDataOcc (OccName VarName s)  
   | isLexCon s = pprPanic "isDataOcc: check me" (ppr s)
                -- Jan06: I don't think this should happen
 isDataOcc _                    = False
 
--- Any operator (data constructor or variable)
+-- | Test if the 'OccName' is a data constructor that starts with
+-- a symbol (e.g. @:@, or @[]@)
+isDataSymOcc :: OccName -> Bool
+isDataSymOcc (OccName DataName s) = isLexConSym s
+isDataSymOcc (OccName VarName s)  
+  | isLexConSym s = pprPanic "isDataSymOcc: check me" (ppr s)
+               -- Jan06: I don't think this should happen
+isDataSymOcc _                    = False
 -- Pretty inefficient!
 -- Pretty inefficient!
+
+-- | Test if the 'OccName' is that for any operator (whether 
+-- it is a data constructor or variable or whatever)
+isSymOcc :: OccName -> Bool
 isSymOcc (OccName DataName s)  = isLexConSym s
 isSymOcc (OccName TcClsName s) = isLexConSym s
 isSymOcc (OccName VarName s)   = isLexSym s
 isSymOcc (OccName TvName s)    = isLexSym s
 isSymOcc (OccName DataName s)  = isLexConSym s
 isSymOcc (OccName TcClsName s) = isLexConSym s
 isSymOcc (OccName VarName s)   = isLexSym s
 isSymOcc (OccName TvName s)    = isLexSym s
+-- Pretty inefficient!
 
 parenSymOcc :: OccName -> SDoc -> SDoc
 
 parenSymOcc :: OccName -> SDoc -> SDoc
--- Wrap parens around an operator
+-- ^ Wrap parens around an operator
 parenSymOcc occ doc | isSymOcc occ = parens doc
                    | otherwise    = doc
 \end{code}
 
 
 \begin{code}
 parenSymOcc occ doc | isSymOcc occ = parens doc
                    | otherwise    = doc
 \end{code}
 
 
 \begin{code}
-reportIfUnused :: OccName -> Bool
-  -- Haskell 98 encourages compilers to suppress warnings about
-  -- unused names in a pattern if they start with "_".
-reportIfUnused occ = case occNameString occ of
-                       ('_' : _) -> False
-                       _other    -> True
+startsWithUnderscore :: OccName -> Bool
+-- ^ Haskell 98 encourages compilers to suppress warnings about unsed
+-- names in a pattern if they start with @_@: this implements that test
+startsWithUnderscore occ = case occNameString occ of
+                            ('_' : _) -> True
+                            _other    -> False
 \end{code}
 
 
 \end{code}
 
 
@@ -409,26 +480,30 @@ reportIfUnused occ = case occNameString occ of
 
 Here's our convention for splitting up the interface file name space:
 
 
 Here's our convention for splitting up the interface file name space:
 
-       d...            dictionary identifiers
-                       (local variables, so no name-clash worries)
+   d...                dictionary identifiers
+               (local variables, so no name-clash worries)
+
+All of these other OccNames contain a mixture of alphabetic
+and symbolic characters, and hence cannot possibly clash with
+a user-written type or function name
 
 
-       $f...           dict-fun identifiers (from inst decls)
-       $dm...          default methods
-       $p...           superclass selectors
-       $w...           workers
-       :T...           compiler-generated tycons for dictionaries
-       :D...           ...ditto data cons
-        :Co...          ...ditto coercions
-       $sf..           specialised version of f
+   $f...       Dict-fun identifiers (from inst decls)
+   $dmop       Default method for 'op'
+   $pnC                n'th superclass selector for class C
+   $wf         Worker for functtoin 'f'
+   $sf..       Specialised version of f
+   T:C         Tycon for dictionary for class C
+   D:C         Data constructor for dictionary for class C
+   NTCo:T       Coercion connecting newtype T with its representation type
+   TFCo:R       Coercion connecting a data family to its respresentation type R
 
 
-       in encoded form these appear as Zdfxxx etc
+In encoded form these appear as Zdfxxx etc
 
        :...            keywords (export:, letrec: etc.)
 --- I THINK THIS IS WRONG!
 
 This knowledge is encoded in the following functions.
 
 
        :...            keywords (export:, letrec: etc.)
 --- I THINK THIS IS WRONG!
 
 This knowledge is encoded in the following functions.
 
-
 @mk_deriv@ generates an @OccName@ from the prefix and a string.
 NB: The string must already be encoded!
 
 @mk_deriv@ generates an @OccName@ from the prefix and a string.
 NB: The string must already be encoded!
 
@@ -439,6 +514,13 @@ mk_deriv :: NameSpace
         -> OccName
 
 mk_deriv occ_sp sys_prefix str = mkOccName occ_sp (sys_prefix ++ str)
         -> OccName
 
 mk_deriv occ_sp sys_prefix str = mkOccName occ_sp (sys_prefix ++ str)
+
+isDerivedOccName :: OccName -> Bool
+isDerivedOccName occ = 
+   case occNameString occ of
+     '$':c:_ | isAlphaNum c -> True
+     ':':c:_ | isAlphaNum c -> True
+     _other                 -> False
 \end{code}
 
 \begin{code}
 \end{code}
 
 \begin{code}
@@ -446,26 +528,33 @@ mkDataConWrapperOcc, mkWorkerOcc, mkDefaultMethodOcc, mkDerivedTyConOcc,
        mkClassTyConOcc, mkClassDataConOcc, mkDictOcc, mkIPOcc, 
        mkSpecOcc, mkForeignExportOcc, mkGenOcc1, mkGenOcc2,
        mkDataTOcc, mkDataCOcc, mkDataConWorkerOcc, mkNewTyCoOcc,
        mkClassTyConOcc, mkClassDataConOcc, mkDictOcc, mkIPOcc, 
        mkSpecOcc, mkForeignExportOcc, mkGenOcc1, mkGenOcc2,
        mkDataTOcc, mkDataCOcc, mkDataConWorkerOcc, mkNewTyCoOcc,
-       mkInstTyCoOcc, mkEqPredCoOcc,
+       mkInstTyCoOcc, mkEqPredCoOcc, mkClassOpAuxOcc,
+        mkCon2TagOcc, mkTag2ConOcc, mkMaxTagOcc,
        mkVectOcc, mkVectTyConOcc, mkVectDataConOcc, mkVectIsoOcc,
        mkVectOcc, mkVectTyConOcc, mkVectDataConOcc, mkVectIsoOcc,
-       mkPArrayTyConOcc, mkPArrayDataConOcc, mkPReprTyConOcc, mkPADFunOcc
+       mkPDataTyConOcc, mkPDataDataConOcc, mkPReprTyConOcc, mkPADFunOcc
    :: OccName -> OccName
 
 -- These derived variables have a prefix that no Haskell value could have
 mkDataConWrapperOcc = mk_simple_deriv varName  "$W"
 mkWorkerOcc         = mk_simple_deriv varName  "$w"
 mkDefaultMethodOcc  = mk_simple_deriv varName  "$dm"
    :: OccName -> OccName
 
 -- These derived variables have a prefix that no Haskell value could have
 mkDataConWrapperOcc = mk_simple_deriv varName  "$W"
 mkWorkerOcc         = mk_simple_deriv varName  "$w"
 mkDefaultMethodOcc  = mk_simple_deriv varName  "$dm"
+mkClassOpAuxOcc     = mk_simple_deriv varName  "$c"
 mkDerivedTyConOcc   = mk_simple_deriv tcName   ":"     -- The : prefix makes sure it classifies
 mkDerivedTyConOcc   = mk_simple_deriv tcName   ":"     -- The : prefix makes sure it classifies
-mkClassTyConOcc     = mk_simple_deriv tcName   ":T"    -- as a tycon/datacon
-mkClassDataConOcc   = mk_simple_deriv dataName ":D"    -- We go straight to the "real" data con
+mkClassTyConOcc     = mk_simple_deriv tcName   "T:"    -- as a tycon/datacon
+mkClassDataConOcc   = mk_simple_deriv dataName "D:"    -- We go straight to the "real" data con
                                                        -- for datacons from classes
 mkDictOcc          = mk_simple_deriv varName  "$d"
 mkIPOcc                    = mk_simple_deriv varName  "$i"
 mkSpecOcc          = mk_simple_deriv varName  "$s"
 mkForeignExportOcc  = mk_simple_deriv varName  "$f"
                                                        -- for datacons from classes
 mkDictOcc          = mk_simple_deriv varName  "$d"
 mkIPOcc                    = mk_simple_deriv varName  "$i"
 mkSpecOcc          = mk_simple_deriv varName  "$s"
 mkForeignExportOcc  = mk_simple_deriv varName  "$f"
-mkNewTyCoOcc        = mk_simple_deriv tcName  ":Co"
-mkInstTyCoOcc       = mk_simple_deriv tcName  ":CoF"     -- derived from rep ty
-mkEqPredCoOcc      = mk_simple_deriv tcName  "$co"
+mkNewTyCoOcc        = mk_simple_deriv tcName   "NTCo:" -- Coercion for newtypes
+mkInstTyCoOcc       = mk_simple_deriv tcName   "TFCo:"   -- Coercion for type functions
+mkEqPredCoOcc      = mk_simple_deriv tcName   "$co"
+
+-- used in derived instances
+mkCon2TagOcc        = mk_simple_deriv varName  "$con2tag_"
+mkTag2ConOcc        = mk_simple_deriv varName  "$tag2con_"
+mkMaxTagOcc         = mk_simple_deriv varName  "$maxtag_"
 
 -- Generic derivable classes
 mkGenOcc1           = mk_simple_deriv varName  "$gfrom"
 
 -- Generic derivable classes
 mkGenOcc1           = mk_simple_deriv varName  "$gfrom"
@@ -482,8 +571,8 @@ mkVectOcc          = mk_simple_deriv varName  "$v_"
 mkVectTyConOcc     = mk_simple_deriv tcName   ":V_"
 mkVectDataConOcc   = mk_simple_deriv dataName ":VD_"
 mkVectIsoOcc       = mk_simple_deriv varName  "$VI_"
 mkVectTyConOcc     = mk_simple_deriv tcName   ":V_"
 mkVectDataConOcc   = mk_simple_deriv dataName ":VD_"
 mkVectIsoOcc       = mk_simple_deriv varName  "$VI_"
-mkPArrayTyConOcc   = mk_simple_deriv tcName   ":VP_"
-mkPArrayDataConOcc = mk_simple_deriv dataName ":VPD_"
+mkPDataTyConOcc    = mk_simple_deriv tcName   ":VP_"
+mkPDataDataConOcc  = mk_simple_deriv dataName ":VPD_"
 mkPReprTyConOcc    = mk_simple_deriv tcName   ":VR_"
 mkPADFunOcc        = mk_simple_deriv varName  "$PA_"
 
 mkPReprTyConOcc    = mk_simple_deriv tcName   ":VR_"
 mkPADFunOcc        = mk_simple_deriv varName  "$PA_"
 
@@ -497,50 +586,59 @@ mkDataConWorkerOcc datacon_occ = setOccNameSpace varName datacon_occ
 \end{code}
 
 \begin{code}
 \end{code}
 
 \begin{code}
-mkSuperDictSelOcc :: Int       -- Index of superclass, eg 3
-                 -> OccName    -- Class, eg "Ord"
-                 -> OccName    -- eg "$p3Ord"
+mkSuperDictSelOcc :: Int       -- ^ Index of superclass, e.g. 3
+                 -> OccName    -- ^ Class, e.g. @Ord@
+                 -> OccName    -- ^ Derived 'Occname', e.g. @$p3Ord@
 mkSuperDictSelOcc index cls_occ
   = mk_deriv varName "$p" (show index ++ occNameString cls_occ)
 
 mkSuperDictSelOcc index cls_occ
   = mk_deriv varName "$p" (show index ++ occNameString cls_occ)
 
-mkLocalOcc :: Unique           -- Unique
-          -> OccName           -- Local name (e.g. "sat")
-          -> OccName           -- Nice unique version ("$L23sat")
+mkLocalOcc :: Unique           -- ^ Unique to combine with the 'OccName'
+          -> OccName           -- ^ Local name, e.g. @sat@
+          -> OccName           -- ^ Nice unique version, e.g. @$L23sat@
 mkLocalOcc uniq occ
    = mk_deriv varName ("$L" ++ show uniq) (occNameString occ)
        -- The Unique might print with characters 
        -- that need encoding (e.g. 'z'!)
 \end{code}
 
 mkLocalOcc uniq occ
    = mk_deriv varName ("$L" ++ show uniq) (occNameString occ)
        -- The Unique might print with characters 
        -- that need encoding (e.g. 'z'!)
 \end{code}
 
-Derive a name for the representation type constructor of a data/newtype
-instance.
-
 \begin{code}
 \begin{code}
-mkInstTyTcOcc :: Int                   -- Index
-             -> OccName                -- Family name (e.g. "Map")
-             -> OccName                -- Nice unique version (":R23Map")
-mkInstTyTcOcc index occ
-   = mk_deriv tcName (":R" ++ show index) (occNameString occ)
+-- | Derive a name for the representation type constructor of a
+-- @data@\/@newtype@ instance.
+mkInstTyTcOcc :: String                -- ^ Family name, e.g. @Map@
+              -> OccSet                 -- ^ avoid these Occs
+             -> OccName                -- ^ @R:Map@
+mkInstTyTcOcc str set =
+  chooseUniqueOcc tcName ('R' : ':' : str) set
 \end{code}
 
 \begin{code}
 \end{code}
 
 \begin{code}
-mkDFunOcc :: String            -- Typically the class and type glommed together e.g. "OrdMaybe"
+mkDFunOcc :: String            -- ^ Typically the class and type glommed together e.g. @OrdMaybe@.
                                -- Only used in debug mode, for extra clarity
                                -- Only used in debug mode, for extra clarity
-         -> Bool               -- True <=> hs-boot instance dfun
-         -> Int                -- Unique index
-         -> OccName            -- "$f3OrdMaybe"
+         -> Bool               -- ^ Is this a hs-boot instance DFun?
+          -> OccSet             -- ^ avoid these Occs
+         -> OccName            -- ^ E.g. @$f3OrdMaybe@
 
 -- In hs-boot files we make dict funs like $fx7ClsTy, which get bound to the real
 -- thing when we compile the mother module. Reason: we don't know exactly
 -- what the  mother module will call it.
 
 
 -- In hs-boot files we make dict funs like $fx7ClsTy, which get bound to the real
 -- thing when we compile the mother module. Reason: we don't know exactly
 -- what the  mother module will call it.
 
-mkDFunOcc info_str is_boot index 
-  = mk_deriv VarName prefix string
+mkDFunOcc info_str is_boot set
+  = chooseUniqueOcc VarName (prefix ++ info_str) set
   where
     prefix | is_boot   = "$fx"
           | otherwise = "$f"
   where
     prefix | is_boot   = "$fx"
           | otherwise = "$f"
-    string | opt_PprStyle_Debug = show index ++ info_str
-          | otherwise          = show index
+\end{code}
+
+Sometimes we need to pick an OccName that has not already been used,
+given a set of in-use OccNames.
+
+\begin{code}
+chooseUniqueOcc :: NameSpace -> String -> OccSet -> OccName
+chooseUniqueOcc ns str set = loop (mkOccName ns str) (0::Int)
+  where
+  loop occ n
+   | occ `elemOccSet` set = loop (mkOccName ns (str ++ show n)) (n+1)
+   | otherwise            = occ
 \end{code}
 
 We used to add a '$m' to indicate a method, but that gives rise to bad
 \end{code}
 
 We used to add a '$m' to indicate a method, but that gives rise to bad