    {-# LANGUAGE CPP #-}
    {-# LANGUAGE DeriveDataTypeable #-}
    --
    -- (c) The University of Glasgow
    --

    #include "HsVersions.h"

    module GHC.Types.Avail (
        Avails,
        AvailInfo(..),
        avail,
        availsToNameSet,
        availsToNameSetWithSelectors,
        availsToNameEnv,
        availName, availNames, availNonFldNames,
        availNamesWithSelectors,
        availFlds,
        availsNamesWithOccs,
        availNamesWithOccs,
        stableAvailCmp,
        plusAvail,
        trimAvail,
        filterAvail,
        filterAvails,
        nubAvails

      ) where

    import GHC.Prelude

    import GHC.Types.Name
    import GHC.Types.Name.Env
    import GHC.Types.Name.Set

    import GHC.Types.FieldLabel
    import GHC.Utils.Binary
    import GHC.Data.List.SetOps
    import GHC.Utils.Outputable
    import GHC.Utils.Misc

    import Data.Data ( Data )
    import Data.List ( find )
    import Data.Function

    -- -----------------------------------------------------------------------------
    -- The AvailInfo type

    -- | Records what things are \"available\", i.e. in scope
    data AvailInfo

      -- | An ordinary identifier in scope
      = Avail Name

      -- | A type or class in scope
      --
      -- The __AvailTC Invariant__: If the type or class is itself to be in scope,
      -- it must be /first/ in this list.  Thus, typically:
      --
      -- > AvailTC Eq [Eq, ==, \/=] []
      | AvailTC
           Name         -- ^ The name of the type or class
           [Name]       -- ^ The available pieces of type or class,
                        -- excluding field selectors.
           [FieldLabel] -- ^ The record fields of the type
                        -- (see Note [Representing fields in AvailInfo]).

       deriving ( AvailInfo -> AvailInfo -> Bool
    (AvailInfo -> AvailInfo -> Bool)
    -> (AvailInfo -> AvailInfo -> Bool) -> Eq AvailInfo
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    /= :: AvailInfo -> AvailInfo -> Bool
    $c/= :: AvailInfo -> AvailInfo -> Bool
    == :: AvailInfo -> AvailInfo -> Bool
    $c== :: AvailInfo -> AvailInfo -> Bool
    Eq    -- ^ Used when deciding if the interface has changed
                , Typeable AvailInfo
    Typeable AvailInfo
    -> (forall (c :: * -> *).
        (forall d b. Data d => c (d -> b) -> d -> c b)
        -> (forall g. g -> c g) -> AvailInfo -> c AvailInfo)
    -> (forall (c :: * -> *).
        (forall b r. Data b => c (b -> r) -> c r)
        -> (forall r. r -> c r) -> Constr -> c AvailInfo)
    -> (AvailInfo -> Constr)
    -> (AvailInfo -> DataType)
    -> (forall (t :: * -> *) (c :: * -> *).
        Typeable t =>
        (forall d. Data d => c (t d)) -> Maybe (c AvailInfo))
    -> (forall (t :: * -> * -> *) (c :: * -> *).
        Typeable t =>
        (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c AvailInfo))
    -> ((forall b. Data b => b -> b) -> AvailInfo -> AvailInfo)
    -> (forall r r'.
        (r -> r' -> r)
        -> r -> (forall d. Data d => d -> r') -> AvailInfo -> r)
    -> (forall r r'.
        (r' -> r -> r)
        -> r -> (forall d. Data d => d -> r') -> AvailInfo -> r)
    -> (forall u. (forall d. Data d => d -> u) -> AvailInfo -> [u])
    -> (forall u.
        Int -> (forall d. Data d => d -> u) -> AvailInfo -> u)
    -> (forall (m :: * -> *).
        Monad m =>
        (forall d. Data d => d -> m d) -> AvailInfo -> m AvailInfo)
    -> (forall (m :: * -> *).
        MonadPlus m =>
        (forall d. Data d => d -> m d) -> AvailInfo -> m AvailInfo)
    -> (forall (m :: * -> *).
        MonadPlus m =>
        (forall d. Data d => d -> m d) -> AvailInfo -> m AvailInfo)
    -> Data AvailInfo
    AvailInfo -> DataType
    AvailInfo -> Constr
    (forall b. Data b => b -> b) -> AvailInfo -> AvailInfo
    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) -> AvailInfo -> u
    forall u. (forall d. Data d => d -> u) -> AvailInfo -> [u]
    forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> AvailInfo -> r
    forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> AvailInfo -> r
    forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> AvailInfo -> m AvailInfo
    forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> AvailInfo -> m AvailInfo
    forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c AvailInfo
    forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> AvailInfo -> c AvailInfo
    forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c AvailInfo)
    forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c AvailInfo)
    gmapMo :: forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> AvailInfo -> m AvailInfo
    $cgmapMo :: forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> AvailInfo -> m AvailInfo
    gmapMp :: forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> AvailInfo -> m AvailInfo
    $cgmapMp :: forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> AvailInfo -> m AvailInfo
    gmapM :: forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> AvailInfo -> m AvailInfo
    $cgmapM :: forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> AvailInfo -> m AvailInfo
    gmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> AvailInfo -> u
    $cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> AvailInfo -> u
    gmapQ :: forall u. (forall d. Data d => d -> u) -> AvailInfo -> [u]
    $cgmapQ :: forall u. (forall d. Data d => d -> u) -> AvailInfo -> [u]
    gmapQr :: forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> AvailInfo -> r
    $cgmapQr :: forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> AvailInfo -> r
    gmapQl :: forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> AvailInfo -> r
    $cgmapQl :: forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> AvailInfo -> r
    gmapT :: (forall b. Data b => b -> b) -> AvailInfo -> AvailInfo
    $cgmapT :: (forall b. Data b => b -> b) -> AvailInfo -> AvailInfo
    dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c AvailInfo)
    $cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c AvailInfo)
    dataCast1 :: forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c AvailInfo)
    $cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c AvailInfo)
    dataTypeOf :: AvailInfo -> DataType
    $cdataTypeOf :: AvailInfo -> DataType
    toConstr :: AvailInfo -> Constr
    $ctoConstr :: AvailInfo -> Constr
    gunfold :: forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c AvailInfo
    $cgunfold :: forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c AvailInfo
    gfoldl :: forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> AvailInfo -> c AvailInfo
    $cgfoldl :: forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> AvailInfo -> c AvailInfo
    Data )

    -- | A collection of 'AvailInfo' - several things that are \"available\"
    type Avails = [AvailInfo]

    {-
    Note [Representing fields in AvailInfo]
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    When -XDuplicateRecordFields is disabled (the normal case), a
    datatype like

      data T = MkT { foo :: Int }

    gives rise to the AvailInfo

      AvailTC T [T, MkT] [FieldLabel "foo" False foo]

    whereas if -XDuplicateRecordFields is enabled it gives

      AvailTC T [T, MkT] [FieldLabel "foo" True $sel:foo:MkT]

    since the label does not match the selector name.

    The labels in a field list are not necessarily unique:
    data families allow the same parent (the family tycon) to have
    multiple distinct fields with the same label. For example,

      data family F a
      data instance F Int  = MkFInt { foo :: Int }
      data instance F Bool = MkFBool { foo :: Bool}

    gives rise to

      AvailTC F [ F, MkFInt, MkFBool ]
                [ FieldLabel "foo" True $sel:foo:MkFInt
                , FieldLabel "foo" True $sel:foo:MkFBool ]

    Moreover, note that the flIsOverloaded flag need not be the same for
    all the elements of the list.  In the example above, this occurs if
    the two data instances are defined in different modules, one with
    `-XDuplicateRecordFields` enabled and one with it disabled.  Thus it
    is possible to have

      AvailTC F [ F, MkFInt, MkFBool ]
                [ FieldLabel "foo" True $sel:foo:MkFInt
                , FieldLabel "foo" False foo ]

    If the two data instances are defined in different modules, both
    without `-XDuplicateRecordFields`, it will be impossible to export
    them from the same module (even with `-XDuplicateRecordfields`
    enabled), because they would be represented identically.  The
    workaround here is to enable `-XDuplicateRecordFields` on the defining
    modules.
    -}

    -- | Compare lexicographically
    stableAvailCmp :: AvailInfo -> AvailInfo -> Ordering
    stableAvailCmp :: AvailInfo -> AvailInfo -> Ordering
    stableAvailCmp (Avail Name
    n1)       (Avail Name
    n2)   = Name
    n1 Name -> Name -> Ordering
    `stableNameCmp` Name
    n2
    stableAvailCmp (Avail {})         (AvailTC {})   = Ordering
    LT
    stableAvailCmp (AvailTC Name
    n [Name]
    ns [FieldLabel]
    nfs) (AvailTC Name
    m [Name]
    ms [FieldLabel]
    mfs) =
        (Name
    n Name -> Name -> Ordering
    `stableNameCmp` Name
    m) Ordering -> Ordering -> Ordering
    `thenCmp`
        ((Name -> Name -> Ordering) -> [Name] -> [Name] -> Ordering
    forall a. (a -> a -> Ordering) -> [a] -> [a] -> Ordering
    cmpList Name -> Name -> Ordering
    stableNameCmp [Name]
    ns [Name]
    ms) Ordering -> Ordering -> Ordering
    `thenCmp`
        ((FieldLabel -> FieldLabel -> Ordering)
    -> [FieldLabel] -> [FieldLabel] -> Ordering
    forall a. (a -> a -> Ordering) -> [a] -> [a] -> Ordering
    cmpList (Name -> Name -> Ordering
    stableNameCmp (Name -> Name -> Ordering)
    -> (FieldLabel -> Name) -> FieldLabel -> FieldLabel -> Ordering
    forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
    `on` FieldLabel -> Name
    forall a. FieldLbl a -> a
    flSelector) [FieldLabel]
    nfs [FieldLabel]
    mfs)
    stableAvailCmp (AvailTC {})       (Avail {})     = Ordering
    GT

    avail :: Name -> AvailInfo
    avail :: Name -> AvailInfo
    avail Name
    n = Name -> AvailInfo
    Avail Name
    n

    -- -----------------------------------------------------------------------------
    -- Operations on AvailInfo

    availsToNameSet :: [AvailInfo] -> NameSet
    availsToNameSet :: [AvailInfo] -> NameSet
    availsToNameSet [AvailInfo]
    avails = (AvailInfo -> NameSet -> NameSet)
    -> NameSet -> [AvailInfo] -> NameSet
    forall (t :: * -> *) a b.
    Foldable t =>
    (a -> b -> b) -> b -> t a -> b
    foldr AvailInfo -> NameSet -> NameSet
    add NameSet
    emptyNameSet [AvailInfo]
    avails
          where add :: AvailInfo -> NameSet -> NameSet
    add AvailInfo
    avail NameSet
    set = NameSet -> [Name] -> NameSet
    extendNameSetList NameSet
    set (AvailInfo -> [Name]
    availNames AvailInfo
    avail)

    availsToNameSetWithSelectors :: [AvailInfo] -> NameSet
    availsToNameSetWithSelectors :: [AvailInfo] -> NameSet
    availsToNameSetWithSelectors [AvailInfo]
    avails = (AvailInfo -> NameSet -> NameSet)
    -> NameSet -> [AvailInfo] -> NameSet
    forall (t :: * -> *) a b.
    Foldable t =>
    (a -> b -> b) -> b -> t a -> b
    foldr AvailInfo -> NameSet -> NameSet
    add NameSet
    emptyNameSet [AvailInfo]
    avails
          where add :: AvailInfo -> NameSet -> NameSet
    add AvailInfo
    avail NameSet
    set = NameSet -> [Name] -> NameSet
    extendNameSetList NameSet
    set (AvailInfo -> [Name]
    availNamesWithSelectors AvailInfo
    avail)

    availsToNameEnv :: [AvailInfo] -> NameEnv AvailInfo
    availsToNameEnv :: [AvailInfo] -> NameEnv AvailInfo
    availsToNameEnv [AvailInfo]
    avails = (AvailInfo -> NameEnv AvailInfo -> NameEnv AvailInfo)
    -> NameEnv AvailInfo -> [AvailInfo] -> NameEnv AvailInfo
    forall (t :: * -> *) a b.
    Foldable t =>
    (a -> b -> b) -> b -> t a -> b
    foldr AvailInfo -> NameEnv AvailInfo -> NameEnv AvailInfo
    add NameEnv AvailInfo
    forall a. NameEnv a
    emptyNameEnv [AvailInfo]
    avails
         where add :: AvailInfo -> NameEnv AvailInfo -> NameEnv AvailInfo
    add AvailInfo
    avail NameEnv AvailInfo
    env = NameEnv AvailInfo -> [(Name, AvailInfo)] -> NameEnv AvailInfo
    forall a. NameEnv a -> [(Name, a)] -> NameEnv a
    extendNameEnvList NameEnv AvailInfo
    env
                                    ([Name] -> [AvailInfo] -> [(Name, AvailInfo)]
    forall a b. [a] -> [b] -> [(a, b)]
    zip (AvailInfo -> [Name]
    availNames AvailInfo
    avail) (AvailInfo -> [AvailInfo]
    forall a. a -> [a]
    repeat AvailInfo
    avail))

    -- | Just the main name made available, i.e. not the available pieces
    -- of type or class brought into scope by the 'GenAvailInfo'
    availName :: AvailInfo -> Name
    availName :: AvailInfo -> Name
    availName (Avail Name
    n)     = Name
    n
    availName (AvailTC Name
    n [Name]
    _ [FieldLabel]
    _) = Name
    n

    -- | All names made available by the availability information (excluding overloaded selectors)
    availNames :: AvailInfo -> [Name]
    availNames :: AvailInfo -> [Name]
    availNames (Avail Name
    n)         = [Name
    n]
    availNames (AvailTC Name
    _ [Name]
    ns [FieldLabel]
    fs) = [Name]
    ns [Name] -> [Name] -> [Name]
    forall a. [a] -> [a] -> [a]
    ++ [ FieldLabel -> Name
    forall a. FieldLbl a -> a
    flSelector FieldLabel
    f | FieldLabel
    f <- [FieldLabel]
    fs, Bool -> Bool
    not (FieldLabel -> Bool
    forall a. FieldLbl a -> Bool
    flIsOverloaded FieldLabel
    f) ]

    -- | All names made available by the availability information (including overloaded selectors)
    availNamesWithSelectors :: AvailInfo -> [Name]
    availNamesWithSelectors :: AvailInfo -> [Name]
    availNamesWithSelectors (Avail Name
    n)         = [Name
    n]
    availNamesWithSelectors (AvailTC Name
    _ [Name]
    ns [FieldLabel]
    fs) = [Name]
    ns [Name] -> [Name] -> [Name]
    forall a. [a] -> [a] -> [a]
    ++ (FieldLabel -> Name) -> [FieldLabel] -> [Name]
    forall a b. (a -> b) -> [a] -> [b]
    map FieldLabel -> Name
    forall a. FieldLbl a -> a
    flSelector [FieldLabel]
    fs

    -- | Names for non-fields made available by the availability information
    availNonFldNames :: AvailInfo -> [Name]
    availNonFldNames :: AvailInfo -> [Name]
    availNonFldNames (Avail Name
    n)        = [Name
    n]
    availNonFldNames (AvailTC Name
    _ [Name]
    ns [FieldLabel]
    _) = [Name]
    ns

    -- | Fields made available by the availability information
    availFlds :: AvailInfo -> [FieldLabel]
    availFlds :: AvailInfo -> [FieldLabel]
    availFlds (AvailTC Name
    _ [Name]
    _ [FieldLabel]
    fs) = [FieldLabel]
    fs
    availFlds AvailInfo
    _                = []

    availsNamesWithOccs :: [AvailInfo] -> [(Name, OccName)]
    availsNamesWithOccs :: [AvailInfo] -> [(Name, OccName)]
    availsNamesWithOccs = (AvailInfo -> [(Name, OccName)])
    -> [AvailInfo] -> [(Name, OccName)]
    forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
    concatMap AvailInfo -> [(Name, OccName)]
    availNamesWithOccs

    -- | 'Name's made available by the availability information, paired with
    -- the 'OccName' used to refer to each one.
    --
    -- When @DuplicateRecordFields@ is in use, the 'Name' may be the
    -- mangled name of a record selector (e.g. @$sel:foo:MkT@) while the
    -- 'OccName' will be the label of the field (e.g. @foo@).
    --
    -- See Note [Representing fields in AvailInfo].
    availNamesWithOccs :: AvailInfo -> [(Name, OccName)]
    availNamesWithOccs :: AvailInfo -> [(Name, OccName)]
    availNamesWithOccs (Avail Name
    n) = [(Name
    n, Name -> OccName
    nameOccName Name
    n)]
    availNamesWithOccs (AvailTC Name
    _ [Name]
    ns [FieldLabel]
    fs)
      = [ (Name
    n, Name -> OccName
    nameOccName Name
    n) | Name
    n <- [Name]
    ns ] [(Name, OccName)] -> [(Name, OccName)] -> [(Name, OccName)]
    forall a. [a] -> [a] -> [a]
    ++
        [ (FieldLabel -> Name
    forall a. FieldLbl a -> a
    flSelector FieldLabel
    fl, FieldLabelString -> OccName
    mkVarOccFS (FieldLabel -> FieldLabelString
    forall a. FieldLbl a -> FieldLabelString
    flLabel FieldLabel
    fl)) | FieldLabel
    fl <- [FieldLabel]
    fs ]

    -- -----------------------------------------------------------------------------
    -- Utility

    plusAvail :: AvailInfo -> AvailInfo -> AvailInfo
    plusAvail :: AvailInfo -> AvailInfo -> AvailInfo
    plusAvail AvailInfo
    a1 AvailInfo
    a2
      | Bool
    debugIsOn Bool -> Bool -> Bool
    && AvailInfo -> Name
    availName AvailInfo
    a1 Name -> Name -> Bool
    forall a. Eq a => a -> a -> Bool
    /= AvailInfo -> Name
    availName AvailInfo
    a2
      = String -> SDoc -> AvailInfo
    forall a. HasCallStack => String -> SDoc -> a
    pprPanic String
    "GHC.Rename.Env.plusAvail names differ" ([SDoc] -> SDoc
    hsep [AvailInfo -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr AvailInfo
    a1,AvailInfo -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr AvailInfo
    a2])
    plusAvail a1 :: AvailInfo
    a1@(Avail {})         (Avail {})        = AvailInfo
    a1
    plusAvail (AvailTC Name
    _ [] [])     a2 :: AvailInfo
    a2@(AvailTC {})   = AvailInfo
    a2
    plusAvail a1 :: AvailInfo
    a1@(AvailTC {})       (AvailTC Name
    _ [] []) = AvailInfo
    a1
    plusAvail (AvailTC Name
    n1 (Name
    s1:[Name]
    ss1) [FieldLabel]
    fs1) (AvailTC Name
    n2 (Name
    s2:[Name]
    ss2) [FieldLabel]
    fs2)
      = case (Name
    n1Name -> Name -> Bool
    forall a. Eq a => a -> a -> Bool
    ==Name
    s1, Name
    n2Name -> Name -> Bool
    forall a. Eq a => a -> a -> Bool
    ==Name
    s2) of  -- Maintain invariant the parent is first
           (Bool
    True,Bool
    True)   -> Name -> [Name] -> [FieldLabel] -> AvailInfo
    AvailTC Name
    n1 (Name
    s1 Name -> [Name] -> [Name]
    forall a. a -> [a] -> [a]
    : ([Name]
    ss1 [Name] -> [Name] -> [Name]
    forall a.
    (HasDebugCallStack, Outputable a, Eq a) =>
    [a] -> [a] -> [a]
    `unionLists` [Name]
    ss2))
                                       ([FieldLabel]
    fs1 [FieldLabel] -> [FieldLabel] -> [FieldLabel]
    forall a.
    (HasDebugCallStack, Outputable a, Eq a) =>
    [a] -> [a] -> [a]
    `unionLists` [FieldLabel]
    fs2)
           (Bool
    True,Bool
    False)  -> Name -> [Name] -> [FieldLabel] -> AvailInfo
    AvailTC Name
    n1 (Name
    s1 Name -> [Name] -> [Name]
    forall a. a -> [a] -> [a]
    : ([Name]
    ss1 [Name] -> [Name] -> [Name]
    forall a.
    (HasDebugCallStack, Outputable a, Eq a) =>
    [a] -> [a] -> [a]
    `unionLists` (Name
    s2Name -> [Name] -> [Name]
    forall a. a -> [a] -> [a]
    :[Name]
    ss2)))
                                       ([FieldLabel]
    fs1 [FieldLabel] -> [FieldLabel] -> [FieldLabel]
    forall a.
    (HasDebugCallStack, Outputable a, Eq a) =>
    [a] -> [a] -> [a]
    `unionLists` [FieldLabel]
    fs2)
           (Bool
    False,Bool
    True)  -> Name -> [Name] -> [FieldLabel] -> AvailInfo
    AvailTC Name
    n1 (Name
    s2 Name -> [Name] -> [Name]
    forall a. a -> [a] -> [a]
    : ((Name
    s1Name -> [Name] -> [Name]
    forall a. a -> [a] -> [a]
    :[Name]
    ss1) [Name] -> [Name] -> [Name]
    forall a.
    (HasDebugCallStack, Outputable a, Eq a) =>
    [a] -> [a] -> [a]
    `unionLists` [Name]
    ss2))
                                       ([FieldLabel]
    fs1 [FieldLabel] -> [FieldLabel] -> [FieldLabel]
    forall a.
    (HasDebugCallStack, Outputable a, Eq a) =>
    [a] -> [a] -> [a]
    `unionLists` [FieldLabel]
    fs2)
           (Bool
    False,Bool
    False) -> Name -> [Name] -> [FieldLabel] -> AvailInfo
    AvailTC Name
    n1 ((Name
    s1Name -> [Name] -> [Name]
    forall a. a -> [a] -> [a]
    :[Name]
    ss1) [Name] -> [Name] -> [Name]
    forall a.
    (HasDebugCallStack, Outputable a, Eq a) =>
    [a] -> [a] -> [a]
    `unionLists` (Name
    s2Name -> [Name] -> [Name]
    forall a. a -> [a] -> [a]
    :[Name]
    ss2))
                                       ([FieldLabel]
    fs1 [FieldLabel] -> [FieldLabel] -> [FieldLabel]
    forall a.
    (HasDebugCallStack, Outputable a, Eq a) =>
    [a] -> [a] -> [a]
    `unionLists` [FieldLabel]
    fs2)
    plusAvail (AvailTC Name
    n1 [Name]
    ss1 [FieldLabel]
    fs1) (AvailTC Name
    _ [] [FieldLabel]
    fs2)
      = Name -> [Name] -> [FieldLabel] -> AvailInfo
    AvailTC Name
    n1 [Name]
    ss1 ([FieldLabel]
    fs1 [FieldLabel] -> [FieldLabel] -> [FieldLabel]
    forall a.
    (HasDebugCallStack, Outputable a, Eq a) =>
    [a] -> [a] -> [a]
    `unionLists` [FieldLabel]
    fs2)
    plusAvail (AvailTC Name
    n1 [] [FieldLabel]
    fs1)  (AvailTC Name
    _ [Name]
    ss2 [FieldLabel]
    fs2)
      = Name -> [Name] -> [FieldLabel] -> AvailInfo
    AvailTC Name
    n1 [Name]
    ss2 ([FieldLabel]
    fs1 [FieldLabel] -> [FieldLabel] -> [FieldLabel]
    forall a.
    (HasDebugCallStack, Outputable a, Eq a) =>
    [a] -> [a] -> [a]
    `unionLists` [FieldLabel]
    fs2)
    plusAvail AvailInfo
    a1 AvailInfo
    a2 = String -> SDoc -> AvailInfo
    forall a. HasCallStack => String -> SDoc -> a
    pprPanic String
    "GHC.Rename.Env.plusAvail" ([SDoc] -> SDoc
    hsep [AvailInfo -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr AvailInfo
    a1,AvailInfo -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr AvailInfo
    a2])

    -- | trims an 'AvailInfo' to keep only a single name
    trimAvail :: AvailInfo -> Name -> AvailInfo
    trimAvail :: AvailInfo -> Name -> AvailInfo
    trimAvail (Avail Name
    n)         Name
    _ = Name -> AvailInfo
    Avail Name
    n
    trimAvail (AvailTC Name
    n [Name]
    ns [FieldLabel]
    fs) Name
    m = case (FieldLabel -> Bool) -> [FieldLabel] -> Maybe FieldLabel
    forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
    find ((Name -> Name -> Bool
    forall a. Eq a => a -> a -> Bool
    == Name
    m) (Name -> Bool) -> (FieldLabel -> Name) -> FieldLabel -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . FieldLabel -> Name
    forall a. FieldLbl a -> a
    flSelector) [FieldLabel]
    fs of
        Just FieldLabel
    x  -> Name -> [Name] -> [FieldLabel] -> AvailInfo
    AvailTC Name
    n [] [FieldLabel
    x]
        Maybe FieldLabel
    Nothing -> ASSERT( m `elem` ns ) AvailTC n [m] []

    -- | filters 'AvailInfo's by the given predicate
    filterAvails  :: (Name -> Bool) -> [AvailInfo] -> [AvailInfo]
    filterAvails :: (Name -> Bool) -> [AvailInfo] -> [AvailInfo]
    filterAvails Name -> Bool
    keep [AvailInfo]
    avails = (AvailInfo -> [AvailInfo] -> [AvailInfo])
    -> [AvailInfo] -> [AvailInfo] -> [AvailInfo]
    forall (t :: * -> *) a b.
    Foldable t =>
    (a -> b -> b) -> b -> t a -> b
    foldr ((Name -> Bool) -> AvailInfo -> [AvailInfo] -> [AvailInfo]
    filterAvail Name -> Bool
    keep) [] [AvailInfo]
    avails

    -- | filters an 'AvailInfo' by the given predicate
    filterAvail :: (Name -> Bool) -> AvailInfo -> [AvailInfo] -> [AvailInfo]
    filterAvail :: (Name -> Bool) -> AvailInfo -> [AvailInfo] -> [AvailInfo]
    filterAvail Name -> Bool
    keep AvailInfo
    ie [AvailInfo]
    rest =
      case AvailInfo
    ie of
        Avail Name
    n | Name -> Bool
    keep Name
    n    -> AvailInfo
    ie AvailInfo -> [AvailInfo] -> [AvailInfo]
    forall a. a -> [a] -> [a]
    : [AvailInfo]
    rest
                | Bool
    otherwise -> [AvailInfo]
    rest
        AvailTC Name
    tc [Name]
    ns [FieldLabel]
    fs ->
            let ns' :: [Name]
    ns' = (Name -> Bool) -> [Name] -> [Name]
    forall a. (a -> Bool) -> [a] -> [a]
    filter Name -> Bool
    keep [Name]
    ns
                fs' :: [FieldLabel]
    fs' = (FieldLabel -> Bool) -> [FieldLabel] -> [FieldLabel]
    forall a. (a -> Bool) -> [a] -> [a]
    filter (Name -> Bool
    keep (Name -> Bool) -> (FieldLabel -> Name) -> FieldLabel -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . FieldLabel -> Name
    forall a. FieldLbl a -> a
    flSelector) [FieldLabel]
    fs in
            if [Name] -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    null [Name]
    ns' Bool -> Bool -> Bool
    && [FieldLabel] -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    null [FieldLabel]
    fs' then [AvailInfo]
    rest else Name -> [Name] -> [FieldLabel] -> AvailInfo
    AvailTC Name
    tc [Name]
    ns' [FieldLabel]
    fs' AvailInfo -> [AvailInfo] -> [AvailInfo]
    forall a. a -> [a] -> [a]
    : [AvailInfo]
    rest

    -- | Combines 'AvailInfo's from the same family
    -- 'avails' may have several items with the same availName
    -- E.g  import Ix( Ix(..), index )
    -- will give Ix(Ix,index,range) and Ix(index)
    -- We want to combine these; addAvail does that
    nubAvails :: [AvailInfo] -> [AvailInfo]
    nubAvails :: [AvailInfo] -> [AvailInfo]
    nubAvails [AvailInfo]
    avails = NameEnv AvailInfo -> [AvailInfo]
    forall a. NameEnv a -> [a]
    nameEnvElts ((NameEnv AvailInfo -> AvailInfo -> NameEnv AvailInfo)
    -> NameEnv AvailInfo -> [AvailInfo] -> NameEnv AvailInfo
    forall (t :: * -> *) b a.
    Foldable t =>
    (b -> a -> b) -> b -> t a -> b
    foldl' NameEnv AvailInfo -> AvailInfo -> NameEnv AvailInfo
    add NameEnv AvailInfo
    forall a. NameEnv a
    emptyNameEnv [AvailInfo]
    avails)
      where
        add :: NameEnv AvailInfo -> AvailInfo -> NameEnv AvailInfo
    add NameEnv AvailInfo
    env AvailInfo
    avail = (AvailInfo -> AvailInfo -> AvailInfo)
    -> NameEnv AvailInfo -> Name -> AvailInfo -> NameEnv AvailInfo
    forall a. (a -> a -> a) -> NameEnv a -> Name -> a -> NameEnv a
    extendNameEnv_C AvailInfo -> AvailInfo -> AvailInfo
    plusAvail NameEnv AvailInfo
    env (AvailInfo -> Name
    availName AvailInfo
    avail) AvailInfo
    avail

    -- -----------------------------------------------------------------------------
    -- Printing

    instance Outputable AvailInfo where
       ppr :: AvailInfo -> SDoc
    ppr = AvailInfo -> SDoc
    pprAvail

    pprAvail :: AvailInfo -> SDoc
    pprAvail :: AvailInfo -> SDoc
    pprAvail (Avail Name
    n)
      = Name -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Name
    n
    pprAvail (AvailTC Name
    n [Name]
    ns [FieldLabel]
    fs)
      = Name -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Name
    n SDoc -> SDoc -> SDoc
    <> SDoc -> SDoc
    braces ([SDoc] -> SDoc
    sep [ [SDoc] -> SDoc
    fsep (SDoc -> [SDoc] -> [SDoc]
    punctuate SDoc
    comma ((Name -> SDoc) -> [Name] -> [SDoc]
    forall a b. (a -> b) -> [a] -> [b]
    map Name -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr [Name]
    ns)) SDoc -> SDoc -> SDoc
    <> SDoc
    semi
                             , [SDoc] -> SDoc
    fsep (SDoc -> [SDoc] -> [SDoc]
    punctuate SDoc
    comma ((FieldLabel -> SDoc) -> [FieldLabel] -> [SDoc]
    forall a b. (a -> b) -> [a] -> [b]
    map (FieldLabelString -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr (FieldLabelString -> SDoc)
    -> (FieldLabel -> FieldLabelString) -> FieldLabel -> SDoc
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . FieldLabel -> FieldLabelString
    forall a. FieldLbl a -> FieldLabelString
    flLabel) [FieldLabel]
    fs))])

    instance Binary AvailInfo where
        put_ :: BinHandle -> AvailInfo -> IO ()
    put_ BinHandle
    bh (Avail Name
    aa) = do
                BinHandle -> Word8 -> IO ()
    putByte BinHandle
    bh Word8
    0
                BinHandle -> Name -> IO ()
    forall a. Binary a => BinHandle -> a -> IO ()
    put_ BinHandle
    bh Name
    aa
        put_ BinHandle
    bh (AvailTC Name
    ab [Name]
    ac [FieldLabel]
    ad) = do
                BinHandle -> Word8 -> IO ()
    putByte BinHandle
    bh Word8
    1
                BinHandle -> Name -> IO ()
    forall a. Binary a => BinHandle -> a -> IO ()
    put_ BinHandle
    bh Name
    ab
                BinHandle -> [Name] -> IO ()
    forall a. Binary a => BinHandle -> a -> IO ()
    put_ BinHandle
    bh [Name]
    ac
                BinHandle -> [FieldLabel] -> IO ()
    forall a. Binary a => BinHandle -> a -> IO ()
    put_ BinHandle
    bh [FieldLabel]
    ad
        get :: BinHandle -> IO AvailInfo
    get BinHandle
    bh = do
                Word8
    h <- BinHandle -> IO Word8
    getByte BinHandle
    bh
                case Word8
    h of
                  Word8
    0 -> do Name
    aa <- BinHandle -> IO Name
    forall a. Binary a => BinHandle -> IO a
    get BinHandle
    bh
                          AvailInfo -> IO AvailInfo
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Name -> AvailInfo
    Avail Name
    aa)
                  Word8
    _ -> do Name
    ab <- BinHandle -> IO Name
    forall a. Binary a => BinHandle -> IO a
    get BinHandle
    bh
                          [Name]
    ac <- BinHandle -> IO [Name]
    forall a. Binary a => BinHandle -> IO a
    get BinHandle
    bh
                          [FieldLabel]
    ad <- BinHandle -> IO [FieldLabel]
    forall a. Binary a => BinHandle -> IO a
    get BinHandle
    bh
                          AvailInfo -> IO AvailInfo
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Name -> [Name] -> [FieldLabel] -> AvailInfo
    AvailTC Name
    ab [Name]
    ac [FieldLabel]
    ad)