-- | 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.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
  [Module]
r <- [Module] -> m [Module]
f (Dependencies -> [Module]
dep_orphs Dependencies
deps)
  Dependencies -> m Dependencies
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Dependencies
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
  [Module]
r <- [Module] -> m [Module]
f (Dependencies -> [Module]
dep_finsts Dependencies
deps)
  Dependencies -> m Dependencies
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Dependencies
deps { dep_finsts = sortBy stableModuleCmp r })


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

    get :: BinHandle -> IO Dependencies
get BinHandle
bh = do Set (UnitId, GenWithIsBoot ModuleName)
dms <- BinHandle -> IO (Set (UnitId, GenWithIsBoot ModuleName))
forall a. Binary a => BinHandle -> IO a
get BinHandle
bh
                Set UnitId
dps <- BinHandle -> IO (Set UnitId)
forall a. Binary a => BinHandle -> IO a
get BinHandle
bh
                Set UnitId
plugin_pkgs <- BinHandle -> IO (Set UnitId)
forall a. Binary a => BinHandle -> IO a
get BinHandle
bh
                Set UnitId
tps <- BinHandle -> IO (Set UnitId)
forall a. Binary a => BinHandle -> IO a
get BinHandle
bh
                [ModuleName]
hsigms <- BinHandle -> IO [ModuleName]
forall a. Binary a => BinHandle -> IO a
get BinHandle
bh
                Set (UnitId, GenWithIsBoot ModuleName)
sms <- BinHandle -> IO (Set (UnitId, GenWithIsBoot ModuleName))
forall a. Binary a => BinHandle -> IO a
get BinHandle
bh
                [Module]
os <- BinHandle -> IO [Module]
forall a. Binary a => BinHandle -> IO a
get BinHandle
bh
                [Module]
