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

    \section[TyConEnv]{@TyConEnv@: tyCon environments}
    -}

    {-# LANGUAGE ScopedTypeVariables #-}

    module GHC.Core.TyCon.Env (
            -- * TyCon environment (map)
            TyConEnv,

            -- ** Manipulating these environments
            mkTyConEnv, mkTyConEnvWith,
            emptyTyConEnv, isEmptyTyConEnv,
            unitTyConEnv, nonDetTyConEnvElts,
            extendTyConEnv_C, extendTyConEnv_Acc, extendTyConEnv,
            extendTyConEnvList, extendTyConEnvList_C,
            filterTyConEnv, anyTyConEnv,
            plusTyConEnv, plusTyConEnv_C, plusTyConEnv_CD, plusTyConEnv_CD2, alterTyConEnv,
            lookupTyConEnv, lookupTyConEnv_NF, delFromTyConEnv, delListFromTyConEnv,
            elemTyConEnv, mapTyConEnv, disjointTyConEnv,

            DTyConEnv,

            emptyDTyConEnv, isEmptyDTyConEnv,
            lookupDTyConEnv,
            delFromDTyConEnv, filterDTyConEnv,
            mapDTyConEnv, mapMaybeDTyConEnv,
            adjustDTyConEnv, alterDTyConEnv, extendDTyConEnv, foldDTyConEnv
        ) where

    import GHC.Prelude

    import GHC.Types.Unique.FM
    import GHC.Types.Unique.DFM
    import GHC.Core.TyCon (TyCon)

    import GHC.Data.Maybe

    {-
    ************************************************************************
    *                                                                      *
    \subsection{TyCon environment}
    *                                                                      *
    ************************************************************************
    -}

    -- | TyCon Environment
    type TyConEnv a = UniqFM TyCon a       -- Domain is TyCon

    emptyTyConEnv       :: TyConEnv a
    isEmptyTyConEnv     :: TyConEnv a -> Bool
    mkTyConEnv          :: [(TyCon,a)] -> TyConEnv a
    mkTyConEnvWith      :: (a -> TyCon) -> [a] -> TyConEnv a
    nonDetTyConEnvElts  :: TyConEnv a -> [a]
    alterTyConEnv       :: (Maybe a-> Maybe a) -> TyConEnv a -> TyCon -> TyConEnv a
    extendTyConEnv_C    :: (a->a->a) -> TyConEnv a -> TyCon -> a -> TyConEnv a
    extendTyConEnv_Acc  :: (a->b->b) -> (a->b) -> TyConEnv b -> TyCon -> a -> TyConEnv b
    extendTyConEnv      :: TyConEnv a -> TyCon -> a -> TyConEnv a
    plusTyConEnv        :: TyConEnv a -> TyConEnv a -> TyConEnv a
    plusTyConEnv_C      :: (a->a->a) -> TyConEnv a -> TyConEnv a -> TyConEnv a
    plusTyConEnv_CD     :: (a->a->a) -> TyConEnv a -> a -> TyConEnv a -> a -> TyConEnv a
    plusTyConEnv_CD2    :: (Maybe a->Maybe a->a) -> TyConEnv a -> TyConEnv a -> TyConEnv a
    extendTyConEnvList  :: TyConEnv a -> [(TyCon,a)] -> TyConEnv a
    extendTyConEnvList_C :: (a->a->a) -> TyConEnv a -> [(TyCon,a)] -> TyConEnv a
    delFromTyConEnv     :: TyConEnv a -> TyCon -> TyConEnv a
    delListFromTyConEnv :: TyConEnv a -> [TyCon] -> TyConEnv a
    elemTyConEnv        :: TyCon -> TyConEnv a -> Bool
    unitTyConEnv        :: TyCon -> a -> TyConEnv a
    lookupTyConEnv      :: TyConEnv a -> TyCon -> Maybe a
    lookupTyConEnv_NF   :: TyConEnv a -> TyCon -> a
    filterTyConEnv      :: (elt -> Bool) -> TyConEnv elt -> TyConEnv elt
    anyTyConEnv         :: (elt -> Bool) -> TyConEnv elt -> Bool
    mapTyConEnv         :: (elt1 -> elt2) -> TyConEnv elt1 -> TyConEnv elt2
    disjointTyConEnv    :: TyConEnv a -> TyConEnv a -> Bool

    nonDetTyConEnvElts :: forall a. TyConEnv a -> [a]
    nonDetTyConEnvElts TyConEnv a
    x   = TyConEnv a -> [a]
    forall {k} (key :: k) elt. UniqFM key elt -> [elt]
    nonDetEltsUFM TyConEnv a
    x
    emptyTyConEnv :: forall a. TyConEnv a
    emptyTyConEnv          = UniqFM TyCon a
    forall {k} (key :: k) elt. UniqFM key elt
    emptyUFM
    isEmptyTyConEnv :: forall a. TyConEnv a -> Bool
    isEmptyTyConEnv        = UniqFM TyCon a -> Bool
    forall {k} (key :: k) elt. UniqFM key elt -> Bool
    isNullUFM
    unitTyConEnv :: forall a. TyCon -> a -> TyConEnv a
    unitTyConEnv TyCon
    x a
    y       = TyCon -> a -> UniqFM TyCon a
    forall key elt. Uniquable key => key -> elt -> UniqFM key elt
    unitUFM TyCon
    x a
    y
    extendTyConEnv :: forall a. TyConEnv a -> TyCon -> a -> TyConEnv a
    extendTyConEnv TyConEnv a
    x TyCon
    y a
    z   = TyConEnv a -> TyCon -> a -> TyConEnv a
    forall key elt.
    Uniquable key =>
    UniqFM key elt -> key -> elt -> UniqFM key elt
    addToUFM TyConEnv a
    x TyCon
    y a
    z
    extendTyConEnvList :: forall a. TyConEnv a -> [(TyCon, a)] -> TyConEnv a
    extendTyConEnvList TyConEnv a
    x [(TyCon, a)]
    l = TyConEnv a -> [(TyCon, a)] -> TyConEnv a
    forall key elt.
    Uniquable key =>
    UniqFM key elt -> [(key, elt)] -> UniqFM key elt
    addListToUFM TyConEnv a
    x [(TyCon, a)]
    l
    lookupTyConEnv :: forall a. TyConEnv a -> TyCon -> Maybe a
    lookupTyConEnv TyConEnv a
    x TyCon
    y     = TyConEnv a -> TyCon -> Maybe a
    forall key elt. Uniquable key => UniqFM key elt -> key -> Maybe elt
    lookupUFM TyConEnv a
    x TyCon
    y
    alterTyConEnv :: forall a. (Maybe a -> Maybe a) -> TyConEnv a -> TyCon -> TyConEnv a
    alterTyConEnv          = (Maybe a -> Maybe a) -> UniqFM TyCon a -> TyCon -> UniqFM TyCon a
    forall key elt.
    Uniquable key =>
    (Maybe elt -> Maybe elt) -> UniqFM key elt -> key -> UniqFM key elt
    alterUFM
    mkTyConEnv :: forall a. [(TyCon, a)] -> TyConEnv a
    mkTyConEnv     [(TyCon, a)]
    l       = [(TyCon, a)] -> UniqFM TyCon a
    forall key elt. Uniquable key => [(key, elt)] -> UniqFM key elt
    listToUFM [(TyCon, a)]
    l
    mkTyConEnvWith :: forall a. (a -> TyCon) -> [a] -> TyConEnv a
    mkTyConEnvWith a -> TyCon
    f       = [(TyCon, a)] -> TyConEnv a
    forall a. [(TyCon, a)] -> TyConEnv a
    mkTyConEnv ([(TyCon, a)] -> TyConEnv a)
    -> ([a] -> [(TyCon, a)]) -> [a] -> TyConEnv a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (a -> (TyCon, a)) -> [a] -> [(TyCon, a)]
    forall a b. (a -> b) -> [a] -> [b]
    map (\a
    a -> (a -> TyCon
    f a
    a, a
    a))
    elemTyConEnv :: forall a. TyCon -> TyConEnv a -> Bool
    elemTyConEnv TyCon
    x TyConEnv a
    y          = TyCon -> TyConEnv a -> Bool
    forall key elt. Uniquable key => key -> UniqFM key elt -> Bool
    elemUFM TyCon
    x TyConEnv a
    y
    plusTyConEnv :: forall a. TyConEnv a -> TyConEnv a -> TyConEnv a
    plusTyConEnv TyConEnv a
    x TyConEnv a
    y          = TyConEnv a -> TyConEnv a -> TyConEnv a
    forall {k} (key :: k) elt.
    UniqFM key elt -> UniqFM key elt -> UniqFM key elt
    plusUFM TyConEnv a
    x TyConEnv a
    y
    plusTyConEnv_C :: forall a. (a -> a -> a) -> TyConEnv a -> TyConEnv a -> TyConEnv a
    plusTyConEnv_C a -> a -> a
    f TyConEnv a
    x TyConEnv a
    y      = (a -> a -> a) -> TyConEnv a -> TyConEnv a -> TyConEnv a
    forall {k} elt (key :: k).
    (elt -> elt -> elt)
    -> UniqFM key elt -> UniqFM key elt -> UniqFM key elt
    plusUFM_C a -> a -> a
    f TyConEnv a
    x TyConEnv a
    y
    plusTyConEnv_CD :: forall a.
    (a -> a -> a) -> TyConEnv a -> a -> TyConEnv a -> a -> TyConEnv a
    plusTyConEnv_CD a -> a -> a
    f TyConEnv a
    x a
    d TyConEnv a
    y a
    b = (a -> a -> a) -> TyConEnv a -> a -> TyConEnv a -> a -> TyConEnv a
    forall {k} elta eltb eltc (key :: k).
    (elta -> eltb -> eltc)
    -> UniqFM key elta
    -> elta
    -> UniqFM key eltb
    -> eltb
    -> UniqFM key eltc
    plusUFM_CD a -> a -> a
    f TyConEnv a
    x a
    d TyConEnv a
    y a
    b
    plusTyConEnv_CD2 :: forall a.
    (Maybe a -> Maybe a -> a) -> TyConEnv a -> TyConEnv a -> TyConEnv a
    plusTyConEnv_CD2 Maybe a -> Maybe a -> a
    f TyConEnv a
    x TyConEnv a
    y    = (Maybe a -> Maybe a -> a) -> TyConEnv a -> TyConEnv a -> TyConEnv a
    forall {k} elta eltb eltc (key :: k).
    (Maybe elta -> Maybe eltb -> eltc)
    -> UniqFM key elta -> UniqFM key eltb -> UniqFM key eltc
    plusUFM_CD2 Maybe a -> Maybe a -> a
    f TyConEnv a
    x TyConEnv a
    y
    extendTyConEnv_C :: forall a. (a -> a -> a) -> TyConEnv a -> TyCon -> a -> TyConEnv a
    extendTyConEnv_C a -> a -> a
    f TyConEnv a
    x TyCon
    y a
    z  = (a -> a -> a) -> TyConEnv a -> TyCon -> a -> TyConEnv a
    forall key elt.
    Uniquable key =>
    (elt -> elt -> elt)
    -> UniqFM key elt -> key -> elt -> UniqFM key elt
    addToUFM_C a -> a -> a
    f TyConEnv a
    x TyCon
    y a
    z
    mapTyConEnv :: forall elt1 elt2. (elt1 -> elt2) -> TyConEnv elt1 -> TyConEnv elt2
    mapTyConEnv elt1 -> elt2
    f TyConEnv elt1
    x           = (elt1 -> elt2) -> TyConEnv elt1 -> UniqFM TyCon elt2
    forall {k} elt1 elt2 (key :: k).
    (elt1 -> elt2) -> UniqFM key elt1 -> UniqFM key elt2
    mapUFM elt1 -> elt2
    f TyConEnv elt1
    x
    extendTyConEnv_Acc :: forall a b.
    (a -> b -> b) -> (a -> b) -> TyConEnv b -> TyCon -> a -> TyConEnv b
    extendTyConEnv_Acc a -> b -> b
    x a -> b
    y TyConEnv b
    z TyCon
    a a
    b  = (a -> b -> b) -> (a -> b) -> TyConEnv b -> TyCon -> a -> TyConEnv 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
    x a -> b
    y TyConEnv b
    z TyCon
    a a
    b
    extendTyConEnvList_C :: forall a. (a -> a -> a) -> TyConEnv a -> [(TyCon, a)] -> TyConEnv a
    extendTyConEnvList_C a -> a -> a
    x TyConEnv a
    y [(TyCon, a)]
    z = (a -> a -> a) -> TyConEnv a -> [(TyCon, a)] -> TyConEnv a
    forall key elt.
    Uniquable key =>
    (elt -> elt -> elt)
    -> UniqFM key elt -> [(key, elt)] -> UniqFM key elt
    addListToUFM_C a -> a -> a
    x TyConEnv a
    y [(TyCon, a)]
    z
    delFromTyConEnv :: forall a. TyConEnv a -> TyCon -> TyConEnv a
    delFromTyConEnv TyConEnv a
    x TyCon
    y      = TyConEnv a -> TyCon -> TyConEnv a
    forall key elt.
    Uniquable key =>
    UniqFM key elt -> key -> UniqFM key elt
    delFromUFM TyConEnv a
    x TyCon
    y
    delListFromTyConEnv :: forall a. TyConEnv a -> [TyCon] -> TyConEnv a
    delListFromTyConEnv TyConEnv a
    x [TyCon]
    y  = TyConEnv a -> [TyCon] -> TyConEnv a
    forall key elt.
    Uniquable key =>
    UniqFM key elt -> [key] -> UniqFM key elt
    delListFromUFM TyConEnv a
    x [TyCon]
    y
    filterTyConEnv :: forall elt. (elt -> Bool) -> TyConEnv elt -> TyConEnv elt
    filterTyConEnv elt -> Bool
    x TyConEnv elt
    y       = (elt -> Bool) -> TyConEnv elt -> TyConEnv elt
    forall {k} elt (key :: k).
    (elt -> Bool) -> UniqFM key elt -> UniqFM key elt
    filterUFM elt -> Bool
    x TyConEnv elt
    y
    anyTyConEnv :: forall elt. (elt -> Bool) -> TyConEnv elt -> Bool
    anyTyConEnv elt -> Bool
    f TyConEnv elt
    x          = (elt -> Bool -> Bool) -> Bool -> TyConEnv elt -> Bool
    forall {k} elt a (key :: k).
    (elt -> a -> a) -> a -> UniqFM key elt -> a
    nonDetFoldUFM (Bool -> Bool -> Bool
    (||) (Bool -> Bool -> Bool) -> (elt -> Bool) -> elt -> Bool -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . elt -> Bool
    f) Bool
    False TyConEnv elt
    x
    disjointTyConEnv :: forall a. TyConEnv a -> TyConEnv a -> Bool
    disjointTyConEnv TyConEnv a
    x TyConEnv a
    y     = TyConEnv a -> TyConEnv a -> Bool
    forall {k} (key :: k) elt1 elt2.
    UniqFM key elt1 -> UniqFM key elt2 -> Bool
    disjointUFM TyConEnv a
    x TyConEnv a
    y

    lookupTyConEnv_NF :: forall a. TyConEnv a -> TyCon -> a
    lookupTyConEnv_NF TyConEnv a
    env TyCon
    n = String -> Maybe a -> a
    forall a. HasCallStack => String -> Maybe a -> a
    expectJust String
    "lookupTyConEnv_NF" (TyConEnv a -> TyCon -> Maybe a
    forall a. TyConEnv a -> TyCon -> Maybe a
    lookupTyConEnv TyConEnv a
    env TyCon
    n)

    -- | Deterministic TyCon Environment
    --
    -- See Note [Deterministic UniqFM] in "GHC.Types.Unique.DFM" for explanation why
    -- we need DTyConEnv.
    type DTyConEnv a = UniqDFM TyCon a

    emptyDTyConEnv :: DTyConEnv a
    emptyDTyConEnv :: forall a. DTyConEnv a
    emptyDTyConEnv = UniqDFM TyCon a
    forall {k} (key :: k) elt. UniqDFM key elt
    emptyUDFM

    isEmptyDTyConEnv :: DTyConEnv a -> Bool
    isEmptyDTyConEnv :: forall a. DTyConEnv a -> Bool
    isEmptyDTyConEnv = UniqDFM TyCon a -> Bool
    forall {k} (key :: k) elt. UniqDFM key elt -> Bool
    isNullUDFM

    lookupDTyConEnv :: DTyConEnv a -> TyCon -> Maybe a
    lookupDTyConEnv :: forall a. DTyConEnv a -> TyCon -> Maybe a
    lookupDTyConEnv = UniqDFM TyCon a -> TyCon -> Maybe a
    forall key elt.
    Uniquable key =>
    UniqDFM key elt -> key -> Maybe elt
    lookupUDFM

    delFromDTyConEnv :: DTyConEnv a -> TyCon -> DTyConEnv a
    delFromDTyConEnv :: forall a. DTyConEnv a -> TyCon -> DTyConEnv a
    delFromDTyConEnv = UniqDFM TyCon a -> TyCon -> UniqDFM TyCon a
    forall key elt.
    Uniquable key =>
    UniqDFM key elt -> key -> UniqDFM key elt
    delFromUDFM

    filterDTyConEnv :: (a -> Bool) -> DTyConEnv a -> DTyConEnv a
    filterDTyConEnv :: forall a. (a -> Bool) -> DTyConEnv a -> DTyConEnv a
    filterDTyConEnv = (a -> Bool) -> UniqDFM TyCon a -> UniqDFM TyCon a
    forall {k} elt (key :: k).
    (elt -> Bool) -> UniqDFM key elt -> UniqDFM key elt
    filterUDFM

    mapDTyConEnv :: (a -> b) -> DTyConEnv a -> DTyConEnv b
    mapDTyConEnv :: forall a b. (a -> b) -> DTyConEnv a -> DTyConEnv b
    mapDTyConEnv = (a -> b) -> UniqDFM TyCon a -> UniqDFM TyCon b
    forall {k} elt1 elt2 (key :: k).
    (elt1 -> elt2) -> UniqDFM key elt1 -> UniqDFM key elt2
    mapUDFM

    mapMaybeDTyConEnv :: (a -> Maybe b) -> DTyConEnv a -> DTyConEnv b
    mapMaybeDTyConEnv :: forall a b. (a -> Maybe b) -> DTyConEnv a -> DTyConEnv b
    mapMaybeDTyConEnv = (a -> Maybe b) -> UniqDFM TyCon a -> UniqDFM TyCon b
    forall {k} elt1 elt2 (key :: k).
    (elt1 -> Maybe elt2) -> UniqDFM key elt1 -> UniqDFM key elt2
    mapMaybeUDFM

    adjustDTyConEnv :: (a -> a) -> DTyConEnv a -> TyCon -> DTyConEnv a
    adjustDTyConEnv :: forall a. (a -> a) -> DTyConEnv a -> TyCon -> DTyConEnv a
    adjustDTyConEnv = (a -> a) -> UniqDFM TyCon a -> TyCon -> UniqDFM TyCon a
    forall key elt.
    Uniquable key =>
    (elt -> elt) -> UniqDFM key elt -> key -> UniqDFM key elt
    adjustUDFM

    alterDTyConEnv :: (Maybe a -> Maybe a) -> DTyConEnv a -> TyCon -> DTyConEnv a
    alterDTyConEnv :: forall a.
    (Maybe a -> Maybe a) -> DTyConEnv a -> TyCon -> DTyConEnv a
    alterDTyConEnv = (Maybe a -> Maybe a) -> UniqDFM TyCon a -> TyCon -> UniqDFM TyCon a
    forall key elt.
    Uniquable key =>
    (Maybe elt -> Maybe elt)
    -> UniqDFM key elt -> key -> UniqDFM key elt
    alterUDFM

    extendDTyConEnv :: DTyConEnv a -> TyCon -> a -> DTyConEnv a
    extendDTyConEnv :: forall a. DTyConEnv a -> TyCon -> a -> DTyConEnv a
    extendDTyConEnv = UniqDFM TyCon a -> TyCon -> a -> UniqDFM TyCon a
    forall key elt.
    Uniquable key =>
    UniqDFM key elt -> key -> elt -> UniqDFM key elt
    addToUDFM

    foldDTyConEnv :: (elt -> a -> a) -> a -> DTyConEnv elt -> a
    foldDTyConEnv :: forall elt a. (elt -> a -> a) -> a -> DTyConEnv elt -> a
    foldDTyConEnv = (elt -> a -> a) -> a -> UniqDFM TyCon elt -> a
    forall {k} elt a (key :: k).
    (elt -> a -> a) -> a -> UniqDFM key elt -> a
    foldUDFM