    {-
    (c) The University of Glasgow 2006
    (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
    -}

    {-# LANGUAGE DeriveDataTypeable #-}
    {-# LANGUAGE BangPatterns #-}
    {-# LANGUAGE OverloadedStrings #-}
    {-# LANGUAGE LambdaCase #-}

    -- |
    -- #name_types#
    -- GHC uses several kinds of name internally:
    --
    -- * 'GHC.Types.Name.Occurrence.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
    --
    -- * 'GHC.Types.Name.Reader.RdrName': see "GHC.Types.Name.Reader#name_types"
    --
    -- * 'GHC.Types.Name.Name': see "GHC.Types.Name#name_types"
    --
    -- * 'GHC.Types.Id.Id': see "GHC.Types.Id#name_types"
    --
    -- * 'GHC.Types.Var.Var': see "GHC.Types.Var#name_types"

    module GHC.Types.Name.Occurrence (
            -- * The 'NameSpace' type
            NameSpace, -- Abstract

            nameSpacesRelated,

            -- ** Construction
            -- $real_vs_source_data_constructors
            tcName, clsName, tcClsName, dataName, varName,
            tvName, srcDataName,

            -- ** Pretty Printing
            pprNameSpace, pprNonVarNameSpace, pprNameSpaceBrief,

            -- * The 'OccName' type
            OccName,        -- Abstract, instance of Outputable
            pprOccName,

            -- ** Construction
            mkOccName, mkOccNameFS,
            mkVarOcc, mkVarOccFS,
            mkDataOcc, mkDataOccFS,
            mkTyVarOcc, mkTyVarOccFS,
            mkTcOcc, mkTcOccFS,
            mkClsOcc, mkClsOccFS,
            mkDFunOcc,
            setOccNameSpace,
            demoteOccName,
            promoteOccName,
            HasOccName(..),

            -- ** Derived 'OccName's
            isDerivedOccName,
            mkDataConWrapperOcc, mkWorkerOcc,
            mkMatcherOcc, mkBuilderOcc,
            mkDefaultMethodOcc, isDefaultMethodOcc, isTypeableBindOcc,
            mkNewTyCoOcc, mkClassOpAuxOcc,
            mkCon2TagOcc, mkTag2ConOcc, mkMaxTagOcc,
            mkClassDataConOcc, mkDictOcc, mkIPOcc,
            mkSpecOcc, mkForeignExportOcc, mkRepEqOcc,
            mkGenR, mkGen1R,
            mkDataTOcc, mkDataCOcc, mkDataConWorkerOcc,
            mkSuperDictSelOcc, mkSuperDictAuxOcc,
            mkLocalOcc, mkMethodOcc, mkInstTyTcOcc,
            mkInstTyCoOcc, mkEqPredCoOcc,
            mkRecFldSelOcc,
            mkTyConRepOcc,

            -- ** Deconstruction
            occNameFS, occNameString, occNameSpace,

            isVarOcc, isTvOcc, isTcOcc, isDataOcc, isDataSymOcc, isSymOcc, isValOcc,
            parenSymOcc, startsWithUnderscore,

            isTcClsNameSpace, isTvNameSpace, isDataConNameSpace, isVarNameSpace, isValNameSpace,

            -- * The 'OccEnv' type
            OccEnv, emptyOccEnv, unitOccEnv, extendOccEnv, mapOccEnv,
            lookupOccEnv, mkOccEnv, mkOccEnv_C, extendOccEnvList, elemOccEnv,
            occEnvElts, foldOccEnv, plusOccEnv, plusOccEnv_C, extendOccEnv_C,
            extendOccEnv_Acc, filterOccEnv, delListFromOccEnv, delFromOccEnv,
            alterOccEnv, pprOccEnv,

            -- * The 'OccSet' type
            OccSet, emptyOccSet, unitOccSet, mkOccSet, extendOccSet,
            extendOccSetList,
            unionOccSets, unionManyOccSets, minusOccSet, elemOccSet,
            isEmptyOccSet, intersectOccSet,
            filterOccSet,

            -- * Tidying up
            TidyOccEnv, emptyTidyOccEnv, initTidyOccEnv,
            tidyOccName, avoidClashesOccEnv, delTidyOccEnvList,

            -- FsEnv
            FastStringEnv, emptyFsEnv, lookupFsEnv, extendFsEnv, mkFsEnv
        ) where

    import GHC.Prelude

    import GHC.Utils.Misc
    import GHC.Types.Unique
    import GHC.Builtin.Uniques
    import GHC.Types.Unique.FM
    import GHC.Types.Unique.Set
    import GHC.Data.FastString
    import GHC.Data.FastString.Env
    import GHC.Utils.Outputable
    import GHC.Utils.Lexeme
    import GHC.Utils.Binary
    import Control.DeepSeq
    import Data.Char
    import Data.Data

    {-
    ************************************************************************
    *                                                                      *
    \subsection{Name space}
    *                                                                      *
    ************************************************************************
    -}

    data NameSpace = VarName        -- Variables, including "real" data constructors
                   | DataName       -- "Source" data constructors
                   | TvName         -- Type variables
                   | TcClsName      -- Type constructors and classes; Haskell has them
                                    -- in the same name space for now.
                   deriving( NameSpace -> NameSpace -> Bool
    (NameSpace -> NameSpace -> Bool)
    -> (NameSpace -> NameSpace -> Bool) -> Eq NameSpace
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    /= :: NameSpace -> NameSpace -> Bool
    $c/= :: NameSpace -> NameSpace -> Bool
    == :: NameSpace -> NameSpace -> Bool
    $c== :: NameSpace -> NameSpace -> Bool
    Eq, Eq NameSpace
    Eq NameSpace
    -> (NameSpace -> NameSpace -> Ordering)
    -> (NameSpace -> NameSpace -> Bool)
    -> (NameSpace -> NameSpace -> Bool)
    -> (NameSpace -> NameSpace -> Bool)
    -> (NameSpace -> NameSpace -> Bool)
    -> (NameSpace -> NameSpace -> NameSpace)
    -> (NameSpace -> NameSpace -> NameSpace)
    -> Ord NameSpace
    NameSpace -> NameSpace -> Bool
    NameSpace -> NameSpace -> Ordering
    NameSpace -> NameSpace -> NameSpace
    forall a.
    Eq a
    -> (a -> a -> Ordering)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> Ord a
    min :: NameSpace -> NameSpace -> NameSpace
    $cmin :: NameSpace -> NameSpace -> NameSpace
    max :: NameSpace -> NameSpace -> NameSpace
    $cmax :: NameSpace -> NameSpace -> NameSpace
    >= :: NameSpace -> NameSpace -> Bool
    $c>= :: NameSpace -> NameSpace -> Bool
    > :: NameSpace -> NameSpace -> Bool
    $c> :: NameSpace -> NameSpace -> Bool
    <= :: NameSpace -> NameSpace -> Bool
    $c<= :: NameSpace -> NameSpace -> Bool
    < :: NameSpace -> NameSpace -> Bool
    $c< :: NameSpace -> NameSpace -> Bool
    compare :: NameSpace -> NameSpace -> Ordering
    $ccompare :: NameSpace -> NameSpace -> Ordering
    Ord )

    -- Note [Data Constructors]
    -- see also: Note [Data Constructor Naming] in GHC.Core.DataCon
    --
    -- $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@
    --
    -- GHC chooses a representation based on the strictness etc.

    tcName, clsName, tcClsName :: NameSpace
    dataName, srcDataName      :: NameSpace
    tvName, varName            :: NameSpace

    -- Though type constructors and classes are in the same name space now,
    -- the NameSpace type is abstract, so we can easily separate them later
    tcName :: NameSpace
    tcName    = NameSpace
    TcClsName           -- Type constructors
    clsName :: NameSpace
    clsName   = NameSpace
    TcClsName           -- Classes
    tcClsName :: NameSpace
    tcClsName = NameSpace
    TcClsName           -- Not sure which!

    dataName :: NameSpace
    dataName    = NameSpace
    DataName
    srcDataName :: NameSpace
    srcDataName = NameSpace
    DataName  -- Haskell-source data constructors should be
                            -- in the Data name space

    tvName :: NameSpace
    tvName      = NameSpace
    TvName
    varName :: NameSpace
    varName     = NameSpace
    VarName

    isDataConNameSpace :: NameSpace -> Bool
    isDataConNameSpace :: NameSpace -> Bool
    isDataConNameSpace NameSpace
    DataName = Bool
    True
    isDataConNameSpace NameSpace
    _        = Bool
    False

    isTcClsNameSpace :: NameSpace -> Bool
    isTcClsNameSpace :: NameSpace -> Bool
    isTcClsNameSpace NameSpace
    TcClsName = Bool
    True
    isTcClsNameSpace NameSpace
    _         = Bool
    False

    isTvNameSpace :: NameSpace -> Bool
    isTvNameSpace :: NameSpace -> Bool
    isTvNameSpace NameSpace
    TvName = Bool
    True
    isTvNameSpace NameSpace
    _      = Bool
    False

    isVarNameSpace :: NameSpace -> Bool     -- Variables or type variables, but not constructors
    isVarNameSpace :: NameSpace -> Bool
    isVarNameSpace NameSpace
    TvName  = Bool
    True
    isVarNameSpace NameSpace
    VarName = Bool
    True
    isVarNameSpace NameSpace
    _       = Bool
    False

    isValNameSpace :: NameSpace -> Bool
    isValNameSpace :: NameSpace -> Bool
    isValNameSpace NameSpace
    DataName = Bool
    True
    isValNameSpace NameSpace
    VarName  = Bool
    True
    isValNameSpace NameSpace
    _        = Bool
    False

    pprNameSpace :: NameSpace -> SDoc
    pprNameSpace :: NameSpace -> SDoc
    pprNameSpace NameSpace
    DataName  = [Char] -> SDoc
    text [Char]
    "data constructor"
    pprNameSpace NameSpace
    VarName   = [Char] -> SDoc
    text [Char]
    "variable"
    pprNameSpace NameSpace
    TvName    = [Char] -> SDoc
    text [Char]
    "type variable"
    pprNameSpace NameSpace
    TcClsName = [Char] -> SDoc
    text [Char]
    "type constructor or class"

    pprNonVarNameSpace :: NameSpace -> SDoc
    pprNonVarNameSpace :: NameSpace -> SDoc
    pprNonVarNameSpace NameSpace
    VarName = SDoc
    empty
    pprNonVarNameSpace NameSpace
    ns = NameSpace -> SDoc
    pprNameSpace NameSpace
    ns

    pprNameSpaceBrief :: NameSpace -> SDoc
    pprNameSpaceBrief :: NameSpace -> SDoc
    pprNameSpaceBrief NameSpace
    DataName  = Char -> SDoc
    char Char
    'd'
    pprNameSpaceBrief NameSpace
    VarName   = Char -> SDoc
    char Char
    'v'
    pprNameSpaceBrief NameSpace
    TvName    = [Char] -> SDoc
    text [Char]
    "tv"
    pprNameSpaceBrief NameSpace
    TcClsName = [Char] -> SDoc
    text [Char]
    "tc"

    -- demoteNameSpace lowers the NameSpace if possible.  We can not know
    -- in advance, since a TvName can appear in an HsTyVar.
    -- See Note [Demotion] in GHC.Rename.Env.
    demoteNameSpace :: NameSpace -> Maybe NameSpace
    demoteNameSpace :: NameSpace -> Maybe NameSpace
    demoteNameSpace NameSpace
    VarName = Maybe NameSpace
    forall a. Maybe a
    Nothing
    demoteNameSpace NameSpace
    DataName = Maybe NameSpace
    forall a. Maybe a
    Nothing
    demoteNameSpace NameSpace
    TvName = Maybe NameSpace
    forall a. Maybe a
    Nothing
    demoteNameSpace NameSpace
    TcClsName = NameSpace -> Maybe NameSpace
    forall a. a -> Maybe a
    Just NameSpace
    DataName

    -- promoteNameSpace promotes the NameSpace as follows.
    -- See Note [Promotion] in GHC.Rename.Env.
    promoteNameSpace :: NameSpace -> Maybe NameSpace
    promoteNameSpace :: NameSpace -> Maybe NameSpace
    promoteNameSpace NameSpace
    DataName = NameSpace -> Maybe NameSpace
    forall a. a -> Maybe a
    Just NameSpace
    TcClsName
    promoteNameSpace NameSpace
    VarName = NameSpace -> Maybe NameSpace
    forall a. a -> Maybe a
    Just NameSpace
    TvName
    promoteNameSpace NameSpace
    TcClsName = Maybe NameSpace
    forall a. Maybe a
    Nothing
    promoteNameSpace NameSpace
    TvName = Maybe NameSpace
    forall a. Maybe a
    Nothing

    {-
    ************************************************************************
    *                                                                      *
    \subsection[Name-pieces-datatypes]{The @OccName@ datatypes}
    *                                                                      *
    ************************************************************************
    -}

    -- | Occurrence Name
    --
    -- In this context that means:
    -- "classified (i.e. as a type name, value name, etc) but not qualified
    -- and not yet resolved"
    data OccName = OccName
        { OccName -> NameSpace
    occNameSpace  :: !NameSpace
        , OccName -> FastString
    occNameFS     :: !FastString
        }

    instance Eq OccName where
        (OccName NameSpace
    sp1 FastString
    s1) == :: OccName -> OccName -> Bool
    == (OccName NameSpace
    sp2 FastString
    s2) = FastString
    s1 FastString -> FastString -> Bool
    forall a. Eq a => a -> a -> Bool
    == FastString
    s2 Bool -> Bool -> Bool
    && NameSpace
    sp1 NameSpace -> NameSpace -> Bool
    forall a. Eq a => a -> a -> Bool
    == NameSpace
    sp2

    instance Ord OccName where
            -- Compares lexicographically, *not* by Unique of the string
        compare :: OccName -> OccName -> Ordering
    compare (OccName NameSpace
    sp1 FastString
    s1) (OccName NameSpace
    sp2 FastString
    s2)
            = (FastString
    s1  FastString -> FastString -> Ordering
    `lexicalCompareFS` FastString
    s2) Ordering -> Ordering -> Ordering
    `thenCmp` (NameSpace
    sp1 NameSpace -> NameSpace -> Ordering
    forall a. Ord a => a -> a -> Ordering
    `compare` NameSpace
    sp2)

    instance Data OccName where
      -- don't traverse?
      toConstr :: OccName -> Constr
    toConstr OccName
    _   = [Char] -> Constr
    abstractConstr [Char]
    "OccName"
      gunfold :: forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c OccName
    gunfold forall b r. Data b => c (b -> r) -> c r
    _ forall r. r -> c r
    _  = [Char] -> Constr -> c OccName
    forall a. HasCallStack => [Char] -> a
    error [Char]
    "gunfold"
      dataTypeOf :: OccName -> DataType
    dataTypeOf OccName
    _ = [Char] -> DataType
    mkNoRepType [Char]
    "OccName"

    instance HasOccName OccName where
      occName :: OccName -> OccName
    occName = OccName -> OccName
    forall a. a -> a
    id

    instance NFData OccName where
      rnf :: OccName -> ()
    rnf OccName
    x = OccName
    x OccName -> () -> ()
    `seq` ()

    {-
    ************************************************************************
    *                                                                      *
    \subsection{Printing}
    *                                                                      *
    ************************************************************************
    -}

    instance Outputable OccName where
        ppr :: OccName -> SDoc
    ppr = OccName -> SDoc
    pprOccName

    instance OutputableBndr OccName where
        pprBndr :: BindingSite -> OccName -> SDoc
    pprBndr BindingSite
    _ = OccName -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr
        pprInfixOcc :: OccName -> SDoc
    pprInfixOcc OccName
    n = Bool -> SDoc -> SDoc
    pprInfixVar (OccName -> Bool
    isSymOcc OccName
    n) (OccName -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr OccName
    n)
        pprPrefixOcc :: OccName -> SDoc
    pprPrefixOcc OccName
    n = Bool -> SDoc -> SDoc
    pprPrefixVar (OccName -> Bool
    isSymOcc OccName
    n) (OccName -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr OccName
    n)

    pprOccName :: OccName -> SDoc
    pprOccName :: OccName -> SDoc
    pprOccName (OccName NameSpace
    sp FastString
    occ)
      = (PprStyle -> SDoc) -> SDoc
    getPprStyle ((PprStyle -> SDoc) -> SDoc) -> (PprStyle -> SDoc) -> SDoc
    forall a b. (a -> b) -> a -> b
    $ \ PprStyle
    sty ->
        if PprStyle -> Bool
    codeStyle PprStyle
    sty
        then FastZString -> SDoc
    ztext (FastString -> FastZString
    zEncodeFS FastString
    occ)
        else SDoc
    pp_occ SDoc -> SDoc -> SDoc
    <> SDoc -> SDoc
    whenPprDebug (SDoc -> SDoc
    braces (NameSpace -> SDoc
    pprNameSpaceBrief NameSpace
    sp))
      where
        pp_occ :: SDoc
    pp_occ = (SDocContext -> Bool) -> (Bool -> SDoc) -> SDoc
    forall a. (SDocContext -> a) -> (a -> SDoc) -> SDoc
    sdocOption SDocContext -> Bool
    sdocSuppressUniques ((Bool -> SDoc) -> SDoc) -> (Bool -> SDoc) -> SDoc
    forall a b. (a -> b) -> a -> b
    $ \case
                   Bool
    True  -> [Char] -> SDoc
    text ([Char] -> [Char]
    strip_th_unique (FastString -> [Char]
    unpackFS FastString
    occ))
                   Bool
    False -> FastString -> SDoc
    ftext FastString
    occ

            -- See Note [Suppressing uniques in OccNames]
        strip_th_unique :: [Char] -> [Char]
    strip_th_unique (Char
    '[' : Char
    c : [Char]
    _) | Char -> Bool
    isAlphaNum Char
    c = []
        strip_th_unique (Char
    c : [Char]
    cs) = Char
    c Char -> [Char] -> [Char]
    forall a. a -> [a] -> [a]
    : [Char] -> [Char]
    strip_th_unique [Char]
    cs
        strip_th_unique []       = []

    {-
    Note [Suppressing uniques in OccNames]
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    This is a hack to de-wobblify the OccNames that contain uniques from
    Template Haskell that have been turned into a string in the OccName.
    See Note [Unique OccNames from Template Haskell] in "GHC.ThToHs"

    ************************************************************************
    *                                                                      *
    \subsection{Construction}
    *                                                                      *
    ************************************************************************
    -}

    mkOccName :: NameSpace -> String -> OccName
    mkOccName :: NameSpace -> [Char] -> OccName
    mkOccName NameSpace
    occ_sp [Char]
    str = NameSpace -> FastString -> OccName
    OccName NameSpace
    occ_sp ([Char] -> FastString
    mkFastString [Char]
    str)

    mkOccNameFS :: NameSpace -> FastString -> OccName
    mkOccNameFS :: NameSpace -> FastString -> OccName
    mkOccNameFS NameSpace
    occ_sp FastString
    fs = NameSpace -> FastString -> OccName
    OccName NameSpace
    occ_sp FastString
    fs

    mkVarOcc :: String -> OccName
    mkVarOcc :: [Char] -> OccName
    mkVarOcc [Char]
    s = NameSpace -> [Char] -> OccName
    mkOccName NameSpace
    varName [Char]
    s

    mkVarOccFS :: FastString -> OccName
    mkVarOccFS :: FastString -> OccName
    mkVarOccFS FastString
    fs = NameSpace -> FastString -> OccName
    mkOccNameFS NameSpace
    varName FastString
    fs

    mkDataOcc :: String -> OccName
    mkDataOcc :: [Char] -> OccName
    mkDataOcc = NameSpace -> [Char] -> OccName
    mkOccName NameSpace
    dataName

    mkDataOccFS :: FastString -> OccName
    mkDataOccFS :: FastString -> OccName
    mkDataOccFS = NameSpace -> FastString -> OccName
    mkOccNameFS NameSpace
    dataName

    mkTyVarOcc :: String -> OccName
    mkTyVarOcc :: [Char] -> OccName
    mkTyVarOcc = NameSpace -> [Char] -> OccName
    mkOccName NameSpace
    tvName

    mkTyVarOccFS :: FastString -> OccName
    mkTyVarOccFS :: FastString -> OccName
    mkTyVarOccFS FastString
    fs = NameSpace -> FastString -> OccName
    mkOccNameFS NameSpace
    tvName FastString
    fs

    mkTcOcc :: String -> OccName
    mkTcOcc :: [Char] -> OccName
    mkTcOcc = NameSpace -> [Char] -> OccName
    mkOccName NameSpace
    tcName

    mkTcOccFS :: FastString -> OccName
    mkTcOccFS :: FastString -> OccName
    mkTcOccFS = NameSpace -> FastString -> OccName
    mkOccNameFS NameSpace
    tcName

    mkClsOcc :: String -> OccName
    mkClsOcc :: [Char] -> OccName
    mkClsOcc = NameSpace -> [Char] -> OccName
    mkOccName NameSpace
    clsName

    mkClsOccFS :: FastString -> OccName
    mkClsOccFS :: FastString -> OccName
    mkClsOccFS = NameSpace -> FastString -> OccName
    mkOccNameFS NameSpace
    clsName

    -- demoteOccName lowers the Namespace of OccName.
    -- See Note [Demotion] in GHC.Rename.Env.
    demoteOccName :: OccName -> Maybe OccName
    demoteOccName :: OccName -> Maybe OccName
    demoteOccName (OccName NameSpace
    space FastString
    name) = do
      NameSpace
    space' <- NameSpace -> Maybe NameSpace
    demoteNameSpace NameSpace
    space
      OccName -> Maybe OccName
    forall (m :: * -> *) a. Monad m => a -> m a
    return (OccName -> Maybe OccName) -> OccName -> Maybe OccName
    forall a b. (a -> b) -> a -> b
    $ NameSpace -> FastString -> OccName
    OccName NameSpace
    space' FastString
    name

    -- promoteOccName promotes the NameSpace of OccName.
    -- See Note [Promotion] in GHC.Rename.Env.
    promoteOccName :: OccName -> Maybe OccName
    promoteOccName :: OccName -> Maybe OccName
    promoteOccName (OccName NameSpace
    space FastString
    name) = do
      NameSpace
    space' <- NameSpace -> Maybe NameSpace
    promoteNameSpace NameSpace
    space
      OccName -> Maybe OccName
    forall (m :: * -> *) a. Monad m => a -> m a
    return (OccName -> Maybe OccName) -> OccName -> Maybe OccName
    forall a b. (a -> b) -> a -> b
    $ NameSpace -> FastString -> OccName
    OccName NameSpace
    space' FastString
    name

    -- Name spaces are related if there is a chance to mean the one when one writes
    -- the other, i.e. variables <-> data constructors and type variables <-> type constructors
    nameSpacesRelated :: NameSpace -> NameSpace -> Bool
    nameSpacesRelated :: NameSpace -> NameSpace -> Bool
    nameSpacesRelated NameSpace
    ns1 NameSpace
    ns2 = NameSpace
    ns1 NameSpace -> NameSpace -> Bool
    forall a. Eq a => a -> a -> Bool
    == NameSpace
    ns2 Bool -> Bool -> Bool
    || NameSpace -> NameSpace
    otherNameSpace NameSpace
    ns1 NameSpace -> NameSpace -> Bool
    forall a. Eq a => a -> a -> Bool
    == NameSpace
    ns2

    otherNameSpace :: NameSpace -> NameSpace
    otherNameSpace :: NameSpace -> NameSpace
    otherNameSpace NameSpace
    VarName = NameSpace
    DataName
    otherNameSpace NameSpace
    DataName = NameSpace
    VarName
    otherNameSpace NameSpace
    TvName = NameSpace
    TcClsName
    otherNameSpace NameSpace
    TcClsName = NameSpace
    TvName

    {- | Other names in the compiler add additional information to an OccName.
    This class provides a consistent way to access the underlying OccName. -}
    class HasOccName name where
      occName :: name -> OccName

    {-
    ************************************************************************
    *                                                                      *
                    Environments
    *                                                                      *
    ************************************************************************

    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
    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 representing the name space.  This in turn makes it
    easy to build an OccEnv.
    -}

    instance Uniquable OccName where
          -- See Note [The Unique of an OccName]
      getUnique :: OccName -> Unique
    getUnique (OccName NameSpace
    VarName   FastString
    fs) = FastString -> Unique
    mkVarOccUnique  FastString
    fs
      getUnique (OccName NameSpace
    DataName  FastString
    fs) = FastString -> Unique
    mkDataOccUnique FastString
    fs
      getUnique (OccName NameSpace
    TvName    FastString
    fs) = FastString -> Unique
    mkTvOccUnique   FastString
    fs
      getUnique (OccName NameSpace
    TcClsName FastString
    fs) = FastString -> Unique
    mkTcOccUnique   FastString
    fs

    newtype OccEnv a = A (UniqFM OccName a)
      deriving Typeable (OccEnv a)
    Typeable (OccEnv a)
    -> (forall (c :: * -> *).
        (forall d b. Data d => c (d -> b) -> d -> c b)
        -> (forall g. g -> c g) -> OccEnv a -> c (OccEnv a))
    -> (forall (c :: * -> *).
        (forall b r. Data b => c (b -> r) -> c r)
        -> (forall r. r -> c r) -> Constr -> c (OccEnv a))
    -> (OccEnv a -> Constr)
    -> (OccEnv a -> DataType)
    -> (forall (t :: * -> *) (c :: * -> *).
        Typeable t =>
        (forall d. Data d => c (t d)) -> Maybe (c (OccEnv a)))
    -> (forall (t :: * -> * -> *) (c :: * -> *).
        Typeable t =>
        (forall d e. (Data d, Data e) => c (t d e))
        -> Maybe (c (OccEnv a)))
    -> ((forall b. Data b => b -> b) -> OccEnv a -> OccEnv a)
    -> (forall r r'.
        (r -> r' -> r)
        -> r -> (forall d. Data d => d -> r') -> OccEnv a -> r)
    -> (forall r r'.
        (r' -> r -> r)
        -> r -> (forall d. Data d => d -> r') -> OccEnv a -> r)
    -> (forall u. (forall d. Data d => d -> u) -> OccEnv a -> [u])
    -> (forall u. Int -> (forall d. Data d => d -> u) -> OccEnv a -> u)
    -> (forall (m :: * -> *).
        Monad m =>
        (forall d. Data d => d -> m d) -> OccEnv a -> m (OccEnv a))
    -> (forall (m :: * -> *).
        MonadPlus m =>
        (forall d. Data d => d -> m d) -> OccEnv a -> m (OccEnv a))
    -> (forall (m :: * -> *).
        MonadPlus m =>
        (forall d. Data d => d -> m d) -> OccEnv a -> m (OccEnv a))
    -> Data (OccEnv a)
    OccEnv a -> DataType
    OccEnv a -> Constr
    (forall b. Data b => b -> b) -> OccEnv a -> OccEnv a
    forall {a}. Data a => Typeable (OccEnv a)
    forall a. Data a => OccEnv a -> DataType
    forall a. Data a => OccEnv a -> Constr
    forall a.
    Data a =>
    (forall b. Data b => b -> b) -> OccEnv a -> OccEnv a
    forall a u.
    Data a =>
    Int -> (forall d. Data d => d -> u) -> OccEnv a -> u
    forall a u.
    Data a =>
    (forall d. Data d => d -> u) -> OccEnv a -> [u]
    forall a r r'.
    Data a =>
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> OccEnv a -> r
    forall a r r'.
    Data a =>
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> OccEnv a -> r
    forall a (m :: * -> *).
    (Data a, Monad m) =>
    (forall d. Data d => d -> m d) -> OccEnv a -> m (OccEnv a)
    forall a (m :: * -> *).
    (Data a, MonadPlus m) =>
    (forall d. Data d => d -> m d) -> OccEnv a -> m (OccEnv a)
    forall a (c :: * -> *).
    Data a =>
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c (OccEnv a)
    forall a (c :: * -> *).
    Data a =>
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> OccEnv a -> c (OccEnv a)
    forall a (t :: * -> *) (c :: * -> *).
    (Data a, Typeable t) =>
    (forall d. Data d => c (t d)) -> Maybe (c (OccEnv a))
    forall a (t :: * -> * -> *) (c :: * -> *).
    (Data a, Typeable t) =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (OccEnv a))
    forall a.
    Typeable a
    -> (forall (c :: * -> *).
        (forall d b. Data d => c (d -> b) -> d -> c b)
        -> (forall g. g -> c g) -> a -> c a)
    -> (forall (c :: * -> *).
        (forall b r. Data b => c (b -> r) -> c r)
        -> (forall r. r -> c r) -> Constr -> c a)
    -> (a -> Constr)
    -> (a -> DataType)
    -> (forall (t :: * -> *) (c :: * -> *).
        Typeable t =>
        (forall d. Data d => c (t d)) -> Maybe (c a))
    -> (forall (t :: * -> * -> *) (c :: * -> *).
        Typeable t =>
        (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
    -> ((forall b. Data b => b -> b) -> a -> a)
    -> (forall r r'.
        (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
    -> (forall r r'.
        (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
    -> (forall u. (forall d. Data d => d -> u) -> a -> [u])
    -> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
    -> (forall (m :: * -> *).
        Monad m =>
        (forall d. Data d => d -> m d) -> a -> m a)
    -> (forall (m :: * -> *).
        MonadPlus m =>
        (forall d. Data d => d -> m d) -> a -> m a)
    -> (forall (m :: * -> *).
        MonadPlus m =>
        (forall d. Data d => d -> m d) -> a -> m a)
    -> Data a
    forall u. Int -> (forall d. Data d => d -> u) -> OccEnv a -> u
    forall u. (forall d. Data d => d -> u) -> OccEnv a -> [u]
    forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> OccEnv a -> r
    forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> OccEnv a -> r
    forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> OccEnv a -> m (OccEnv a)
    forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> OccEnv a -> m (OccEnv a)
    forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c (OccEnv a)
    forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> OccEnv a -> c (OccEnv a)
    forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c (OccEnv a))
    forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (OccEnv a))
    gmapMo :: forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> OccEnv a -> m (OccEnv a)
    $cgmapMo :: forall a (m :: * -> *).
    (Data a, MonadPlus m) =>
    (forall d. Data d => d -> m d) -> OccEnv a -> m (OccEnv a)
    gmapMp :: forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> OccEnv a -> m (OccEnv a)
    $cgmapMp :: forall a (m :: * -> *).
    (Data a, MonadPlus m) =>
    (forall d. Data d => d -> m d) -> OccEnv a -> m (OccEnv a)
    gmapM :: forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> OccEnv a -> m (OccEnv a)
    $cgmapM :: forall a (m :: * -> *).
    (Data a, Monad m) =>
    (forall d. Data d => d -> m d) -> OccEnv a -> m (OccEnv a)
    gmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> OccEnv a -> u
    $cgmapQi :: forall a u.
    Data a =>
    Int -> (forall d. Data d => d -> u) -> OccEnv a -> u
    gmapQ :: forall u. (forall d. Data d => d -> u) -> OccEnv a -> [u]
    $cgmapQ :: forall a u.
    Data a =>
    (forall d. Data d => d -> u) -> OccEnv a -> [u]
    gmapQr :: forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> OccEnv a -> r
    $cgmapQr :: forall a r r'.
    Data a =>
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> OccEnv a -> r
    gmapQl :: forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> OccEnv a -> r
    $cgmapQl :: forall a r r'.
    Data a =>
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> OccEnv a -> r
    gmapT :: (forall b. Data b => b -> b) -> OccEnv a -> OccEnv a
    $cgmapT :: forall a.
    Data a =>
    (forall b. Data b => b -> b) -> OccEnv a -> OccEnv a
    dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (OccEnv a))
    $cdataCast2 :: forall a (t :: * -> * -> *) (c :: * -> *).
    (Data a, Typeable t) =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (OccEnv a))
    dataCast1 :: forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c (OccEnv a))
    $cdataCast1 :: forall a (t :: * -> *) (c :: * -> *).
    (Data a, Typeable t) =>
    (forall d. Data d => c (t d)) -> Maybe (c (OccEnv a))
    dataTypeOf :: OccEnv a -> DataType
    $cdataTypeOf :: forall a. Data a => OccEnv a -> DataType
    toConstr :: OccEnv a -> Constr
    $ctoConstr :: forall a. Data a => OccEnv a -> Constr
    gunfold :: forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c (OccEnv a)
    $cgunfold :: forall a (c :: * -> *).
    Data a =>
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c (OccEnv a)
    gfoldl :: forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> OccEnv a -> c (OccEnv a)
    $cgfoldl :: forall a (c :: * -> *).
    Data a =>
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> OccEnv a -> c (OccEnv a)
    Data

    emptyOccEnv :: OccEnv a
    unitOccEnv  :: OccName -> a -> OccEnv a
    extendOccEnv :: OccEnv a -> OccName -> a -> OccEnv a
    extendOccEnvList :: OccEnv a -> [(OccName, a)] -> OccEnv a
    lookupOccEnv :: OccEnv a -> OccName -> Maybe a
    mkOccEnv     :: [(OccName,a)] -> OccEnv a
    mkOccEnv_C   :: (a -> a -> a) -> [(OccName,a)] -> OccEnv a
    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
    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
    delFromOccEnv      :: OccEnv a -> OccName -> OccEnv a
    delListFromOccEnv :: OccEnv a -> [OccName] -> OccEnv a
    filterOccEnv       :: (elt -> Bool) -> OccEnv elt -> OccEnv elt
    alterOccEnv        :: (Maybe elt -> Maybe elt) -> OccEnv elt -> OccName -> OccEnv elt

    emptyOccEnv :: forall a. OccEnv a
    emptyOccEnv      = UniqFM OccName a -> OccEnv a
    forall a. UniqFM OccName a -> OccEnv a
    A UniqFM OccName a
    forall key elt. UniqFM key elt
    emptyUFM
    unitOccEnv :: forall a. OccName -> a -> OccEnv a
    unitOccEnv OccName
    x a
    y = UniqFM OccName a -> OccEnv a
    forall a. UniqFM OccName a -> OccEnv a
    A (UniqFM OccName a -> OccEnv a) -> UniqFM OccName a -> OccEnv a
    forall a b. (a -> b) -> a -> b
    $ OccName -> a -> UniqFM OccName a
    forall key elt. Uniquable key => key -> elt -> UniqFM key elt
    unitUFM OccName
    x a
    y
    extendOccEnv :: forall a. OccEnv a -> OccName -> a -> OccEnv a
    extendOccEnv (A UniqFM OccName a
    x) OccName
    y a
    z = UniqFM OccName a -> OccEnv a
    forall a. UniqFM OccName a -> OccEnv a
    A (UniqFM OccName a -> OccEnv a) -> UniqFM OccName a -> OccEnv a
    forall a b. (a -> b) -> a -> b
    $ UniqFM OccName a -> OccName -> a -> UniqFM OccName a
    forall key elt.
    Uniquable key =>
    UniqFM key elt -> key -> elt -> UniqFM key elt
    addToUFM UniqFM OccName a
    x OccName
    y a
    z
    extendOccEnvList :: forall a. OccEnv a -> [(OccName, a)] -> OccEnv a
    extendOccEnvList (A UniqFM OccName a
    x) [(OccName, a)]
    l = UniqFM OccName a -> OccEnv a
    forall a. UniqFM OccName a -> OccEnv a
    A (UniqFM OccName a -> OccEnv a) -> UniqFM OccName a -> OccEnv a
    forall a b. (a -> b) -> a -> b
    $ UniqFM OccName a -> [(OccName, a)] -> UniqFM OccName a
    forall key elt.
    Uniquable key =>
    UniqFM key elt -> [(key, elt)] -> UniqFM key elt
    addListToUFM UniqFM OccName a
    x [(OccName, a)]
    l
    lookupOccEnv :: forall a. OccEnv a -> OccName -> Maybe a
    lookupOccEnv (A UniqFM OccName a
    x) OccName
    y = UniqFM OccName a -> OccName -> Maybe a
    forall key elt. Uniquable key => UniqFM key elt -> key -> Maybe elt
    lookupUFM UniqFM OccName a
    x OccName
    y
    mkOccEnv :: forall a. [(OccName, a)] -> OccEnv a
    mkOccEnv     [(OccName, a)]
    l    = UniqFM OccName a -> OccEnv a
    forall a. UniqFM OccName a -> OccEnv a
    A (UniqFM OccName a -> OccEnv a) -> UniqFM OccName a -> OccEnv a
    forall a b. (a -> b) -> a -> b
    $ [(OccName, a)] -> UniqFM OccName a
    forall key elt. Uniquable key => [(key, elt)] -> UniqFM key elt
    listToUFM [(OccName, a)]
    l
    elemOccEnv :: forall a. OccName -> OccEnv a -> Bool
    elemOccEnv OccName
    x (A UniqFM OccName a
    y)       = OccName -> UniqFM OccName a -> Bool
    forall key elt. Uniquable key => key -> UniqFM key elt -> Bool
    elemUFM OccName
    x UniqFM OccName a
    y
    foldOccEnv :: forall a b. (a -> b -> b) -> b -> OccEnv a -> b
    foldOccEnv a -> b -> b
    a b
    b (A UniqFM OccName a
    c)     = (a -> b -> b) -> b -> UniqFM OccName a -> b
    forall elt a key. (elt -> a -> a) -> a -> UniqFM key elt -> a
    foldUFM a -> b -> b
    a b
    b UniqFM OccName a
    c
    occEnvElts :: forall a. OccEnv a -> [a]
    occEnvElts (A UniqFM OccName a
    x)         = UniqFM OccName a -> [a]
    forall key elt. UniqFM key elt -> [elt]
    eltsUFM UniqFM OccName a
    x
    plusOccEnv :: forall a. OccEnv a -> OccEnv a -> OccEnv a
    plusOccEnv (A UniqFM OccName a
    x) (A UniqFM OccName a
    y)   = UniqFM OccName a -> OccEnv a
    forall a. UniqFM OccName a -> OccEnv a
    A (UniqFM OccName a -> OccEnv a) -> UniqFM OccName a -> OccEnv a
    forall a b. (a -> b) -> a -> b
    $ UniqFM OccName a -> UniqFM OccName a -> UniqFM OccName a
    forall key elt. UniqFM key elt -> UniqFM key elt -> UniqFM key elt
    plusUFM UniqFM OccName a
    x UniqFM OccName a
    y
    plusOccEnv_C :: forall a. (a -> a -> a) -> OccEnv a -> OccEnv a -> OccEnv a
    plusOccEnv_C a -> a -> a
    f (A UniqFM OccName a
    x) (A UniqFM OccName a
    y)       = UniqFM OccName a -> OccEnv a
    forall a. UniqFM OccName a -> OccEnv a
    A (UniqFM OccName a -> OccEnv a) -> UniqFM OccName a -> OccEnv a
    forall a b. (a -> b) -> a -> b
    $ (a -> a -> a)
    -> UniqFM OccName a -> UniqFM OccName a -> UniqFM OccName a
    forall elt key.
    (elt -> elt -> elt)
    -> UniqFM key elt -> UniqFM key elt -> UniqFM key elt
    plusUFM_C a -> a -> a
    f UniqFM OccName a
    x UniqFM OccName a
    y
    extendOccEnv_C :: forall a. (a -> a -> a) -> OccEnv a -> OccName -> a -> OccEnv a
    extendOccEnv_C a -> a -> a
    f (A UniqFM OccName a
    x) OccName
    y a
    z   = UniqFM OccName a -> OccEnv a
    forall a. UniqFM OccName a -> OccEnv a
    A (UniqFM OccName a -> OccEnv a) -> UniqFM OccName a -> OccEnv a
    forall a b. (a -> b) -> a -> b
    $ (a -> a -> a)
    -> UniqFM OccName a -> OccName -> a -> UniqFM OccName a
    forall key elt.
    Uniquable key =>
    (elt -> elt -> elt)
    -> UniqFM key elt -> key -> elt -> UniqFM key elt
    addToUFM_C a -> a -> a
    f UniqFM OccName a
    x OccName
    y a
    z
    extendOccEnv_Acc :: forall a b.
    (a -> b -> b) -> (a -> b) -> OccEnv b -> OccName -> a -> OccEnv b
    extendOccEnv_Acc a -> b -> b
    f a -> b
    g (A UniqFM OccName b
    x) OccName
    y a
    z   = UniqFM OccName b -> OccEnv b
    forall a. UniqFM OccName a -> OccEnv a
    A (UniqFM OccName b -> OccEnv b) -> UniqFM OccName b -> OccEnv b
    forall a b. (a -> b) -> a -> b
    $ (a -> b -> b)
    -> (a -> b) -> UniqFM OccName b -> OccName -> a -> UniqFM OccName b
    forall key elt elts.
    Uniquable key =>
    (elt -> elts -> elts)
    -> (elt -> elts)
    -> UniqFM key elts
    -> key
    -> elt
    -> UniqFM key elts
    addToUFM_Acc a -> b -> b
    f a -> b
    g UniqFM OccName b
    x OccName
    y a
    z
    mapOccEnv :: forall a b. (a -> b) -> OccEnv a -> OccEnv b
    mapOccEnv a -> b
    f (A UniqFM OccName a
    x)        = UniqFM OccName b -> OccEnv b
    forall a. UniqFM OccName a -> OccEnv a
    A (UniqFM OccName b -> OccEnv b) -> UniqFM OccName b -> OccEnv b
    forall a b. (a -> b) -> a -> b
    $ (a -> b) -> UniqFM OccName a -> UniqFM OccName b
    forall elt1 elt2 key.
    (elt1 -> elt2) -> UniqFM key elt1 -> UniqFM key elt2
    mapUFM a -> b
    f UniqFM OccName a
    x
    mkOccEnv_C :: forall a. (a -> a -> a) -> [(OccName, a)] -> OccEnv a
    mkOccEnv_C a -> a -> a
    comb [(OccName, a)]
    l = UniqFM OccName a -> OccEnv a
    forall a. UniqFM OccName a -> OccEnv a
    A (UniqFM OccName a -> OccEnv a) -> UniqFM OccName a -> OccEnv a
    forall a b. (a -> b) -> a -> b
    $ (a -> a -> a)
    -> UniqFM OccName a -> [(OccName, a)] -> UniqFM OccName a
    forall key elt.
    Uniquable key =>
    (elt -> elt -> elt)
    -> UniqFM key elt -> [(key, elt)] -> UniqFM key elt
    addListToUFM_C a -> a -> a
    comb UniqFM OccName a
    forall key elt. UniqFM key elt
    emptyUFM [(OccName, a)]
    l
    delFromOccEnv :: forall a. OccEnv a -> OccName -> OccEnv a
    delFromOccEnv (A UniqFM OccName a
    x) OccName
    y    = UniqFM OccName a -> OccEnv a
    forall a. UniqFM OccName a -> OccEnv a
    A (UniqFM OccName a -> OccEnv a) -> UniqFM OccName a -> OccEnv a
    forall a b. (a -> b) -> a -> b
    $ UniqFM OccName a -> OccName -> UniqFM OccName a
    forall key elt.
    Uniquable key =>
    UniqFM key elt -> key -> UniqFM key elt
    delFromUFM UniqFM OccName a
    x OccName
    y
    delListFromOccEnv :: forall a. OccEnv a -> [OccName] -> OccEnv a
    delListFromOccEnv (A UniqFM OccName a
    x) [OccName]
    y  = UniqFM OccName a -> OccEnv a
    forall a. UniqFM OccName a -> OccEnv a
    A (UniqFM OccName a -> OccEnv a) -> UniqFM OccName a -> OccEnv a
    forall a b. (a -> b) -> a -> b
    $ UniqFM OccName a -> [OccName] -> UniqFM OccName a
    forall key elt.
    Uniquable key =>
    UniqFM key elt -> [key] -> UniqFM key elt
    delListFromUFM UniqFM OccName a
    x [OccName]
    y
    filterOccEnv :: forall elt. (elt -> Bool) -> OccEnv elt -> OccEnv elt
    filterOccEnv elt -> Bool
    x (A UniqFM OccName elt
    y)       = UniqFM OccName elt -> OccEnv elt
    forall a. UniqFM OccName a -> OccEnv a
    A (UniqFM OccName elt -> OccEnv elt)
    -> UniqFM OccName elt -> OccEnv elt
    forall a b. (a -> b) -> a -> b
    $ (elt -> Bool) -> UniqFM OccName elt -> UniqFM OccName elt
    forall elt key. (elt -> Bool) -> UniqFM key elt -> UniqFM key elt
    filterUFM elt -> Bool
    x UniqFM OccName elt
    y
    alterOccEnv :: forall elt.
    (Maybe elt -> Maybe elt) -> OccEnv elt -> OccName -> OccEnv elt
    alterOccEnv Maybe elt -> Maybe elt
    fn (A UniqFM OccName elt
    y) OccName
    k     = UniqFM OccName elt -> OccEnv elt
    forall a. UniqFM OccName a -> OccEnv a
    A (UniqFM OccName elt -> OccEnv elt)
    -> UniqFM OccName elt -> OccEnv elt
    forall a b. (a -> b) -> a -> b
    $ (Maybe elt -> Maybe elt)
    -> UniqFM OccName elt -> OccName -> UniqFM OccName elt
    forall key elt.
    Uniquable key =>
    (Maybe elt -> Maybe elt) -> UniqFM key elt -> key -> UniqFM key elt
    alterUFM Maybe elt -> Maybe elt
    fn UniqFM OccName elt
    y OccName
    k

    instance Outputable a => Outputable (OccEnv a) where
        ppr :: OccEnv a -> SDoc
    ppr OccEnv a
    x = (a -> SDoc) -> OccEnv a -> SDoc
    forall a. (a -> SDoc) -> OccEnv a -> SDoc
    pprOccEnv a -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr OccEnv a
    x

    pprOccEnv :: (a -> SDoc) -> OccEnv a -> SDoc
    pprOccEnv :: forall a. (a -> SDoc) -> OccEnv a -> SDoc
    pprOccEnv a -> SDoc
    ppr_elt (A UniqFM OccName a
    env) = (a -> SDoc) -> UniqFM OccName a -> SDoc
    forall a key. (a -> SDoc) -> UniqFM key a -> SDoc
    pprUniqFM a -> SDoc
    ppr_elt UniqFM OccName a
    env

    type OccSet = UniqSet OccName

    emptyOccSet       :: OccSet
    unitOccSet        :: OccName -> OccSet
    mkOccSet          :: [OccName] -> OccSet
    extendOccSet      :: OccSet -> OccName -> OccSet
    extendOccSetList  :: OccSet -> [OccName] -> OccSet
    unionOccSets      :: OccSet -> OccSet -> OccSet
    unionManyOccSets  :: [OccSet] -> OccSet
    minusOccSet       :: OccSet -> OccSet -> OccSet
    elemOccSet        :: OccName -> OccSet -> Bool
    isEmptyOccSet     :: OccSet -> Bool
    intersectOccSet   :: OccSet -> OccSet -> OccSet
    filterOccSet      :: (OccName -> Bool) -> OccSet -> OccSet

    emptyOccSet :: OccSet
    emptyOccSet       = OccSet
    forall a. UniqSet a
    emptyUniqSet
    unitOccSet :: OccName -> OccSet
    unitOccSet        = OccName -> OccSet
    forall a. Uniquable a => a -> UniqSet a
    unitUniqSet
    mkOccSet :: [OccName] -> OccSet
    mkOccSet          = [OccName] -> OccSet
    forall a. Uniquable a => [a] -> UniqSet a
    mkUniqSet
    extendOccSet :: OccSet -> OccName -> OccSet
    extendOccSet      = OccSet -> OccName -> OccSet
    forall a. Uniquable a => UniqSet a -> a -> UniqSet a
    addOneToUniqSet
    extendOccSetList :: OccSet -> [OccName] -> OccSet
    extendOccSetList  = OccSet -> [OccName] -> OccSet
    forall a. Uniquable a => UniqSet a -> [a] -> UniqSet a
    addListToUniqSet
    unionOccSets :: OccSet -> OccSet -> OccSet
    unionOccSets      = OccSet -> OccSet -> OccSet
    forall a. UniqSet a -> UniqSet a -> UniqSet a
    unionUniqSets
    unionManyOccSets :: [OccSet] -> OccSet
    unionManyOccSets  = [OccSet] -> OccSet
    forall a. [UniqSet a] -> UniqSet a
    unionManyUniqSets
    minusOccSet :: OccSet -> OccSet -> OccSet
    minusOccSet       = OccSet -> OccSet -> OccSet
    forall a. UniqSet a -> UniqSet a -> UniqSet a
    minusUniqSet
    elemOccSet :: OccName -> OccSet -> Bool
    elemOccSet        = OccName -> OccSet -> Bool
    forall a. Uniquable a => a -> UniqSet a -> Bool
    elementOfUniqSet
    isEmptyOccSet :: OccSet -> Bool
    isEmptyOccSet     = OccSet -> Bool
    forall a. UniqSet a -> Bool
    isEmptyUniqSet
    intersectOccSet :: OccSet -> OccSet -> OccSet
    intersectOccSet   = OccSet -> OccSet -> OccSet
    forall a. UniqSet a -> UniqSet a -> UniqSet a
    intersectUniqSets
    filterOccSet :: (OccName -> Bool) -> OccSet -> OccSet
    filterOccSet      = (OccName -> Bool) -> OccSet -> OccSet
    forall a. (a -> Bool) -> UniqSet a -> UniqSet a
    filterUniqSet

    {-
    ************************************************************************
    *                                                                      *
    \subsection{Predicates and taking them apart}
    *                                                                      *
    ************************************************************************
    -}

    occNameString :: OccName -> String
    occNameString :: OccName -> [Char]
    occNameString (OccName NameSpace
    _ FastString
    s) = FastString -> [Char]
    unpackFS FastString
    s

    setOccNameSpace :: NameSpace -> OccName -> OccName
    setOccNameSpace :: NameSpace -> OccName -> OccName
    setOccNameSpace NameSpace
    sp (OccName NameSpace
    _ FastString
    occ) = NameSpace -> FastString -> OccName
    OccName NameSpace
    sp FastString
    occ

    isVarOcc, isTvOcc, isTcOcc, isDataOcc :: OccName -> Bool

    isVarOcc :: OccName -> Bool
    isVarOcc (OccName NameSpace
    VarName FastString
    _) = Bool
    True
    isVarOcc OccName
    _                   = Bool
    False

    isTvOcc :: OccName -> Bool
    isTvOcc (OccName NameSpace
    TvName FastString
    _) = Bool
    True
    isTvOcc OccName
    _                  = Bool
    False

    isTcOcc :: OccName -> Bool
    isTcOcc (OccName NameSpace
    TcClsName FastString
    _) = Bool
    True
    isTcOcc OccName
    _                     = Bool
    False

    -- | /Value/ 'OccNames's are those that are either in
    -- the variable or data constructor namespaces
    isValOcc :: OccName -> Bool
    isValOcc :: OccName -> Bool
    isValOcc (OccName NameSpace
    VarName  FastString
    _) = Bool
    True
    isValOcc (OccName NameSpace
    DataName FastString
    _) = Bool
    True
    isValOcc OccName
    _                    = Bool
    False

    isDataOcc :: OccName -> Bool
    isDataOcc (OccName NameSpace
    DataName FastString
    _) = Bool
    True
    isDataOcc OccName
    _                    = Bool
    False

    -- | Test if the 'OccName' is a data constructor that starts with
    -- a symbol (e.g. @:@, or @[]@)
    isDataSymOcc :: OccName -> Bool
    isDataSymOcc :: OccName -> Bool
    isDataSymOcc (OccName NameSpace
    DataName FastString
    s) = FastString -> Bool
    isLexConSym FastString
    s
    isDataSymOcc OccName
    _                    = Bool
    False
    -- 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 -> Bool
    isSymOcc (OccName NameSpace
    DataName FastString
    s)  = FastString -> Bool
    isLexConSym FastString
    s
    isSymOcc (OccName NameSpace
    TcClsName FastString
    s) = FastString -> Bool
    isLexSym FastString
    s
    isSymOcc (OccName NameSpace
    VarName FastString
    s)   = FastString -> Bool
    isLexSym FastString
    s
    isSymOcc (OccName NameSpace
    TvName FastString
    s)    = FastString -> Bool
    isLexSym FastString
    s
    -- Pretty inefficient!

    parenSymOcc :: OccName -> SDoc -> SDoc
    -- ^ Wrap parens around an operator
    parenSymOcc :: OccName -> SDoc -> SDoc
    parenSymOcc OccName
    occ SDoc
    doc | OccName -> Bool
    isSymOcc OccName
    occ = SDoc -> SDoc
    parens SDoc
    doc
                        | Bool
    otherwise    = SDoc
    doc

    startsWithUnderscore :: OccName -> Bool
    -- ^ Haskell 98 encourages compilers to suppress warnings about unused
    -- names in a pattern if they start with @_@: this implements that test
    startsWithUnderscore :: OccName -> Bool
    startsWithUnderscore OccName
    occ = FastString -> Char
    headFS (OccName -> FastString
    occNameFS OccName
    occ) Char -> Char -> Bool
    forall a. Eq a => a -> a -> Bool
    == Char
    '_'

    {-
    ************************************************************************
    *                                                                      *
    \subsection{Making system names}
    *                                                                      *
    ************************************************************************

    Here's our convention for splitting up the interface file name space:

       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)
       $dmop        Default method for 'op'
       $pnC         n'th superclass selector for class C
       $wf          Worker for function 'f'
       $sf..        Specialised version of f
       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 representation type R

    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.

    @mk_deriv@ generates an @OccName@ from the prefix and a string.
    NB: The string must already be encoded!
    -}

    -- | Build an 'OccName' derived from another 'OccName'.
    --
    -- Note that the pieces of the name are passed in as a @[FastString]@ so that
    -- the whole name can be constructed with a single 'concatFS', minimizing
    -- unnecessary intermediate allocations.
    mk_deriv :: NameSpace
             -> FastString      -- ^ A prefix which distinguishes one sort of
                                -- derived name from another
             -> [FastString]    -- ^ The name we are deriving from in pieces which
                                -- will be concatenated.
             -> OccName
    mk_deriv :: NameSpace -> FastString -> [FastString] -> OccName
    mk_deriv NameSpace
    occ_sp FastString
    sys_prefix [FastString]
    str =
        NameSpace -> FastString -> OccName
    mkOccNameFS NameSpace
    occ_sp ([FastString] -> FastString
    concatFS ([FastString] -> FastString) -> [FastString] -> FastString
    forall a b. (a -> b) -> a -> b
    $ FastString
    sys_prefix FastString -> [FastString] -> [FastString]
    forall a. a -> [a] -> [a]
    : [FastString]
    str)

    isDerivedOccName :: OccName -> Bool
    -- ^ Test for definitions internally generated by GHC.  This predicate
    -- is used to suppress printing of internal definitions in some debug prints
    isDerivedOccName :: OccName -> Bool
    isDerivedOccName OccName
    occ =
       case OccName -> [Char]
    occNameString OccName
    occ of
         Char
    '$':Char
    c:[Char]
    _ | Char -> Bool
    isAlphaNum Char
    c -> Bool
    True   -- E.g.  $wfoo
         Char
    c:Char
    ':':[Char]
    _ | Char -> Bool
    isAlphaNum Char
    c -> Bool
    True   -- E.g.  N:blah   newtype coercions
         [Char]
    _other                 -> Bool
    False

    isDefaultMethodOcc :: OccName -> Bool
    isDefaultMethodOcc :: OccName -> Bool
    isDefaultMethodOcc OccName
    occ =
       case OccName -> [Char]
    occNameString OccName
    occ of
         Char
    '$':Char
    'd':Char
    'm':[Char]
    _ -> Bool
    True
         [Char]
    _ -> Bool
    False

    -- | Is an 'OccName' one of a Typeable @TyCon@ or @Module@ binding?
    -- This is needed as these bindings are renamed differently.
    -- See Note [Grand plan for Typeable] in "GHC.Tc.Instance.Typeable".
    isTypeableBindOcc :: OccName -> Bool
    isTypeableBindOcc :: OccName -> Bool
    isTypeableBindOcc OccName
    occ =
       case OccName -> [Char]
    occNameString OccName
    occ of
         Char
    '$':Char
    't':Char
    'c':[Char]
    _ -> Bool
    True  -- mkTyConRepOcc
         Char
    '$':Char
    't':Char
    'r':[Char]
    _ -> Bool
    True  -- Module binding
         [Char]
    _ -> Bool
    False

    mkDataConWrapperOcc, mkWorkerOcc,
            mkMatcherOcc, mkBuilderOcc,
            mkDefaultMethodOcc,
            mkClassDataConOcc, mkDictOcc,
            mkIPOcc, mkSpecOcc, mkForeignExportOcc, mkRepEqOcc,
            mkGenR, mkGen1R,
            mkDataConWorkerOcc, mkNewTyCoOcc,
            mkInstTyCoOcc, mkEqPredCoOcc, mkClassOpAuxOcc,
            mkCon2TagOcc, mkTag2ConOcc, mkMaxTagOcc, mkDataTOcc, mkDataCOcc,
            mkTyConRepOcc
       :: OccName -> OccName

    -- These derived variables have a prefix that no Haskell value could have
    mkDataConWrapperOcc :: OccName -> OccName
    mkDataConWrapperOcc = NameSpace -> FastString -> OccName -> OccName
    mk_simple_deriv NameSpace
    varName  FastString
    "$W"
    mkWorkerOcc :: OccName -> OccName
    mkWorkerOcc         = NameSpace -> FastString -> OccName -> OccName
    mk_simple_deriv NameSpace
    varName  FastString
    "$w"
    mkMatcherOcc :: OccName -> OccName
    mkMatcherOcc        = NameSpace -> FastString -> OccName -> OccName
    mk_simple_deriv NameSpace
    varName  FastString
    "$m"
    mkBuilderOcc :: OccName -> OccName
    mkBuilderOcc        = NameSpace -> FastString -> OccName -> OccName
    mk_simple_deriv NameSpace
    varName  FastString
    "$b"
    mkDefaultMethodOcc :: OccName -> OccName
    mkDefaultMethodOcc  = NameSpace -> FastString -> OccName -> OccName
    mk_simple_deriv NameSpace
    varName  FastString
    "$dm"
    mkClassOpAuxOcc :: OccName -> OccName
    mkClassOpAuxOcc     = NameSpace -> FastString -> OccName -> OccName
    mk_simple_deriv NameSpace
    varName  FastString
    "$c"
    mkDictOcc :: OccName -> OccName
    mkDictOcc           = NameSpace -> FastString -> OccName -> OccName
    mk_simple_deriv NameSpace
    varName  FastString
    "$d"
    mkIPOcc :: OccName -> OccName
    mkIPOcc             = NameSpace -> FastString -> OccName -> OccName
    mk_simple_deriv NameSpace
    varName  FastString
    "$i"
    mkSpecOcc :: OccName -> OccName
    mkSpecOcc           = NameSpace -> FastString -> OccName -> OccName
    mk_simple_deriv NameSpace
    varName  FastString
    "$s"
    mkForeignExportOcc :: OccName -> OccName
    mkForeignExportOcc  = NameSpace -> FastString -> OccName -> OccName
    mk_simple_deriv NameSpace
    varName  FastString
    "$f"
    mkRepEqOcc :: OccName -> OccName
    mkRepEqOcc          = NameSpace -> FastString -> OccName -> OccName
    mk_simple_deriv NameSpace
    tvName   FastString
    "$r"   -- In RULES involving Coercible
    mkClassDataConOcc :: OccName -> OccName
    mkClassDataConOcc   = NameSpace -> FastString -> OccName -> OccName
    mk_simple_deriv NameSpace
    dataName FastString
    "C:"   -- Data con for a class
    mkNewTyCoOcc :: OccName -> OccName
    mkNewTyCoOcc        = NameSpace -> FastString -> OccName -> OccName
    mk_simple_deriv NameSpace
    tcName   FastString
    "N:"   -- Coercion for newtypes
    mkInstTyCoOcc :: OccName -> OccName
    mkInstTyCoOcc       = NameSpace -> FastString -> OccName -> OccName
    mk_simple_deriv NameSpace
    tcName   FastString
    "D:"   -- Coercion for type functions
    mkEqPredCoOcc :: OccName -> OccName
    mkEqPredCoOcc       = NameSpace -> FastString -> OccName -> OccName
    mk_simple_deriv NameSpace
    tcName   FastString
    "$co"

    -- Used in derived instances for the names of auxiliary bindings.
    -- See Note [Auxiliary binders] in GHC.Tc.Deriv.Generate.
    mkCon2TagOcc :: OccName -> OccName
    mkCon2TagOcc        = NameSpace -> FastString -> OccName -> OccName
    mk_simple_deriv NameSpace
    varName  FastString
    "$con2tag_"
    mkTag2ConOcc :: OccName -> OccName
    mkTag2ConOcc        = NameSpace -> FastString -> OccName -> OccName
    mk_simple_deriv NameSpace
    varName  FastString
    "$tag2con_"
    mkMaxTagOcc :: OccName -> OccName
    mkMaxTagOcc         = NameSpace -> FastString -> OccName -> OccName
    mk_simple_deriv NameSpace
    varName  FastString
    "$maxtag_"
    mkDataTOcc :: OccName -> OccName
    mkDataTOcc          = NameSpace -> FastString -> OccName -> OccName
    mk_simple_deriv NameSpace
    varName  FastString
    "$t"
    mkDataCOcc :: OccName -> OccName
    mkDataCOcc          = NameSpace -> FastString -> OccName -> OccName
    mk_simple_deriv NameSpace
    varName  FastString
    "$c"

    -- TyConRepName stuff; see Note [Grand plan for Typeable] in GHC.Tc.Instance.Typeable
    mkTyConRepOcc :: OccName -> OccName
    mkTyConRepOcc OccName
    occ = NameSpace -> FastString -> OccName -> OccName
    mk_simple_deriv NameSpace
    varName FastString
    prefix OccName
    occ
      where
        prefix :: FastString
    prefix | OccName -> Bool
    isDataOcc OccName
    occ = FastString
    "$tc'"
               | Bool
    otherwise     = FastString
    "$tc"

    -- Generic deriving mechanism
    mkGenR :: OccName -> OccName
    mkGenR   = NameSpace -> FastString -> OccName -> OccName
    mk_simple_deriv NameSpace
    tcName FastString
    "Rep_"
    mkGen1R :: OccName -> OccName
    mkGen1R  = NameSpace -> FastString -> OccName -> OccName
    mk_simple_deriv NameSpace
    tcName FastString
    "Rep1_"

    -- Overloaded record field selectors
    mkRecFldSelOcc :: String -> OccName
    mkRecFldSelOcc :: [Char] -> OccName
    mkRecFldSelOcc [Char]
    s = NameSpace -> FastString -> [FastString] -> OccName
    mk_deriv NameSpace
    varName FastString
    "$sel" [[Char] -> FastString
    fsLit [Char]
    s]

    mk_simple_deriv :: NameSpace -> FastString -> OccName -> OccName
    mk_simple_deriv :: NameSpace -> FastString -> OccName -> OccName
    mk_simple_deriv NameSpace
    sp FastString
    px OccName
    occ = NameSpace -> FastString -> [FastString] -> OccName
    mk_deriv NameSpace
    sp FastString
    px [OccName -> FastString
    occNameFS OccName
    occ]

    -- Data constructor workers are made by setting the name space
    -- of the data constructor OccName (which should be a DataName)
    -- to VarName
    mkDataConWorkerOcc :: OccName -> OccName
    mkDataConWorkerOcc OccName
    datacon_occ = NameSpace -> OccName -> OccName
    setOccNameSpace NameSpace
    varName OccName
    datacon_occ

    mkSuperDictAuxOcc :: Int -> OccName -> OccName
    mkSuperDictAuxOcc :: Int -> OccName -> OccName
    mkSuperDictAuxOcc Int
    index OccName
    cls_tc_occ
      = NameSpace -> FastString -> [FastString] -> OccName
    mk_deriv NameSpace
    varName FastString
    "$cp" [[Char] -> FastString
    fsLit ([Char] -> FastString) -> [Char] -> FastString
    forall a b. (a -> b) -> a -> b
    $ Int -> [Char]
    forall a. Show a => a -> [Char]
    show Int
    index, OccName -> FastString
    occNameFS OccName
    cls_tc_occ]

    mkSuperDictSelOcc :: Int        -- ^ Index of superclass, e.g. 3
                      -> OccName    -- ^ Class, e.g. @Ord@
                      -> OccName    -- ^ Derived 'Occname', e.g. @$p3Ord@
    mkSuperDictSelOcc :: Int -> OccName -> OccName
    mkSuperDictSelOcc Int
    index OccName
    cls_tc_occ
      = NameSpace -> FastString -> [FastString] -> OccName
    mk_deriv NameSpace
    varName FastString
    "$p" [[Char] -> FastString
    fsLit ([Char] -> FastString) -> [Char] -> FastString
    forall a b. (a -> b) -> a -> b
    $ Int -> [Char]
    forall a. Show a => a -> [Char]
    show Int
    index, OccName -> FastString
    occNameFS OccName
    cls_tc_occ]

    mkLocalOcc :: Unique            -- ^ Unique to combine with the 'OccName'
               -> OccName           -- ^ Local name, e.g. @sat@
               -> OccName           -- ^ Nice unique version, e.g. @$L23sat@
    mkLocalOcc :: Unique -> OccName -> OccName
    mkLocalOcc Unique
    uniq OccName
    occ
       = NameSpace -> FastString -> [FastString] -> OccName
    mk_deriv NameSpace
    varName FastString
    "$L" [[Char] -> FastString
    fsLit ([Char] -> FastString) -> [Char] -> FastString
    forall a b. (a -> b) -> a -> b
    $ Unique -> [Char]
    forall a. Show a => a -> [Char]
    show Unique
    uniq, OccName -> FastString
    occNameFS OccName
    occ]
            -- The Unique might print with characters
            -- that need encoding (e.g. 'z'!)

    -- | 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 :: [Char] -> OccSet -> OccName
    mkInstTyTcOcc [Char]
    str = NameSpace -> [Char] -> OccSet -> OccName
    chooseUniqueOcc NameSpace
    tcName (Char
    'R' Char -> [Char] -> [Char]
    forall a. a -> [a] -> [a]
    : Char
    ':' Char -> [Char] -> [Char]
    forall a. a -> [a] -> [a]
    : [Char]
    str)

    mkDFunOcc :: String             -- ^ Typically the class and type glommed together e.g. @OrdMaybe@.
                                    -- Only used in debug mode, for extra clarity
              -> 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.

    mkDFunOcc :: [Char] -> Bool -> OccSet -> OccName
    mkDFunOcc [Char]
    info_str Bool
    is_boot OccSet
    set
      = NameSpace -> [Char] -> OccSet -> OccName
    chooseUniqueOcc NameSpace
    VarName ([Char]
    prefix [Char] -> [Char] -> [Char]
    forall a. [a] -> [a] -> [a]
    ++ [Char]
    info_str) OccSet
    set
      where
        prefix :: [Char]
    prefix | Bool
    is_boot   = [Char]
    "$fx"
               | Bool
    otherwise = [Char]
    "$f"

    {-
    Sometimes we need to pick an OccName that has not already been used,
    given a set of in-use OccNames.
    -}

    chooseUniqueOcc :: NameSpace -> String -> OccSet -> OccName
    chooseUniqueOcc :: NameSpace -> [Char] -> OccSet -> OccName
    chooseUniqueOcc NameSpace
    ns [Char]
    str OccSet
    set = OccName -> Int -> OccName
    loop (NameSpace -> [Char] -> OccName
    mkOccName NameSpace
    ns [Char]
    str) (Int
    0::Int)
      where
      loop :: OccName -> Int -> OccName
    loop OccName
    occ Int
    n
       | OccName
    occ OccName -> OccSet -> Bool
    `elemOccSet` OccSet
    set = OccName -> Int -> OccName
    loop (NameSpace -> [Char] -> OccName
    mkOccName NameSpace
    ns ([Char]
    str [Char] -> [Char] -> [Char]
    forall a. [a] -> [a] -> [a]
    ++ Int -> [Char]
    forall a. Show a => a -> [Char]
    show Int
    n)) (Int
    nInt -> Int -> Int
    forall a. Num a => a -> a -> a
    +Int
    1)
       | Bool
    otherwise            = OccName
    occ

    {-
    We used to add a '$m' to indicate a method, but that gives rise to bad
    error messages from the type checker when we print the function name or pattern
    of an instance-decl binding.  Why? Because the binding is zapped
    to use the method name in place of the selector name.
    (See GHC.Tc.TyCl.Class.tcMethodBind)

    The way it is now, -ddump-xx output may look confusing, but
    you can always say -dppr-debug to get the uniques.

    However, we *do* have to zap the first character to be lower case,
    because overloaded constructors (blarg) generate methods too.
    And convert to VarName space

    e.g. a call to constructor MkFoo where
            data (Ord a) => Foo a = MkFoo a

    If this is necessary, we do it by prefixing '$m'.  These
    guys never show up in error messages.  What a hack.
    -}

    mkMethodOcc :: OccName -> OccName
    mkMethodOcc :: OccName -> OccName
    mkMethodOcc occ :: OccName
    occ@(OccName NameSpace
    VarName FastString
    _) = OccName
    occ
    mkMethodOcc OccName
    occ                     = NameSpace -> FastString -> OccName -> OccName
    mk_simple_deriv NameSpace
    varName FastString
    "$m" OccName
    occ

    {-
    ************************************************************************
    *                                                                      *
    \subsection{Tidying them up}
    *                                                                      *
    ************************************************************************

    Before we print chunks of code we like to rename it so that
    we don't have to print lots of silly uniques in it.  But we mustn't
    accidentally introduce name clashes!  So the idea is that we leave the
    OccName alone unless it accidentally clashes with one that is already
    in scope; if so, we tack on '1' at the end and try again, then '2', and
    so on till we find a unique one.

    There's a wrinkle for operators.  Consider '>>='.  We can't use '>>=1'
    because that isn't a single lexeme.  So we encode it to 'lle' and *then*
    tack on the '1', if necessary.

    Note [TidyOccEnv]
    ~~~~~~~~~~~~~~~~~
    type TidyOccEnv = UniqFM Int

    * Domain = The OccName's FastString. These FastStrings are "taken";
               make sure that we don't re-use

    * Int, n = A plausible starting point for new guesses
               There is no guarantee that "FSn" is available;
               you must look that up in the TidyOccEnv.  But
               it's a good place to start looking.

    * When looking for a renaming for "foo2" we strip off the "2" and start
      with "foo".  Otherwise if we tidy twice we get silly names like foo23.

      However, if it started with digits at the end, we always make a name
      with digits at the end, rather than shortening "foo2" to just "foo",
      even if "foo" is unused.  Reasons:
         - Plain "foo" might be used later
         - We use trailing digits to subtly indicate a unification variable
           in typechecker error message; see TypeRep.tidyTyVarBndr

    We have to take care though! Consider a machine-generated module (#10370)
      module Foo where
         a1 = e1
         a2 = e2
         ...
         a2000 = e2000
    Then "a1", "a2" etc are all marked taken.  But now if we come across "a7" again,
    we have to do a linear search to find a free one, "a2001".  That might just be
    acceptable once.  But if we now come across "a8" again, we don't want to repeat
    that search.

    So we use the TidyOccEnv mapping for "a" (not "a7" or "a8") as our base for
    starting the search; and we make sure to update the starting point for "a"
    after we allocate a new one.

    Note [Tidying multiple names at once]
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    Consider

        > :t (id,id,id)

    Every id contributes a type variable to the type signature, and all of them are
    "a". If we tidy them one by one, we get

        (id,id,id) :: (a2 -> a2, a1 -> a1, a -> a)

    which is a bit unfortunate, as it unfairly renames only two of them. What we
    would like to see is

        (id,id,id) :: (a3 -> a3, a2 -> a2, a1 -> a1)

    To achieve this, the function avoidClashesOccEnv can be used to prepare the
    TidyEnv, by “blocking” every name that occurs twice in the map. This way, none
    of the "a"s will get the privilege of keeping this name, and all of them will
    get a suitable number by tidyOccName.

    This prepared TidyEnv can then be used with tidyOccName. See tidyTyCoVarBndrs
    for an example where this is used.

    This is #12382.

    -}

    type TidyOccEnv = UniqFM FastString Int    -- The in-scope OccNames
      -- See Note [TidyOccEnv]

    emptyTidyOccEnv :: TidyOccEnv
    emptyTidyOccEnv :: TidyOccEnv
    emptyTidyOccEnv = TidyOccEnv
    forall key elt. UniqFM key elt
    emptyUFM

    initTidyOccEnv :: [OccName] -> TidyOccEnv       -- Initialise with names to avoid!
    initTidyOccEnv :: [OccName] -> TidyOccEnv
    initTidyOccEnv = (TidyOccEnv -> OccName -> TidyOccEnv)
    -> TidyOccEnv -> [OccName] -> TidyOccEnv
    forall (t :: * -> *) b a.
    Foldable t =>
    (b -> a -> b) -> b -> t a -> b
    foldl' TidyOccEnv -> OccName -> TidyOccEnv
    forall {elt}.
    Num elt =>
    UniqFM FastString elt -> OccName -> UniqFM FastString elt
    add TidyOccEnv
    forall key elt. UniqFM key elt
    emptyUFM
      where
        add :: UniqFM FastString elt -> OccName -> UniqFM FastString elt
    add UniqFM FastString elt
    env (OccName NameSpace
    _ FastString
    fs) = UniqFM FastString elt -> FastString -> elt -> UniqFM FastString elt
    forall key elt.
    Uniquable key =>
    UniqFM key elt -> key -> elt -> UniqFM key elt
    addToUFM UniqFM FastString elt
    env FastString
    fs elt
    1

    delTidyOccEnvList :: TidyOccEnv -> [FastString] -> TidyOccEnv
    delTidyOccEnvList :: TidyOccEnv -> [FastString] -> TidyOccEnv
    delTidyOccEnvList = TidyOccEnv -> [FastString] -> TidyOccEnv
    forall key elt.
    Uniquable key =>
    UniqFM key elt -> [key] -> UniqFM key elt
    delListFromUFM

    -- see Note [Tidying multiple names at once]
    avoidClashesOccEnv :: TidyOccEnv -> [OccName] -> TidyOccEnv
    avoidClashesOccEnv :: TidyOccEnv -> [OccName] -> TidyOccEnv
    avoidClashesOccEnv TidyOccEnv
    env [OccName]
    occs = TidyOccEnv -> UniqFM FastString () -> [OccName] -> TidyOccEnv
    forall {elt}.
    Num elt =>
    UniqFM FastString elt
    -> UniqFM FastString () -> [OccName] -> UniqFM FastString elt
    go TidyOccEnv
    env UniqFM FastString ()
    forall key elt. UniqFM key elt
    emptyUFM [OccName]
    occs
      where
        go :: UniqFM FastString elt
    -> UniqFM FastString () -> [OccName] -> UniqFM FastString elt
    go UniqFM FastString elt
    env UniqFM FastString ()
    _        [] = UniqFM FastString elt
    env
        go UniqFM FastString elt
    env UniqFM FastString ()
    seenOnce ((OccName NameSpace
    _ FastString
    fs):[OccName]
    occs)
          | FastString
    fs FastString -> UniqFM FastString elt -> Bool
    forall key elt. Uniquable key => key -> UniqFM key elt -> Bool
    `elemUFM` UniqFM FastString elt
    env      = UniqFM FastString elt
    -> UniqFM FastString () -> [OccName] -> UniqFM FastString elt
    go UniqFM FastString elt
    env UniqFM FastString ()
    seenOnce                  [OccName]
    occs
          | FastString
    fs FastString -> UniqFM FastString () -> Bool
    forall key elt. Uniquable key => key -> UniqFM key elt -> Bool
    `elemUFM` UniqFM FastString ()
    seenOnce = UniqFM FastString elt
    -> UniqFM FastString () -> [OccName] -> UniqFM FastString elt
    go (UniqFM FastString elt -> FastString -> elt -> UniqFM FastString elt
    forall key elt.
    Uniquable key =>
    UniqFM key elt -> key -> elt -> UniqFM key elt
    addToUFM UniqFM FastString elt
    env FastString
    fs elt
    1) UniqFM FastString ()
    seenOnce  [OccName]
    occs
          | Bool
    otherwise             = UniqFM FastString elt
    -> UniqFM FastString () -> [OccName] -> UniqFM FastString elt
    go UniqFM FastString elt
    env (UniqFM FastString () -> FastString -> () -> UniqFM FastString ()
    forall key elt.
    Uniquable key =>
    UniqFM key elt -> key -> elt -> UniqFM key elt
    addToUFM UniqFM FastString ()
    seenOnce FastString
    fs ()) [OccName]
    occs

    tidyOccName :: TidyOccEnv -> OccName -> (TidyOccEnv, OccName)
    tidyOccName :: TidyOccEnv -> OccName -> (TidyOccEnv, OccName)
    tidyOccName TidyOccEnv
    env occ :: OccName
    occ@(OccName NameSpace
    occ_sp FastString
    fs)
      | Bool -> Bool
    not (FastString
    fs FastString -> TidyOccEnv -> Bool
    forall key elt. Uniquable key => key -> UniqFM key elt -> Bool
    `elemUFM` TidyOccEnv
    env)
      = -- Desired OccName is free, so use it,
        -- and record in 'env' that it's no longer available
        (TidyOccEnv -> FastString -> Int -> TidyOccEnv
    forall key elt.
    Uniquable key =>
    UniqFM key elt -> key -> elt -> UniqFM key elt
    addToUFM TidyOccEnv
    env FastString
    fs Int
    1, OccName
    occ)

      | Bool
    otherwise
      = case TidyOccEnv -> FastString -> Maybe Int
    forall key elt. Uniquable key => UniqFM key elt -> key -> Maybe elt
    lookupUFM TidyOccEnv
    env FastString
    base1 of
           Maybe Int
    Nothing -> (TidyOccEnv -> FastString -> Int -> TidyOccEnv
    forall key elt.
    Uniquable key =>
    UniqFM key elt -> key -> elt -> UniqFM key elt
    addToUFM TidyOccEnv
    env FastString
    base1 Int
    2, NameSpace -> FastString -> OccName
    OccName NameSpace
    occ_sp FastString
    base1)
           Just Int
    n  -> Int -> Int -> (TidyOccEnv, OccName)
    find Int
    1 Int
    n
      where
        base :: String  -- Drop trailing digits (see Note [TidyOccEnv])
        base :: [Char]
    base  = (Char -> Bool) -> [Char] -> [Char]
    forall a. (a -> Bool) -> [a] -> [a]
    dropWhileEndLE Char -> Bool
    isDigit (FastString -> [Char]
    unpackFS FastString
    fs)
        base1 :: FastString
    base1 = [Char] -> FastString
    mkFastString ([Char]
    base [Char] -> [Char] -> [Char]
    forall a. [a] -> [a] -> [a]
    ++ [Char]
    "1")

        find :: Int -> Int -> (TidyOccEnv, OccName)
    find !Int
    k !Int
    n
          = case TidyOccEnv -> FastString -> Maybe Int
    forall key elt. Uniquable key => UniqFM key elt -> key -> Maybe elt
    lookupUFM TidyOccEnv
    env FastString
    new_fs of
              Just {} -> Int -> Int -> (TidyOccEnv, OccName)
    find (Int
    kInt -> Int -> Int
    forall a. Num a => a -> a -> a
    +Int
    1 :: Int) (Int
    nInt -> Int -> Int
    forall a. Num a => a -> a -> a
    +Int
    k)
                           -- By using n+k, the n argument to find goes
                           --    1, add 1, add 2, add 3, etc which
                           -- moves at quadratic speed through a dense patch

              Maybe Int
    Nothing -> (TidyOccEnv
    new_env, NameSpace -> FastString -> OccName
    OccName NameSpace
    occ_sp FastString
    new_fs)
           where
             new_fs :: FastString
    new_fs = [Char] -> FastString
    mkFastString ([Char]
    base [Char] -> [Char] -> [Char]
    forall a. [a] -> [a] -> [a]
    ++ Int -> [Char]
    forall a. Show a => a -> [Char]
    show Int
    n)
             new_env :: TidyOccEnv
    new_env = TidyOccEnv -> FastString -> Int -> TidyOccEnv
    forall key elt.
    Uniquable key =>
    UniqFM key elt -> key -> elt -> UniqFM key elt
    addToUFM (TidyOccEnv -> FastString -> Int -> TidyOccEnv
    forall key elt.
    Uniquable key =>
    UniqFM key elt -> key -> elt -> UniqFM key elt
    addToUFM TidyOccEnv
    env FastString
    new_fs Int
    1) FastString
    base1 (Int
    nInt -> Int -> Int
    forall a. Num a => a -> a -> a
    +Int
    1)
                         -- Update:  base1,  so that next time we'll start where we left off
                         --          new_fs, so that we know it is taken
                         -- If they are the same (n==1), the former wins
                         -- See Note [TidyOccEnv]

    {-
    ************************************************************************
    *                                                                      *
                    Binary instance
        Here rather than in GHC.Iface.Binary because OccName is abstract
    *                                                                      *
    ************************************************************************
    -}

    instance Binary NameSpace where
        put_ :: BinHandle -> NameSpace -> IO ()
    put_ BinHandle
    bh NameSpace
    VarName =
                BinHandle -> Word8 -> IO ()
    putByte BinHandle
    bh Word8
    0
        put_ BinHandle
    bh NameSpace
    DataName =
                BinHandle -> Word8 -> IO ()
    putByte BinHandle
    bh Word8
    1
        put_ BinHandle
    bh NameSpace
    TvName =
                BinHandle -> Word8 -> IO ()
    putByte BinHandle
    bh Word8
    2
        put_ BinHandle
    bh NameSpace
    TcClsName =
                BinHandle -> Word8 -> IO ()
    putByte BinHandle
    bh Word8
    3
        get :: BinHandle -> IO NameSpace
    get BinHandle
    bh = do
                Word8
    h <- BinHandle -> IO Word8
    getByte BinHandle
    bh
                case Word8
    h of
                  Word8
    0 -> NameSpace -> IO NameSpace
    forall (m :: * -> *) a. Monad m => a -> m a
    return NameSpace
    VarName
                  Word8
    1 -> NameSpace -> IO NameSpace
    forall (m :: * -> *) a. Monad m => a -> m a
    return NameSpace
    DataName
                  Word8
    2 -> NameSpace -> IO NameSpace
    forall (m :: * -> *) a. Monad m => a -> m a
    return NameSpace
    TvName
                  Word8
    _ -> NameSpace -> IO NameSpace
    forall (m :: * -> *) a. Monad m => a -> m a
    return NameSpace
    TcClsName

    instance Binary OccName where
        put_ :: BinHandle -> OccName -> IO ()
    put_ BinHandle
    bh (OccName NameSpace
    aa FastString
    ab) = do
                BinHandle -> NameSpace -> IO ()
    forall a. Binary a => BinHandle -> a -> IO ()
    put_ BinHandle
    bh NameSpace
    aa
                BinHandle -> FastString -> IO ()
    forall a. Binary a => BinHandle -> a -> IO ()
    put_ BinHandle
    bh FastString
    ab
        get :: BinHandle -> IO OccName
    get BinHandle
    bh = do
              NameSpace
    aa <- BinHandle -> IO NameSpace
    forall a. Binary a => BinHandle -> IO a
    get BinHandle
    bh
              FastString
    ab <- BinHandle -> IO FastString
    forall a. Binary a => BinHandle -> IO a
    get BinHandle
    bh
              OccName -> IO OccName
    forall (m :: * -> *) a. Monad m => a -> m a
    return (NameSpace -> FastString -> OccName
    OccName NameSpace
    aa FastString
    ab)