fis <- BinHandle -> IO [Module]
forall a. Binary a => BinHandle -> IO a
get BinHandle
bh
                Dependencies -> IO Dependencies
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Deps { dep_direct_mods :: Set (UnitId, GenWithIsBoot ModuleName)
dep_direct_mods = Set (UnitId, GenWithIsBoot ModuleName)
dms
                             , dep_direct_pkgs :: Set UnitId
dep_direct_pkgs = Set UnitId
dps
                             , dep_plugin_pkgs :: Set UnitId
dep_plugin_pkgs = Set UnitId
plugin_pkgs
                             , dep_sig_mods :: [ModuleName]
dep_sig_mods = [ModuleName]
hsigms
                             , dep_boot_mods :: Set (UnitId, GenWithIsBoot ModuleName)
dep_boot_mods = Set (UnitId, GenWithIsBoot ModuleName)
sms
                             , dep_trusted_pkgs :: Set UnitId
dep_trusted_pkgs = Set UnitId
tps
                             , dep_orphs :: [Module]
dep_orphs = [Module]
os,
                               dep_finsts :: [Module]
dep_finsts = [Module]
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
        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 -> String
usg_file_path  :: FilePath,
        -- ^ 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
        , 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_ :: BinHandle -> Usage -> IO ()
put_ BinHandle
bh usg :: Usage
usg@UsagePackageModule{} = do
        BinHandle -> Word8 -> IO ()
putByte BinHandle
bh Word8
0
        BinHandle -> Module -> IO ()
forall a. Binary a => BinHandle -> a -> IO ()
put_ BinHandle
bh (Usage -> Module
usg_mod Usage
usg)
        BinHandle -> Fingerprint -> IO ()
forall a. Binary a => BinHandle -> a -> IO ()
put_ BinHandle
bh (Usage -> Fingerprint
usg_mod_hash Usage
usg)
        BinHandle -> Bool -> IO ()
forall a. Binary a => BinHandle -> a -> IO ()
put_ BinHandle
bh (Usage -> Bool
usg_safe     Usage
usg)

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

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

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

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

    get :: BinHandle -> IO Usage
get BinHandle
bh = do
        Word8
h <- BinHandle -> IO Word8
getByte BinHandle
bh
        case Word8
h of
          Word8
0 -> do
            Module
nm    <- BinHandle -> IO Module
forall a. Binary a => BinHandle -> IO a
get BinHandle
bh
            Fingerprint
mod   <- BinHandle -> IO Fingerprint
forall a. Binary a => BinHandle -> IO a
get BinHandle
bh
            Bool
safe  <- BinHandle -> IO Bool
forall a. Binary a => BinHandle -> IO a
get BinHandle
bh
            Usage -> IO Usage
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return UsagePackageModule { usg_mod :: Module
usg_mod = Module
nm, usg_mod_hash :: Fingerprint
usg_mod_hash = Fingerprint
mod, usg_safe :: Bool
usg_safe = Bool
safe }
          Word8
1 -> do
            ModuleName
nm    <- BinHandle -> IO ModuleName
forall a. Binary a => BinHandle -> IO a
get BinHandle
bh
            Fingerprint
mod   <- BinHandle -> IO Fingerprint
forall a. Binary a => BinHandle -> IO a
get BinHandle
bh
            Maybe Fingerprint
exps  <- BinHandle -> IO (Maybe Fingerprint)
forall a. Binary a => BinHandle -> IO a
get BinHandle
bh
            [(OccName, Fingerprint)]
ents  <- BinHandle -> IO [(OccName, Fingerprint)]
forall a. Binary a => BinHandle -> IO a
get BinHandle
bh
            Bool
safe  <- BinHandle -> IO Bool
forall a. Binary a => BinHandle -> IO a
get BinHandle
bh
            Usage -> IO Usage
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return UsageHomeModule { usg_mod_name :: ModuleName
usg_mod_name = ModuleName
nm, usg_mod_hash :: Fingerprint
usg_mod_hash = Fingerprint
mod,
                     usg_exports :: Maybe Fingerprint
usg_exports = Maybe Fingerprint
exps, usg_entities :: [(OccName, Fingerprint)]
usg_entities = [(OccName, Fingerprint)]
ents, usg_safe :: Bool
usg_safe = Bool
safe }
          Word8
2 -> do
            String
fp   <- BinHandle -> IO String
forall a. Binary a => BinHandle -> IO a
get BinHandle
bh
            Fingerprint
hash <- BinHandle -> IO Fingerprint
forall a. Binary a => BinHandle -> IO a
get BinHandle
bh
            Maybe String
label <- BinHandle -> IO (Maybe String)
forall a. Binary a => BinHandle -> IO a
get BinHandle
bh
            Usage -> IO Usage
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return UsageFile { usg_file_path :: String
usg_file_path = String
fp, usg_file_hash :: Fingerprint
usg_file_hash = Fingerprint
hash, usg_file_label :: Maybe String
usg_file_label = Maybe String
label }
          Word8
3 -> do
            Module
mod <- BinHandle -> IO Module
forall a. Binary a => BinHandle -> IO a
get BinHandle
bh
            Fingerprint
hash <- BinHandle -> IO Fingerprint
forall a. Binary a => BinHandle -> IO a
get BinHandle
bh
            Usage -> IO Usage
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return UsageMergedRequirement { usg_mod :: Module
usg_mod = Module
mod, usg_mod_hash :: Fingerprint
usg_mod_hash = Fingerprint
hash }
          Word8
4 -> do
            ModuleName
mod <- BinHandle -> IO ModuleName
forall a. Binary a => BinHandle -> IO a
get BinHandle
bh
            Fingerprint
hash <- BinHandle -> IO Fingerprint
forall a. Binary a => BinHandle -> IO a
get BinHandle
bh
            Usage -> IO Usage
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return UsageHomeModuleInterface { usg_mod_name :: ModuleName
usg_mod_name = ModuleName
mod, usg_iface_hash :: Fingerprint
usg_iface_hash = Fingerprint
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)
      }