    -- | Dependencies and Usage of a module
    module GHC.Unit.Module.Deps
       ( Dependencies
       , mkDependencies
       , noDependencies
       , dep_direct_mods
       , dep_direct_pkgs
       , dep_sig_mods
       , dep_trusted_pkgs
       , dep_orphs
       , dep_plugin_pkgs
       , dep_finsts
       , dep_boot_mods
       , dep_orphs_update
       , dep_finsts_update
       , pprDeps
       , Usage (..)
       , ImportAvails (..)
       )
    where

    import GHC.Prelude

    import GHC.Data.FastString

    import GHC.Types.SafeHaskell
    import GHC.Types.Name

    import GHC.Unit.Module.Imported
    import GHC.Unit.Module
    import GHC.Unit.Home
    import GHC.Unit.State

    import GHC.Utils.Fingerprint
    import GHC.Utils.Binary
    import GHC.Utils.Outputable

    import Data.List (sortBy, sort, partition)
    import Data.Set (Set)
    import qualified Data.Set as Set
    import Data.Bifunctor

    -- | Dependency information about ALL modules and packages below this one
    -- in the import hierarchy. This is the serialisable version of `ImportAvails`.
    --
    -- Invariant: the dependencies of a module @M@ never includes @M@.
    --
    -- Invariant: none of the lists contain duplicates.
    --
    -- Invariant: lists are ordered canonically (e.g. using stableModuleCmp)
    --
    -- See Note [Transitive Information in Dependencies]
    data Dependencies = Deps
       { Dependencies -> Set (UnitId, GenWithIsBoot ModuleName)
    dep_direct_mods :: Set (UnitId, ModuleNameWithIsBoot)
          -- ^ All home-package modules which are directly imported by this one.
          -- This may include modules from other units when using multiple home units

       , Dependencies -> Set UnitId
    dep_direct_pkgs :: Set UnitId
          -- ^ All packages directly imported by this module
          -- I.e. packages to which this module's direct imports belong.
          -- Does not include other home units when using multiple home units.
          -- Modules from these units will go in `dep_direct_mods`

       , Dependencies -> Set UnitId
    dep_plugin_pkgs :: Set UnitId
          -- ^ All units needed for plugins

        ------------------------------------
        -- Transitive information below here

       , Dependencies -> [ModuleName]
    dep_sig_mods :: ![ModuleName]
        -- ^ Transitive closure of hsig files in the home package

       , Dependencies -> Set UnitId
    dep_trusted_pkgs :: Set UnitId
          -- Packages which we are required to trust
          -- when the module is imported as a safe import
          -- (Safe Haskell). See Note [Tracking Trust Transitively] in GHC.Rename.Names

       , Dependencies -> Set (UnitId, GenWithIsBoot ModuleName)
    dep_boot_mods :: Set (UnitId, ModuleNameWithIsBoot)
          -- ^ All modules which have boot files below this one, and whether we
          -- should use the boot file or not.
          -- This information is only used to populate the eps_is_boot field.
          -- See Note [Structure of dep_boot_mods]

       , Dependencies -> [Module]
    dep_orphs  :: [Module]
          -- ^ Transitive closure of orphan modules (whether
          -- home or external pkg).
          --
          -- (Possible optimization: don't include family
          -- instance orphans as they are anyway included in
          -- 'dep_finsts'.  But then be careful about code
          -- which relies on dep_orphs having the complete list!)
          -- This does NOT include us, unlike 'imp_orphs'.

       , Dependencies -> [Module]
    dep_finsts :: [Module]
          -- ^ Transitive closure of depended upon modules which
          -- contain family instances (whether home or external).
          -- This is used by 'checkFamInstConsistency'.  This
          -- does NOT include us, unlike 'imp_finsts'. See Note
          -- [The type family instance consistency story].

       }
       deriving( Dependencies -> Dependencies -> Bool
    (Dependencies -> Dependencies -> Bool)
    -> (Dependencies -> Dependencies -> Bool) -> Eq Dependencies
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: Dependencies -> Dependencies -> Bool
    == :: Dependencies -> Dependencies -> Bool
    $c/= :: Dependencies -> Dependencies -> Bool
    /= :: Dependencies -> Dependencies -> Bool
    Eq )
            -- Equality used only for old/new comparison in GHC.Iface.Recomp.addFingerprints
            -- See 'GHC.Tc.Utils.ImportAvails' for details on dependencies.

    -- | Extract information from the rename and typecheck phases to produce
    -- a dependencies information for the module being compiled.
    --
    -- The fourth argument is a list of plugin modules.
    mkDependencies :: HomeUnit -> Module -> ImportAvails -> [Module] -> Dependencies
    mkDependencies :: HomeUnit -> Module -> ImportAvails -> [Module] -> Dependencies
    mkDependencies HomeUnit
    home_unit Module
    mod ImportAvails
    imports [Module]
    plugin_mods =
      let ([Module]
    home_plugins, [Module]
    external_plugins) = (Module -> Bool) -> [Module] -> ([Module], [Module])
    forall a. (a -> Bool) -> [a] -> ([a], [a])
    partition (HomeUnit -> GenUnit UnitId -> Bool
    isHomeUnit HomeUnit
    home_unit (GenUnit UnitId -> Bool)
    -> (Module -> GenUnit UnitId) -> Module -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Module -> GenUnit UnitId
    forall unit. GenModule unit -> unit
    moduleUnit) [Module]
    plugin_mods
          plugin_units :: Set UnitId
    plugin_units = [UnitId] -> Set UnitId
    forall a. Ord a => [a] -> Set a
    Set.fromList ((Module -> UnitId) -> [Module] -> [UnitId]
    forall a b. (a -> b) -> [a] -> [b]
    map (GenUnit UnitId -> UnitId
    toUnitId (GenUnit UnitId -> UnitId)
    -> (Module -> GenUnit UnitId) -> Module -> UnitId
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Module -> GenUnit UnitId
    forall unit. GenModule unit -> unit
    moduleUnit) [Module]
    external_plugins)
          all_direct_mods :: InstalledModuleEnv (GenWithIsBoot ModuleName)
    all_direct_mods = (InstalledModule
     -> InstalledModuleEnv (GenWithIsBoot ModuleName)
     -> InstalledModuleEnv (GenWithIsBoot ModuleName))
    -> InstalledModuleEnv (GenWithIsBoot ModuleName)
    -> [InstalledModule]
    -> InstalledModuleEnv (GenWithIsBoot ModuleName)
    forall a b. (a -> b -> b) -> b -> [a] -> b
    forall (t :: * -> *) a b.
    Foldable t =>
    (a -> b -> b) -> b -> t a -> b
    foldr (\InstalledModule
    mn InstalledModuleEnv (GenWithIsBoot ModuleName)
    m -> InstalledModuleEnv (GenWithIsBoot ModuleName)
    -> InstalledModule
    -> GenWithIsBoot ModuleName
    -> InstalledModuleEnv (GenWithIsBoot ModuleName)
    forall a.
    InstalledModuleEnv a
    -> InstalledModule -> a -> InstalledModuleEnv a
    extendInstalledModuleEnv InstalledModuleEnv (GenWithIsBoot ModuleName)
    m InstalledModule
    mn (ModuleName -> IsBootInterface -> GenWithIsBoot ModuleName
    forall mod. mod -> IsBootInterface -> GenWithIsBoot mod
    GWIB (InstalledModule -> ModuleName
    forall unit. GenModule unit -> ModuleName
    moduleName InstalledModule
    mn) IsBootInterface
    NotBoot))
                                  (ImportAvails -> InstalledModuleEnv (GenWithIsBoot ModuleName)
    imp_direct_dep_mods ImportAvails
    imports)
                                  ((Module -> InstalledModule) -> [Module] -> [InstalledModule]
    forall a b. (a -> b) -> [a] -> [b]
    map ((GenUnit UnitId -> UnitId) -> Module -> InstalledModule
    forall a b. (a -> b) -> GenModule a -> GenModule b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap GenUnit UnitId -> UnitId
    toUnitId) [Module]
    home_plugins)

          modDepsElts :: InstalledModuleEnv (GenWithIsBoot ModuleName)
    -> Set (InstalledModule, GenWithIsBoot ModuleName)
    modDepsElts = [(InstalledModule, GenWithIsBoot ModuleName)]
    -> Set (InstalledModule, GenWithIsBoot ModuleName)
    forall a. Ord a => [a] -> Set a
    Set.fromList ([(InstalledModule, GenWithIsBoot ModuleName)]
     -> Set (InstalledModule, GenWithIsBoot ModuleName))
    -> (InstalledModuleEnv (GenWithIsBoot ModuleName)
        -> [(InstalledModule, GenWithIsBoot ModuleName)])
    -> InstalledModuleEnv (GenWithIsBoot ModuleName)
    -> Set (InstalledModule, GenWithIsBoot ModuleName)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . InstalledModuleEnv (GenWithIsBoot ModuleName)
    -> [(InstalledModule, GenWithIsBoot ModuleName)]
    forall a. InstalledModuleEnv a -> [(InstalledModule, a)]
    installedModuleEnvElts
            -- It's OK to use nonDetEltsUFM here because sorting by module names
            -- restores determinism

          direct_mods :: Set (UnitId, GenWithIsBoot ModuleName)
    direct_mods = (InstalledModule -> UnitId)
    -> (InstalledModule, GenWithIsBoot ModuleName)
    -> (UnitId, GenWithIsBoot ModuleName)
    forall a b c. (a -> b) -> (a, c) -> (b, c)
    forall (p :: * -> * -> *) a b c.
    Bifunctor p =>
    (a -> b) -> p a c -> p b c
    first InstalledModule -> UnitId
    forall unit. GenModule unit -> unit
    moduleUnit ((InstalledModule, GenWithIsBoot ModuleName)
     -> (UnitId, GenWithIsBoot ModuleName))
    -> Set (InstalledModule, GenWithIsBoot ModuleName)
    -> Set (UnitId, GenWithIsBoot ModuleName)
    forall b a. Ord b => (a -> b) -> Set a -> Set b
    `Set.map` InstalledModuleEnv (GenWithIsBoot ModuleName)
    -> Set (InstalledModule, GenWithIsBoot ModuleName)
    modDepsElts (InstalledModuleEnv (GenWithIsBoot ModuleName)
    -> InstalledModule -> InstalledModuleEnv (GenWithIsBoot ModuleName)
    forall a.
    InstalledModuleEnv a -> InstalledModule -> InstalledModuleEnv a
    delInstalledModuleEnv InstalledModuleEnv (GenWithIsBoot ModuleName)
    all_direct_mods (GenUnit UnitId -> UnitId
    toUnitId (GenUnit UnitId -> UnitId) -> Module -> InstalledModule
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Module
    mod))
                -- M.hi-boot can be in the imp_dep_mods, but we must remove
                -- it before recording the modules on which this one depends!
                -- (We want to retain M.hi-boot in imp_dep_mods so that
                --  loadHiBootInterface can see if M's direct imports depend
                --  on M.hi-boot, and hence that we should do the hi-boot consistency
                --  check.)

          dep_orphs :: [Module]
    dep_orphs = (Module -> Bool) -> [Module] -> [Module]
    forall a. (a -> Bool) -> [a] -> [a]
    filter (Module -> Module -> Bool
    forall a. Eq a => a -> a -> Bool
    /= Module
    mod) (ImportAvails -> [Module]
    imp_orphs ImportAvails
    imports)
                -- We must also remove self-references from imp_orphs. See
                -- Note [Module self-dependency]

          direct_pkgs :: Set UnitId
    direct_pkgs = ImportAvails -> Set UnitId
    imp_dep_direct_pkgs ImportAvails
    imports

          -- Set the packages required to be Safe according to Safe Haskell.
          -- See Note [Tracking Trust Transitively] in GHC.Rename.Names
          trust_pkgs :: Set UnitId
    trust_pkgs  = ImportAvails -> Set UnitId
    imp_trust_pkgs ImportAvails
    imports

          -- If there's a non-boot import, then it shadows the boot import
          -- coming from the dependencies
          source_mods :: Set (UnitId, GenWithIsBoot ModuleName)
    source_mods = (InstalledModule -> UnitId)
    -> (InstalledModule, GenWithIsBoot ModuleName)
    -> (UnitId, GenWithIsBoot ModuleName)
    forall a b c. (a -> b) -> (a, c) -> (b, c)
    forall (p :: * -> * -> *) a b c.
    Bifunctor p =>
    (a -> b) -> p a c -> p b c
    first InstalledModule -> UnitId
    forall unit. GenModule unit -> unit
    moduleUnit ((InstalledModule, GenWithIsBoot ModuleName)
     -> (UnitId, GenWithIsBoot ModuleName))
    -> Set (InstalledModule, GenWithIsBoot ModuleName)
    -> Set (UnitId, GenWithIsBoot ModuleName)
    forall b a. Ord b => (a -> b) -> Set a -> Set b
    `Set.map` InstalledModuleEnv (GenWithIsBoot ModuleName)
    -> Set (InstalledModule, GenWithIsBoot ModuleName)
    modDepsElts (ImportAvails -> InstalledModuleEnv (GenWithIsBoot ModuleName)
    imp_boot_mods ImportAvails
    imports)

          sig_mods :: [ModuleName]
    sig_mods = (ModuleName -> Bool) -> [ModuleName] -> [ModuleName]
    forall a. (a -> Bool) -> [a] -> [a]
    filter (ModuleName -> ModuleName -> Bool
    forall a. Eq a => a -> a -> Bool
    /= (Module -> ModuleName
    forall unit. GenModule unit -> ModuleName
    moduleName Module
    mod)) ([ModuleName] -> [ModuleName]) -> [ModuleName] -> [ModuleName]
    forall a b. (a -> b) -> a -> b
    $ ImportAvails -> [ModuleName]
    imp_sig_mods ImportAvails
    imports

      in Deps { dep_direct_mods :: Set (UnitId, GenWithIsBoot ModuleName)
    dep_direct_mods  = Set (UnitId, GenWithIsBoot ModuleName)
    direct_mods
              , dep_direct_pkgs :: Set UnitId
    dep_direct_pkgs  = Set UnitId
    direct_pkgs
              , dep_plugin_pkgs :: Set UnitId
    dep_plugin_pkgs  = Set UnitId
    plugin_units
              , dep_sig_mods :: [ModuleName]
    dep_sig_mods     = [ModuleName] -> [ModuleName]
    forall a. Ord a => [a] -> [a]
    sort [ModuleName]
    sig_mods
              , dep_trusted_pkgs :: Set UnitId
    dep_trusted_pkgs = Set UnitId
    trust_pkgs
              , dep_boot_mods :: Set (UnitId, GenWithIsBoot ModuleName)
    dep_boot_mods    = Set (UnitId, GenWithIsBoot ModuleName)
    source_mods
              , dep_orphs :: [Module]
    dep_orphs        = (Module -> Module -> Ordering) -> [Module] -> [Module]
    forall a. (a -> a -> Ordering) -> [a] -> [a]
    sortBy Module -> Module -> Ordering
    stableModuleCmp [Module]
    dep_orphs
              , dep_finsts :: [Module]
    dep_finsts       = (Module -> Module -> Ordering) -> [Module] -> [Module]
    forall a. (a -> a -> Ordering) -> [a] -> [a]
    sortBy Module -> Module -> Ordering
    stableModuleCmp (ImportAvails -> [Module]
    imp_finsts ImportAvails
    imports)
                -- sort to get into canonical order
                -- NB. remember to use lexicographic ordering
              }

    -- | Update module dependencies containing orphans (used by Backpack)
    dep_orphs_update :: Monad m => Dependencies -> ([Module] -> m [Module]) -> m Dependencies
    dep_orphs_update :: forall (m :: * -> *).
    Monad m =>
    Dependencies -> ([Module] -> m [Module]) -> m Dependencies
    dep_orphs_update Dependencies
    deps [Module] -> m [Module]
    f = do
      r <- [Module] -> m [Module]
    f (Dependencies -> [Module]
    dep_orphs Dependencies
    deps)
      pure (deps { dep_orphs = sortBy stableModuleCmp r })

    -- | Update module dependencies containing family instances (used by Backpack)
    dep_finsts_update :: Monad m => Dependencies -> ([Module] -> m [Module]) -> m Dependencies
    dep_finsts_update :: forall (m :: * -> *).
    Monad m =>
    Dependencies -> ([Module] -> m [Module]) -> m Dependencies
    dep_finsts_update Dependencies
    deps [Module] -> m [Module]
    f = do
      r <- [Module] -> m [Module]
    f (Dependencies -> [Module]
    dep_finsts Dependencies
    deps)
      pure (deps { dep_finsts = sortBy stableModuleCmp r })

    instance Binary Dependencies where
        put_ :: WriteBinHandle -> Dependencies -> IO ()
    put_ WriteBinHandle
    bh Dependencies
    deps = do WriteBinHandle -> Set (UnitId, GenWithIsBoot ModuleName) -> IO ()
    forall a. Binary a => WriteBinHandle -> a -> IO ()
    put_ WriteBinHandle
    bh (Dependencies -> Set (UnitId, GenWithIsBoot ModuleName)
    dep_direct_mods Dependencies
    deps)
                          WriteBinHandle -> Set UnitId -> IO ()
    forall a. Binary a => WriteBinHandle -> a -> IO ()
    put_ WriteBinHandle
    bh (Dependencies -> Set UnitId
    dep_direct_pkgs Dependencies
    deps)
                          WriteBinHandle -> Set UnitId -> IO ()
    forall a. Binary a => WriteBinHandle -> a -> IO ()
    put_ WriteBinHandle
    bh (Dependencies -> Set UnitId
    dep_plugin_pkgs Dependencies
    deps)
                          WriteBinHandle -> Set UnitId -> IO ()
    forall a. Binary a => WriteBinHandle -> a -> IO ()
    put_ WriteBinHandle
    bh (Dependencies -> Set UnitId
    dep_trusted_pkgs Dependencies
    deps)
                          WriteBinHandle -> [ModuleName] -> IO ()
    forall a. Binary a => WriteBinHandle -> a -> IO ()
    put_ WriteBinHandle
    bh (Dependencies -> [ModuleName]
    dep_sig_mods Dependencies
    deps)
                          WriteBinHandle -> Set (UnitId, GenWithIsBoot ModuleName) -> IO ()
    forall a. Binary a => WriteBinHandle -> a -> IO ()
    put_ WriteBinHandle
    bh (Dependencies -> Set (UnitId, GenWithIsBoot ModuleName)
    dep_boot_mods Dependencies
    deps)
                          WriteBinHandle -> [Module] -> IO ()
    forall a. Binary a => WriteBinHandle -> a -> IO ()
    put_ WriteBinHandle
    bh (Dependencies -> [Module]
    dep_orphs Dependencies
    deps)
                          WriteBinHandle -> [Module] -> IO ()
    forall a. Binary a => WriteBinHandle -> a -> IO ()
    put_ WriteBinHandle
    bh (Dependencies -> [Module]
    dep_finsts Dependencies
    deps)

        get :: ReadBinHandle -> IO Dependencies
    get ReadBinHandle
    bh = do dms <- ReadBinHandle -> IO (Set (UnitId, GenWithIsBoot ModuleName))
    forall a. Binary a => ReadBinHandle -> IO a
    get ReadBinHandle
    bh
                    dps <- get bh
                    plugin_pkgs <- get bh
                    tps <- get bh
                    hsigms <- get bh
                    sms <- get bh
                    os <- get bh
                    fis <- get bh
                    return (Deps { dep_direct_mods = dms
                                 , dep_direct_pkgs = dps
                                 , dep_plugin_pkgs = plugin_pkgs
                                 , dep_sig_mods = hsigms
                                 , dep_boot_mods = sms
                                 , dep_trusted_pkgs = tps
                                 , dep_orphs = os,
                                   dep_finsts = fis })

    noDependencies :: Dependencies
    noDependencies :: Dependencies
    noDependencies = Deps
      { dep_direct_mods :: Set (UnitId, GenWithIsBoot ModuleName)
    dep_direct_mods  = Set (UnitId, GenWithIsBoot ModuleName)
    forall a. Set a
    Set.empty
      , dep_direct_pkgs :: Set UnitId
    dep_direct_pkgs  = Set UnitId
    forall a. Set a
    Set.empty
      , dep_plugin_pkgs :: Set UnitId
    dep_plugin_pkgs  = Set UnitId
    forall a. Set a
    Set.empty
      , dep_sig_mods :: [ModuleName]
    dep_sig_mods     = []
      , dep_boot_mods :: Set (UnitId, GenWithIsBoot ModuleName)
    dep_boot_mods    = Set (UnitId, GenWithIsBoot ModuleName)
    forall a. Set a
    Set.empty
      , dep_trusted_pkgs :: Set UnitId
    dep_trusted_pkgs = Set UnitId
    forall a. Set a
    Set.empty
      , dep_orphs :: [Module]
    dep_orphs        = []
      , dep_finsts :: [Module]
    dep_finsts       = []
      }

    -- | Pretty-print unit dependencies
    pprDeps :: UnitState -> Dependencies -> SDoc
    pprDeps :: UnitState -> Dependencies -> SDoc
    pprDeps UnitState
    unit_state (Deps { dep_direct_mods :: Dependencies -> Set (UnitId, GenWithIsBoot ModuleName)
    dep_direct_mods = Set (UnitId, GenWithIsBoot ModuleName)
    dmods
                             , dep_boot_mods :: Dependencies -> Set (UnitId, GenWithIsBoot ModuleName)
    dep_boot_mods = Set (UnitId, GenWithIsBoot ModuleName)
    bmods
                             , dep_plugin_pkgs :: Dependencies -> Set UnitId
    dep_plugin_pkgs = Set UnitId
    plgns
                             , dep_orphs :: Dependencies -> [Module]
    dep_orphs = [Module]
    orphs
                             , dep_direct_pkgs :: Dependencies -> Set UnitId
    dep_direct_pkgs = Set UnitId
    pkgs
                             , dep_trusted_pkgs :: Dependencies -> Set UnitId
    dep_trusted_pkgs = Set UnitId
    tps
                             , dep_finsts :: Dependencies -> [Module]
    dep_finsts = [Module]
    finsts
                             })
      = UnitState -> SDoc -> SDoc
    pprWithUnitState UnitState
    unit_state (SDoc -> SDoc) -> SDoc -> SDoc
    forall a b. (a -> b) -> a -> b
    $
        [SDoc] -> SDoc
    forall doc. IsDoc doc => [doc] -> doc
    vcat [String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "direct module dependencies:"  SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> ((UnitId, GenWithIsBoot ModuleName) -> SDoc)
    -> Set (UnitId, GenWithIsBoot ModuleName) -> SDoc
    forall a. Outputable a => (a -> SDoc) -> Set a -> SDoc
    ppr_set (UnitId, GenWithIsBoot ModuleName) -> SDoc
    forall {a} {a}.
    (Outputable a, Outputable a) =>
    (a, GenWithIsBoot a) -> SDoc
    ppr_mod Set (UnitId, GenWithIsBoot ModuleName)
    dmods,
              String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "boot module dependencies:"    SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> ((UnitId, GenWithIsBoot ModuleName) -> SDoc)
    -> Set (UnitId, GenWithIsBoot ModuleName) -> SDoc
    forall a. Outputable a => (a -> SDoc) -> Set a -> SDoc
    ppr_set (UnitId, GenWithIsBoot ModuleName) -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Set (UnitId, GenWithIsBoot ModuleName)
    bmods,
              String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "direct package dependencies:" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> (UnitId -> SDoc) -> Set UnitId -> SDoc
    forall a. Outputable a => (a -> SDoc) -> Set a -> SDoc
    ppr_set UnitId -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Set UnitId
    pkgs,
              String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "plugin package dependencies:" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> (UnitId -> SDoc) -> Set UnitId -> SDoc
    forall a. Outputable a => (a -> SDoc) -> Set a -> SDoc
    ppr_set UnitId -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Set UnitId
    plgns,
              if Set UnitId -> Bool
    forall a. Set a -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    null Set UnitId
    tps
                then SDoc
    forall doc. IsOutput doc => doc
    empty
                else String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "trusted package dependencies:" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> (UnitId -> SDoc) -> Set UnitId -> SDoc
    forall a. Outputable a => (a -> SDoc) -> Set a -> SDoc
    ppr_set UnitId -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Set UnitId
    tps,
              String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "orphans:" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> [SDoc] -> SDoc
    forall doc. IsLine doc => [doc] -> doc
    fsep ((Module -> SDoc) -> [Module] -> [SDoc]
    forall a b. (a -> b) -> [a] -> [b]
    map Module -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr [Module]
    orphs),
              String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "family instance modules:" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> [SDoc] -> SDoc
    forall doc. IsLine doc => [doc] -> doc
    fsep ((Module -> SDoc) -> [Module] -> [SDoc]
    forall a b. (a -> b) -> [a] -> [b]
    map Module -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr [Module]
    finsts)
            ]
      where
        ppr_mod :: (a, GenWithIsBoot a) -> SDoc
    ppr_mod (a
    uid, (GWIB a
    mod IsBootInterface
    IsBoot))  = a -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr a
    uid SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <> SDoc
    forall doc. IsLine doc => doc
    colon SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <> a -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr a
    mod SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "[boot]"
        ppr_mod (a
    uid, (GWIB a
    mod IsBootInterface
    NotBoot)) = a -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr a
    uid SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <> SDoc
    forall doc. IsLine doc => doc
    colon SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <> a -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr a
    mod

        ppr_set :: Outputable a => (a -> SDoc) -> Set a -> SDoc
        ppr_set :: forall a. Outputable a => (a -> SDoc) -> Set a -> SDoc
    ppr_set a -> SDoc
    w = [SDoc] -> SDoc
    forall doc. IsLine doc => [doc] -> doc
    fsep ([SDoc] -> SDoc) -> (Set a -> [SDoc]) -> Set a -> SDoc
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (a -> SDoc) -> [a] -> [SDoc]
    forall a b. (a -> b) -> [a] -> [b]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap a -> SDoc
    w ([a] -> [SDoc]) -> (Set a -> [a]) -> Set a -> [SDoc]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Set a -> [a]
    forall a. Set a -> [a]
    Set.toAscList

    -- | Records modules for which changes may force recompilation of this module
    -- See wiki: https://gitlab.haskell.org/ghc/ghc/wikis/commentary/compiler/recompilation-avoidance
    --
    -- This differs from Dependencies.  A module X may be in the dep_mods of this
    -- module (via an import chain) but if we don't use anything from X it won't
    -- appear in our Usage
    data Usage
      -- | Module from another package
      = UsagePackageModule {
            Usage -> Module
    usg_mod      :: Module,
               -- ^ External package module depended on
            Usage -> Fingerprint
    usg_mod_hash :: Fingerprint,
                -- ^ Cached module ABI fingerprint (corresponds to mi_mod_hash)
            Usage -> Bool
    usg_safe :: IsSafeImport
                -- ^ Was this module imported as a safe import
        }
      -- | Module from the current package
      | UsageHomeModule {
            Usage -> ModuleName
    usg_mod_name :: ModuleName,
                -- ^ Name of the module
            Usage -> UnitId
    usg_unit_id :: UnitId,
            -- ^ UnitId of the HomeUnit the module is from
            usg_mod_hash :: Fingerprint,
                -- ^ Cached module ABI fingerprint (corresponds to mi_mod_hash).
                -- This may be out dated after recompilation was avoided, but is
                -- still used as a fast initial check for change during
                -- recompilation avoidance.
            Usage -> [(OccName, Fingerprint)]
    usg_entities :: [(OccName,Fingerprint)],
                -- ^ Entities we depend on, sorted by occurrence name and fingerprinted.
                -- NB: usages are for parent names only, e.g. type constructors
                -- but not the associated data constructors.
            Usage -> Maybe Fingerprint
    usg_exports  :: Maybe Fingerprint,
                -- ^ Fingerprint for the export list of this module,
                -- if we directly imported it (and hence we depend on its export list)
            usg_safe :: IsSafeImport
                -- ^ Was this module imported as a safe import
        }
      -- | A file upon which the module depends, e.g. a CPP #include, or using TH's
      -- 'addDependentFile'
      | UsageFile {
            Usage -> FastString
    usg_file_path  :: FastString,
            -- ^ External file dependency. From a CPP #include or TH
            -- addDependentFile. Should be absolute.
            Usage -> Fingerprint
    usg_file_hash  :: Fingerprint,
            -- ^ 'Fingerprint' of the file contents.

            Usage -> Maybe String
    usg_file_label :: Maybe String
            -- ^ An optional string which is used in recompilation messages if
            -- file in question has changed.

            -- Note: We don't consider things like modification timestamps
            -- here, because there's no reason to recompile if the actual
            -- contents don't change.  This previously lead to odd
            -- recompilation behaviors; see #8114
      }
      | UsageHomeModuleInterface {
            usg_mod_name :: ModuleName
            -- ^ Name of the module
            , usg_unit_id :: UnitId
            -- ^ UnitId of the HomeUnit the module is from
            , Usage -> Fingerprint
    usg_iface_hash :: Fingerprint
            -- ^ The *interface* hash of the module, not the ABI hash.
            -- This changes when anything about the interface (and hence the
            -- module) has changed.

            -- UsageHomeModuleInterface is *only* used for recompilation
            -- checking when using TemplateHaskell in the interpreter (where
            -- some modules are loaded as BCOs).

      }
      -- | A requirement which was merged into this one.
      | UsageMergedRequirement {
            usg_mod :: Module,
            usg_mod_hash :: Fingerprint
      }
        deriving( Usage -> Usage -> Bool
    (Usage -> Usage -> Bool) -> (Usage -> Usage -> Bool) -> Eq Usage
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: Usage -> Usage -> Bool
    == :: Usage -> Usage -> Bool
    $c/= :: Usage -> Usage -> Bool
    /= :: Usage -> Usage -> Bool
    Eq )
            -- The export list field is (Just v) if we depend on the export list:
            --      i.e. we imported the module directly, whether or not we
            --           enumerated the things we imported, or just imported
            --           everything
            -- We need to recompile if M's exports change, because
            -- if the import was    import M,       we might now have a name clash
            --                                      in the importing module.
            -- if the import was    import M(x)     M might no longer export x
            -- The only way we don't depend on the export list is if we have
            --                      import M()
            -- And of course, for modules that aren't imported directly we don't
            -- depend on their export lists

    instance Binary Usage where
        put_ :: WriteBinHandle -> Usage -> IO ()
    put_ WriteBinHandle
    bh usg :: Usage
    usg@UsagePackageModule{} = do
            WriteBinHandle -> Word8 -> IO ()
    putByte WriteBinHandle
    bh Word8
    0
            WriteBinHandle -> Module -> IO ()
    forall a. Binary a => WriteBinHandle -> a -> IO ()
    put_ WriteBinHandle
    bh (Usage -> Module
    usg_mod Usage
    usg)
            WriteBinHandle -> Fingerprint -> IO ()
    forall a. Binary a => WriteBinHandle -> a -> IO ()
    put_ WriteBinHandle
    bh (Usage -> Fingerprint
    usg_mod_hash Usage
    usg)
            WriteBinHandle -> Bool -> IO ()
    forall a. Binary a => WriteBinHandle -> a -> IO ()
    put_ WriteBinHandle
    bh (Usage -> Bool
    usg_safe     Usage
    usg)

        put_ WriteBinHandle
    bh usg :: Usage
    usg@UsageHomeModule{} = do
            WriteBinHandle -> Word8 -> IO ()
    putByte WriteBinHandle
    bh Word8
    1
            WriteBinHandle -> ModuleName -> IO ()
    forall a. Binary a => WriteBinHandle -> a -> IO ()
    put_ WriteBinHandle
    bh (Usage -> ModuleName
    usg_mod_name Usage
    usg)
            WriteBinHandle -> UnitId -> IO ()
    forall a. Binary a => WriteBinHandle -> a -> IO ()
    put_ WriteBinHandle
    bh (Usage -> UnitId
    usg_unit_id  Usage
    usg)
            WriteBinHandle -> Fingerprint -> IO ()
    forall a. Binary a => WriteBinHandle -> a -> IO ()
    put_ WriteBinHandle
    bh (Usage -> Fingerprint
    usg_mod_hash Usage
    usg)
            WriteBinHandle -> Maybe Fingerprint -> IO ()
    forall a. Binary a => WriteBinHandle -> a -> IO ()
    put_ WriteBinHandle
    bh (Usage -> Maybe Fingerprint
    usg_exports  Usage
    usg)
            WriteBinHandle -> [(OccName, Fingerprint)] -> IO ()
    forall a. Binary a => WriteBinHandle -> a -> IO ()
    put_ WriteBinHandle
    bh (Usage -> [(OccName, Fingerprint)]
    usg_entities Usage
    usg)
            WriteBinHandle -> Bool -> IO ()
    forall a. Binary a => WriteBinHandle -> a -> IO ()
    put_ WriteBinHandle
    bh (Usage -> Bool
    usg_safe     Usage
    usg)

        put_ WriteBinHandle
    bh usg :: Usage
    usg@UsageFile{} = do
            WriteBinHandle -> Word8 -> IO ()
    putByte WriteBinHandle
    bh Word8
    2
            WriteBinHandle -> FastString -> IO ()
    forall a. Binary a => WriteBinHandle -> a -> IO ()
    put_ WriteBinHandle
    bh (Usage -> FastString
    usg_file_path Usage
    usg)
            WriteBinHandle -> Fingerprint -> IO ()
    forall a. Binary a => WriteBinHandle -> a -> IO ()
    put_ WriteBinHandle
    bh (Usage -> Fingerprint
    usg_file_hash Usage
    usg)
            WriteBinHandle -> Maybe String -> IO ()
    forall a. Binary a => WriteBinHandle -> a -> IO ()
    put_ WriteBinHandle
    bh (Usage -> Maybe String
    usg_file_label Usage
    usg)

        put_ WriteBinHandle
    bh usg :: Usage
    usg@UsageMergedRequirement{} = do
            WriteBinHandle -> Word8 -> IO ()
    putByte WriteBinHandle
    bh Word8
    3
            WriteBinHandle -> Module -> IO ()
    forall a. Binary a => WriteBinHandle -> a -> IO ()
    put_ WriteBinHandle
    bh (Usage -> Module
    usg_mod      Usage
    usg)
            WriteBinHandle -> Fingerprint -> IO ()
    forall a. Binary a => WriteBinHandle -> a -> IO ()
    put_ WriteBinHandle
    bh (Usage -> Fingerprint
    usg_mod_hash Usage
    usg)

        put_ WriteBinHandle
    bh usg :: Usage
    usg@UsageHomeModuleInterface{} = do
            WriteBinHandle -> Word8 -> IO ()
    putByte WriteBinHandle
    bh Word8
    4
            WriteBinHandle -> ModuleName -> IO ()
    forall a. Binary a => WriteBinHandle -> a -> IO ()
    put_ WriteBinHandle
    bh (Usage -> ModuleName
    usg_mod_name Usage
    usg)
            WriteBinHandle -> UnitId -> IO ()
    forall a. Binary a => WriteBinHandle -> a -> IO ()
    put_ WriteBinHandle
    bh (Usage -> UnitId
    usg_unit_id  Usage
    usg)
            WriteBinHandle -> Fingerprint -> IO ()
    forall a. Binary a => WriteBinHandle -> a -> IO ()
    put_ WriteBinHandle
    bh (Usage -> Fingerprint
    usg_iface_hash Usage
    usg)

        get :: ReadBinHandle -> IO Usage
    get ReadBinHandle
    bh = do
            h <- ReadBinHandle -> IO Word8
    getByte ReadBinHandle
    bh
            case h of
              Word8
    0 -> do
                nm    <- ReadBinHandle -> IO Module
    forall a. Binary a => ReadBinHandle -> IO a
    get ReadBinHandle
    bh
                mod   <- get bh
                safe  <- get bh
                return UsagePackageModule { usg_mod = nm, usg_mod_hash = mod, usg_safe = safe }
              Word8
    1 -> do
                nm    <- ReadBinHandle -> IO ModuleName
    forall a. Binary a => ReadBinHandle -> IO a
    get ReadBinHandle
    bh
                uid    <- get bh
                mod   <- get bh
                exps  <- get bh
                ents  <- get bh
                safe  <- get bh
                return UsageHomeModule { usg_mod_name = nm, usg_mod_hash = mod, usg_unit_id = uid,
                         usg_exports = exps, usg_entities = ents, usg_safe = safe }
              Word8
    2 -> do
                fp   <- ReadBinHandle -> IO FastString
    forall a. Binary a => ReadBinHandle -> IO a
    get ReadBinHandle
    bh
                hash <- get bh
                label <- get bh
                return UsageFile { usg_file_path = fp, usg_file_hash = hash, usg_file_label = label }
              Word8
    3 -> do
                mod <- ReadBinHandle -> IO Module
    forall a. Binary a => ReadBinHandle -> IO a
    get ReadBinHandle
    bh
                hash <- get bh
                return UsageMergedRequirement { usg_mod = mod, usg_mod_hash = hash }
              Word8
    4 -> do
                mod <- ReadBinHandle -> IO ModuleName
    forall a. Binary a => ReadBinHandle -> IO a
    get ReadBinHandle
    bh
                uid <- get bh
                hash <- get bh
                return UsageHomeModuleInterface { usg_mod_name = mod, usg_unit_id = uid, usg_iface_hash = hash }
              Word8
    i -> String -> IO Usage
    forall a. HasCallStack => String -> a
    error (String
    "Binary.get(Usage): " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ Word8 -> String
    forall a. Show a => a -> String
    show Word8
    i)

    {-
    Note [Transitive Information in Dependencies]
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    It is important to be careful what information we put in 'Dependencies' because
    ultimately it ends up serialised in an interface file. Interface files must always
    be kept up-to-date with the state of the world, so if `Dependencies` needs to be updated
    then the module had to be recompiled just to update `Dependencies`.

    Before #16885, the dependencies used to contain the transitive closure of all
    home modules. Therefore, if you added an import somewhere low down in the home package
    it would recompile nearly every module in your project, just to update this information.

    Now, we are a bit more careful about what we store and
    explicitly store transitive information only if it is really needed.

    ~ Direct Information

    * dep_direct_mods - Directly imported home package modules
    * dep_direct_pkgs - Directly imported packages
    * dep_plgins      - Directly used plugins

    ~ Transitive Information

    Some features of the compiler require transitive information about what is currently
    being compiled, so that is explicitly stored separately in the form they need.

    * dep_trusted_pkgs - Only used for the -fpackage-trust feature
    * dep_boot_mods  - Only used to populate eps_is_boot in -c mode
    * dep_orphs        - Modules with orphan instances
    * dep_finsts       - Modules with type family instances

    Important note: If you add some transitive information to the interface file then
    you need to make sure recompilation is triggered when it could be out of date.
    The correct way to do this is to include the transitive information in the export
    hash of the module. The export hash is computed in `GHC.Iface.Recomp.addFingerprints`.
    -}

    {-
    Note [Structure of dep_boot_deps]
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    In `-c` mode we always need to know whether to load the normal or boot version of
    an interface file, and this can't be determined from just looking at the direct imports.

    Consider modules with dependencies:

    ```
    A -(S)-> B
    A -> C -> B -(S)-> B
    ```

    Say when compiling module `A` that we need to load the interface for `B`, do we load
    `B.hi` or `B.hi-boot`? Well, `A` does directly {-# SOURCE #-} import B, so you might think
    that we would load the `B.hi-boot` file, however this is wrong because `C` imports
    `B` normally. Therefore in the interface file for `C` we still need to record that
    there is a hs-boot file for `B` below it but that we now want `B.hi` rather than
    `B.hi-boot`. When `C` is imported, the fact that it needs `B.hi` clobbers the `{- SOURCE -}`
    import for `B`.

    Therefore in mod_boot_deps we store the names of any modules which have hs-boot files,
    and whether we want to import the .hi or .hi-boot version of the interface file.

    If you get this wrong, then GHC fails to compile, so there is a test but you might
    not make it that far if you get this wrong!

    Question: does this happen even across packages?
    No: if I need to load the interface for module X from package P I always look for p:X.hi.

    -}

    -- | 'ImportAvails' summarises what was imported from where, irrespective of
    -- whether the imported things are actually used or not.  It is used:
    --
    --  * when processing the export list,
    --
    --  * when constructing usage info for the interface file,
    --
    --  * to identify the list of directly imported modules for initialisation
    --    purposes and for optimised overlap checking of family instances,
    --
    --  * when figuring out what things are really unused
    --
    data ImportAvails
       = ImportAvails {
            ImportAvails -> ImportedMods
    imp_mods :: ImportedMods,
              --      = ModuleEnv [ImportedModsVal],
              -- ^ Domain is all directly-imported modules
              --
              -- See the documentation on ImportedModsVal in
              -- "GHC.Unit.Module.Imported" for the meaning of the fields.
              --
              -- We need a full ModuleEnv rather than a ModuleNameEnv here,
              -- because we might be importing modules of the same name from
              -- different packages. (currently not the case, but might be in the
              -- future).

            ImportAvails -> InstalledModuleEnv (GenWithIsBoot ModuleName)
    imp_direct_dep_mods :: InstalledModuleEnv ModuleNameWithIsBoot,
              -- ^ Home-package modules directly imported by the module being compiled.

            ImportAvails -> Set UnitId
    imp_dep_direct_pkgs :: Set UnitId,
              -- ^ Packages directly needed by the module being compiled

            ImportAvails -> Bool
    imp_trust_own_pkg :: Bool,
              -- ^ Do we require that our own package is trusted?
              -- This is to handle efficiently the case where a Safe module imports
              -- a Trustworthy module that resides in the same package as it.
              -- See Note [Trust Own Package] in "GHC.Rename.Names"

            -- Transitive information below here

            ImportAvails -> Set UnitId
    imp_trust_pkgs :: Set UnitId,
              -- ^ This records the
              -- packages the current module needs to trust for Safe Haskell
              -- compilation to succeed. A package is required to be trusted if
              -- we are dependent on a trustworthy module in that package.
              -- See Note [Tracking Trust Transitively] in "GHC.Rename.Names"

            ImportAvails -> InstalledModuleEnv (GenWithIsBoot ModuleName)
    imp_boot_mods :: InstalledModuleEnv ModuleNameWithIsBoot,
              -- ^ Domain is all modules which have hs-boot files, and whether
              -- we should import the boot version of interface file. Only used
              -- in one-shot mode to populate eps_is_boot.

            ImportAvails -> [ModuleName]
    imp_sig_mods :: [ModuleName],
              -- ^ Signature modules below this one

            ImportAvails -> [Module]
    imp_orphs :: [Module],
              -- ^ Orphan modules below us in the import tree (and maybe including
              -- us for imported modules)

            ImportAvails -> [Module]
    imp_finsts :: [Module]
              -- ^ Family instance modules below us in the import tree (and maybe
              -- including us for imported modules)
          }