    {-# LANGUAGE DeriveFunctor #-}
    {-# LANGUAGE MultiWayIf #-}
    {-# LANGUAGE TupleSections #-}
    {-# LANGUAGE LambdaCase #-}

    -- | Module for detecting if recompilation is required
    module GHC.Iface.Recomp
       ( checkOldIface
       , RecompileRequired(..)
       , needsRecompileBecause
       , recompThen
       , MaybeValidated(..)
       , outOfDateItemBecause
       , RecompReason (..)
       , CompileReason(..)
       , recompileRequired
       , addFingerprints
       )
    where

    import GHC.Prelude
    import GHC.Data.FastString

    import GHC.Driver.Backend
    import GHC.Driver.Config.Finder
    import GHC.Driver.Env
    import GHC.Driver.DynFlags
    import GHC.Driver.Ppr
    import GHC.Driver.Plugins

    import GHC.Iface.Syntax
    import GHC.Iface.Recomp.Binary
    import GHC.Iface.Load
    import GHC.Iface.Recomp.Flags
    import GHC.Iface.Env

    import GHC.Core
    import GHC.Tc.Utils.Monad
    import GHC.Hs

    import GHC.Data.Graph.Directed
    import GHC.Data.Maybe

    import GHC.Utils.Error
    import GHC.Utils.Panic
    import GHC.Utils.Outputable as Outputable
    import GHC.Utils.Misc as Utils
    import GHC.Utils.Binary
    import GHC.Utils.Fingerprint
    import GHC.Utils.Exception
    import GHC.Utils.Logger
    import GHC.Utils.Constants (debugIsOn)

    import GHC.Types.Annotations
    import GHC.Types.Name
    import GHC.Types.Name.Set
    import GHC.Types.SrcLoc
    import GHC.Types.Unique.Set
    import GHC.Types.Fixity.Env
    import GHC.Types.Unique.Map
    import GHC.Unit.External
    import GHC.Unit.Finder
    import GHC.Unit.State
    import GHC.Unit.Home
    import GHC.Unit.Module
    import GHC.Unit.Module.ModIface
    import GHC.Unit.Module.ModSummary
    import GHC.Unit.Module.Warnings
    import GHC.Unit.Module.Deps

    import Control.Monad
    import Data.List (sortBy, sort, sortOn)
    import qualified Data.Map as Map
    import qualified Data.Set as Set
    import Data.Word (Word64)
    import Data.Either

    --Qualified import so we can define a Semigroup instance
    -- but it doesn't clash with Outputable.<>
    import qualified Data.Semigroup
    import GHC.List (uncons)
    import Data.Ord
    import Data.Containers.ListUtils
    import Data.Bifunctor
    import GHC.Iface.Errors.Ppr

    {-
      -----------------------------------------------
              Recompilation checking
      -----------------------------------------------

    A complete description of how recompilation checking works can be
    found in the wiki commentary:

     https://gitlab.haskell.org/ghc/ghc/wikis/commentary/compiler/recompilation-avoidance

    Please read the above page for a top-down description of how this all
    works.  Notes below cover specific issues related to the implementation.

    Basic idea:

      * In the mi_usages information in an interface, we record the
        fingerprint of each free variable of the module

      * In mkIface, we compute the fingerprint of each exported thing A.f.
        For each external thing that A.f refers to, we include the fingerprint
        of the external reference when computing the fingerprint of A.f.  So
        if anything that A.f depends on changes, then A.f's fingerprint will
        change.
        Also record any dependent files added with
          * addDependentFile
          * #include
          * -optP-include

      * In checkOldIface we compare the mi_usages for the module with
        the actual fingerprint for all each thing recorded in mi_usages
    -}

    data RecompileRequired
      -- | everything is up to date, recompilation is not required
      = UpToDate
      -- | Need to compile the module
      | NeedsRecompile !CompileReason
       deriving (RecompileRequired -> RecompileRequired -> AnyHpcUsage
    (RecompileRequired -> RecompileRequired -> AnyHpcUsage)
    -> (RecompileRequired -> RecompileRequired -> AnyHpcUsage)
    -> Eq RecompileRequired
    forall a.
    (a -> a -> AnyHpcUsage) -> (a -> a -> AnyHpcUsage) -> Eq a
    $c== :: RecompileRequired -> RecompileRequired -> AnyHpcUsage
    == :: RecompileRequired -> RecompileRequired -> AnyHpcUsage
    $c/= :: RecompileRequired -> RecompileRequired -> AnyHpcUsage
    /= :: RecompileRequired -> RecompileRequired -> AnyHpcUsage
    Eq)

    needsRecompileBecause :: RecompReason -> RecompileRequired
    needsRecompileBecause :: RecompReason -> RecompileRequired
    needsRecompileBecause = CompileReason -> RecompileRequired
    NeedsRecompile (CompileReason -> RecompileRequired)
    -> (RecompReason -> CompileReason)
    -> RecompReason
    -> RecompileRequired
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . RecompReason -> CompileReason
    RecompBecause

    data MaybeValidated a
      -- | The item contained is validated to be up to date
      = UpToDateItem a
      -- | The item is are absent altogether or out of date, for the reason given.
      | OutOfDateItem
          !CompileReason
          -- ^ the reason we need to recompile.
          (Maybe a)
          -- ^ The old item, if it exists
      deriving ((forall a b. (a -> b) -> MaybeValidated a -> MaybeValidated b)
    -> (forall a b. a -> MaybeValidated b -> MaybeValidated a)
    -> Functor MaybeValidated
    forall a b. a -> MaybeValidated b -> MaybeValidated a
    forall a b. (a -> b) -> MaybeValidated a -> MaybeValidated b
    forall (f :: * -> *).
    (forall a b. (a -> b) -> f a -> f b)
    -> (forall a b. a -> f b -> f a) -> Functor f
    $cfmap :: forall a b. (a -> b) -> MaybeValidated a -> MaybeValidated b
    fmap :: forall a b. (a -> b) -> MaybeValidated a -> MaybeValidated b
    $c<$ :: forall a b. a -> MaybeValidated b -> MaybeValidated a
    <$ :: forall a b. a -> MaybeValidated b -> MaybeValidated a
    Functor)

    instance Outputable a => Outputable (MaybeValidated a) where
      ppr :: MaybeValidated a -> SDoc
    ppr (UpToDateItem a
    a) = String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "UpToDate" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> a -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr a
    a
      ppr (OutOfDateItem CompileReason
    r Maybe a
    _) = String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "OutOfDate: " SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> CompileReason -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr CompileReason
    r

    outOfDateItemBecause :: RecompReason -> Maybe a -> MaybeValidated a
    outOfDateItemBecause :: forall a. RecompReason -> Maybe a -> MaybeValidated a
    outOfDateItemBecause RecompReason
    reason Maybe a
    item = CompileReason -> Maybe a -> MaybeValidated a
    forall a. CompileReason -> Maybe a -> MaybeValidated a
    OutOfDateItem (RecompReason -> CompileReason
    RecompBecause RecompReason
    reason) Maybe a
    item

    data CompileReason
      -- | The .hs file has been touched, or the .o/.hi file does not exist
      = MustCompile
      -- | The .o/.hi files are up to date, but something else has changed
      -- to force recompilation; the String says what (one-line summary)
      | RecompBecause !RecompReason
       deriving (CompileReason -> CompileReason -> AnyHpcUsage
    (CompileReason -> CompileReason -> AnyHpcUsage)
    -> (CompileReason -> CompileReason -> AnyHpcUsage)
    -> Eq CompileReason
    forall a.
    (a -> a -> AnyHpcUsage) -> (a -> a -> AnyHpcUsage) -> Eq a
    $c== :: CompileReason -> CompileReason -> AnyHpcUsage
    == :: CompileReason -> CompileReason -> AnyHpcUsage
    $c/= :: CompileReason -> CompileReason -> AnyHpcUsage
    /= :: CompileReason -> CompileReason -> AnyHpcUsage
    Eq)

    instance Outputable RecompileRequired where
      ppr :: RecompileRequired -> SDoc
    ppr RecompileRequired
    UpToDate = String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "UpToDate"
      ppr (NeedsRecompile CompileReason
    reason) = CompileReason -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr CompileReason
    reason

    instance Outputable CompileReason where
      ppr :: CompileReason -> SDoc
    ppr CompileReason
    MustCompile = String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "MustCompile"
      ppr (RecompBecause RecompReason
    r) = String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "RecompBecause" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> RecompReason -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr RecompReason
    r

    instance Semigroup RecompileRequired where
      RecompileRequired
    UpToDate <> :: RecompileRequired -> RecompileRequired -> RecompileRequired
    <> RecompileRequired
    r = RecompileRequired
    r
      RecompileRequired
    mc <> RecompileRequired
    _       = RecompileRequired
    mc

    instance Monoid RecompileRequired where
      mempty :: RecompileRequired
    mempty = RecompileRequired
    UpToDate

    data RecompReason
      = UnitDepRemoved UnitId
      | ModulePackageChanged FastString
      | SourceFileChanged
      | ThisUnitIdChanged
      | ImpurePlugin
      | PluginsChanged
      | PluginFingerprintChanged
      | ModuleInstChanged
      | HieMissing
      | HieOutdated
      | SigsMergeChanged
      | ModuleChanged ModuleName
      | ModuleRemoved (UnitId, ModuleName)
      | ModuleAdded (UnitId, ModuleName)
      | ModuleChangedRaw ModuleName
      | ModuleChangedIface ModuleName
      | FileChanged FilePath
      | CustomReason String
      | FlagsChanged
      | OptimFlagsChanged
      | HpcFlagsChanged
      | MissingBytecode
      | MissingObjectFile
      | MissingDynObjectFile
      | MissingDynHiFile
      | MismatchedDynHiFile
      | ObjectsChanged
      | LibraryChanged
      | THWithJS
      deriving (RecompReason -> RecompReason -> AnyHpcUsage
    (RecompReason -> RecompReason -> AnyHpcUsage)
    -> (RecompReason -> RecompReason -> AnyHpcUsage) -> Eq RecompReason
    forall a.
    (a -> a -> AnyHpcUsage) -> (a -> a -> AnyHpcUsage) -> Eq a
    $c== :: RecompReason -> RecompReason -> AnyHpcUsage
    == :: RecompReason -> RecompReason -> AnyHpcUsage
    $c/= :: RecompReason -> RecompReason -> AnyHpcUsage
    /= :: RecompReason -> RecompReason -> AnyHpcUsage
    Eq)

    instance Outputable RecompReason where
      ppr :: RecompReason -> SDoc
    ppr = \case
        UnitDepRemoved UnitId
    uid       -> UnitId -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr UnitId
    uid SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "removed"
        ModulePackageChanged FastString
    s   -> FastString -> SDoc
    forall doc. IsLine doc => FastString -> doc
    ftext FastString
    s SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "package changed"
        RecompReason
    SourceFileChanged        -> String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "Source file changed"
        RecompReason
    ThisUnitIdChanged        -> String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "-this-unit-id changed"
        RecompReason
    ImpurePlugin             -> String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "Impure plugin forced recompilation"
        RecompReason
    PluginsChanged           -> String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "Plugins changed"
        RecompReason
    PluginFingerprintChanged -> String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "Plugin fingerprint changed"
        RecompReason
    ModuleInstChanged        -> String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "Implementing module changed"
        RecompReason
    HieMissing               -> String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "HIE file is missing"
        RecompReason
    HieOutdated              -> String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "HIE file is out of date"
        RecompReason
    SigsMergeChanged         -> String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "Signatures to merge in changed"
        ModuleChanged ModuleName
    m          -> ModuleName -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr ModuleName
    m SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "changed"
        ModuleChangedRaw ModuleName
    m       -> ModuleName -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr ModuleName
    m SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "changed (raw)"
        ModuleChangedIface ModuleName
    m     -> ModuleName -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr ModuleName
    m SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "changed (interface)"
        ModuleRemoved (UnitId
    _uid, ModuleName
    m)   -> ModuleName -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr ModuleName
    m SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "removed"
        ModuleAdded (UnitId
    _uid, ModuleName
    m)     -> ModuleName -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr ModuleName
    m SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "added"
        FileChanged String
    fp           -> String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    fp SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "changed"
        CustomReason String
    s           -> String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    s
        RecompReason
    FlagsChanged             -> String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "Flags changed"
        RecompReason
    OptimFlagsChanged        -> String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "Optimisation flags changed"
        RecompReason
    HpcFlagsChanged          -> String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "HPC flags changed"
        RecompReason
    MissingBytecode          -> String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "Missing bytecode"
        RecompReason
    MissingObjectFile        -> String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "Missing object file"
        RecompReason
    MissingDynObjectFile     -> String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "Missing dynamic object file"
        RecompReason
    MissingDynHiFile         -> String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "Missing dynamic interface file"
        RecompReason
    MismatchedDynHiFile     -> String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "Mismatched dynamic interface file"
        RecompReason
    ObjectsChanged          -> String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "Objects changed"
        RecompReason
    LibraryChanged          -> String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "Library changed"
        RecompReason
    THWithJS                -> String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "JS backend always recompiles modules using Template Haskell for now (#23013)"

    recompileRequired :: RecompileRequired -> Bool
    recompileRequired :: RecompileRequired -> AnyHpcUsage
    recompileRequired RecompileRequired
    UpToDate = AnyHpcUsage
    False
    recompileRequired RecompileRequired
    _ = AnyHpcUsage
    True

    recompThen :: Monad m => m RecompileRequired -> m RecompileRequired -> m RecompileRequired
    recompThen :: forall (m :: * -> *).
    Monad m =>
    m RecompileRequired -> m RecompileRequired -> m RecompileRequired
    recompThen m RecompileRequired
    ma m RecompileRequired
    mb = m RecompileRequired
    ma m RecompileRequired
    -> (RecompileRequired -> m RecompileRequired)
    -> m RecompileRequired
    forall a b. m a -> (a -> m b) -> m b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= \case
      RecompileRequired
    UpToDate              -> m RecompileRequired
    mb
      rr :: RecompileRequired
    rr@(NeedsRecompile CompileReason
    _) -> RecompileRequired -> m RecompileRequired
    forall a. a -> m a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure RecompileRequired
    rr

    checkList :: Monad m => [m RecompileRequired] -> m RecompileRequired
    checkList :: forall (m :: * -> *).
    Monad m =>
    [m RecompileRequired] -> m RecompileRequired
    checkList = \case
      []               -> RecompileRequired -> m RecompileRequired
    forall a. a -> m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return RecompileRequired
    UpToDate
      (m RecompileRequired
    check : [m RecompileRequired]
    checks) -> m RecompileRequired
    check m RecompileRequired -> m RecompileRequired -> m RecompileRequired
    forall (m :: * -> *).
    Monad m =>
    m RecompileRequired -> m RecompileRequired -> m RecompileRequired
    `recompThen` [m RecompileRequired] -> m RecompileRequired
    forall (m :: * -> *).
    Monad m =>
    [m RecompileRequired] -> m RecompileRequired
    checkList [m RecompileRequired]
    checks

    ----------------------

    -- | Top level function to check if the version of an old interface file
    -- is equivalent to the current source file the user asked us to compile.
    -- If the same, we can avoid recompilation.
    --
    -- We return on the outside whether the interface file is up to date, providing
    -- evidence that is with a `ModIface`. In the case that it isn't, we may also
    -- return a found or provided `ModIface`. Why we don't always return the old
    -- one, if it exists, is unclear to me, except that I tried it and some tests
    -- failed (see #18205).
    checkOldIface
      :: HscEnv
      -> ModSummary
      -> Maybe ModIface         -- Old interface from compilation manager, if any
      -> IO (MaybeValidated ModIface)

    checkOldIface :: HscEnv
    -> ModSummary -> Maybe ModIface -> IO (MaybeValidated ModIface)
    checkOldIface HscEnv
    hsc_env ModSummary
    mod_summary Maybe ModIface
    maybe_iface
      = do  let dflags :: DynFlags
    dflags = HscEnv -> DynFlags
    hsc_dflags HscEnv
    hsc_env
            let logger :: Logger
    logger = HscEnv -> Logger
    hsc_logger HscEnv
    hsc_env
            Logger -> String -> IO ()
    showPass Logger
    logger (String -> IO ()) -> String -> IO ()
    forall a b. (a -> b) -> a -> b
    $
                String
    "Checking old interface for " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++
                  (DynFlags -> Module -> String
    forall a. Outputable a => DynFlags -> a -> String
    showPpr DynFlags
    dflags (Module -> String) -> Module -> String
    forall a b. (a -> b) -> a -> b
    $ ModSummary -> Module
    ms_mod ModSummary
    mod_summary) String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++
                  String
    " (use -ddump-hi-diffs for more details)"
            SDoc
    -> HscEnv
    -> IfG (MaybeValidated ModIface)
    -> IO (MaybeValidated ModIface)
    forall a. SDoc -> HscEnv -> IfG a -> IO a
    initIfaceCheck (String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "checkOldIface") HscEnv
    hsc_env (IfG (MaybeValidated ModIface) -> IO (MaybeValidated ModIface))
    -> IfG (MaybeValidated ModIface) -> IO (MaybeValidated ModIface)
    forall a b. (a -> b) -> a -> b
    $
                HscEnv
    -> ModSummary -> Maybe ModIface -> IfG (MaybeValidated ModIface)
    check_old_iface HscEnv
    hsc_env ModSummary
    mod_summary Maybe ModIface
    maybe_iface

    check_old_iface
      :: HscEnv
      -> ModSummary
      -> Maybe ModIface
      -> IfG (MaybeValidated ModIface)

    check_old_iface :: HscEnv
    -> ModSummary -> Maybe ModIface -> IfG (MaybeValidated ModIface)
    check_old_iface HscEnv
    hsc_env ModSummary
    mod_summary Maybe ModIface
    maybe_iface
      = let dflags :: DynFlags
    dflags = HscEnv -> DynFlags
    hsc_dflags HscEnv
    hsc_env
            logger :: Logger
    logger = HscEnv -> Logger
    hsc_logger HscEnv
    hsc_env
            getIface :: IO (Maybe ModIface)
    getIface =
                case Maybe ModIface
    maybe_iface of
                    Just ModIface
    _  -> do
                        Logger -> SDoc -> IO ()
    trace_if Logger
    logger (String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "We already have the old interface for" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+>
                          Module -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr (ModSummary -> Module
    ms_mod ModSummary
    mod_summary))
                        Maybe ModIface -> IO (Maybe ModIface)
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Maybe ModIface
    maybe_iface
                    Maybe ModIface
    Nothing -> DynFlags -> String -> IO (Maybe ModIface)
    loadIface DynFlags
    dflags (ModSummary -> String
    msHiFilePath ModSummary
    mod_summary)

            loadIface :: DynFlags -> String -> IO (Maybe ModIface)
    loadIface DynFlags
    read_dflags String
    iface_path = do
                 let ncu :: NameCache
    ncu        = HscEnv -> NameCache
    hsc_NC HscEnv
    hsc_env
                 read_result <- DynFlags
    -> NameCache
    -> Module
    -> String
    -> IO (MaybeErr ReadInterfaceError ModIface)
    readIface DynFlags
    read_dflags NameCache
    ncu (ModSummary -> Module
    ms_mod ModSummary
    mod_summary) String
    iface_path
                 case read_result of
                     Failed ReadInterfaceError
    err -> do
                         let msg :: SDoc
    msg = ReadInterfaceError -> SDoc
    readInterfaceErrorDiagnostic ReadInterfaceError
    err
                         Logger -> SDoc -> IO ()
    trace_if Logger
    logger
                           (SDoc -> IO ()) -> SDoc -> IO ()
    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
    "FYI: cannot read old interface file:"
                                  , Int -> SDoc -> SDoc
    nest Int
    4 SDoc
    msg ]
                         Logger -> SDoc -> IO ()
    trace_hi_diffs Logger
    logger (SDoc -> IO ()) -> SDoc -> IO ()
    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
    "Old interface file was invalid:"
                                , Int -> SDoc -> SDoc
    nest Int
    4 SDoc
    msg ]
                         Maybe ModIface -> IO (Maybe ModIface)
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Maybe ModIface
    forall a. Maybe a
    Nothing
                     Succeeded ModIface
    iface -> do
                         Logger -> SDoc -> IO ()
    trace_if Logger
    logger (String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "Read the interface file" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    iface_path)
                         Maybe ModIface -> IO (Maybe ModIface)
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Maybe ModIface -> IO (Maybe ModIface))
    -> Maybe ModIface -> IO (Maybe ModIface)
    forall a b. (a -> b) -> a -> b
    $ ModIface -> Maybe ModIface
    forall a. a -> Maybe a
    Just ModIface
    iface
            check_dyn_hi :: ModIface
                      -> IfG (MaybeValidated ModIface)
                      -> IfG (MaybeValidated ModIface)
            check_dyn_hi :: ModIface
    -> IfG (MaybeValidated ModIface) -> IfG (MaybeValidated ModIface)
    check_dyn_hi ModIface
    normal_iface IfG (MaybeValidated ModIface)
    recomp_check | GeneralFlag -> DynFlags -> AnyHpcUsage
    gopt GeneralFlag
    Opt_BuildDynamicToo DynFlags
    dflags = do
              res <- IfG (MaybeValidated ModIface)
    recomp_check
              case res of
                UpToDateItem ModIface
    _ -> do
                  maybe_dyn_iface <- IO (Maybe ModIface) -> IOEnv (Env IfGblEnv ()) (Maybe ModIface)
    forall a. IO a -> IOEnv (Env IfGblEnv ()) a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO (Maybe ModIface) -> IOEnv (Env IfGblEnv ()) (Maybe ModIface))
    -> IO (Maybe ModIface) -> IOEnv (Env IfGblEnv ()) (Maybe ModIface)
    forall a b. (a -> b) -> a -> b
    $ DynFlags -> String -> IO (Maybe ModIface)
    loadIface (DynFlags -> DynFlags
    setDynamicNow DynFlags
    dflags) (ModSummary -> String
    msDynHiFilePath ModSummary
    mod_summary)
                  case maybe_dyn_iface of
                    Maybe ModIface
    Nothing -> MaybeValidated ModIface -> IfG (MaybeValidated ModIface)
    forall a. a -> IOEnv (Env IfGblEnv ()) a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (MaybeValidated ModIface -> IfG (MaybeValidated ModIface))
    -> MaybeValidated ModIface -> IfG (MaybeValidated ModIface)
    forall a b. (a -> b) -> a -> b
    $ RecompReason -> Maybe ModIface -> MaybeValidated ModIface
    forall a. RecompReason -> Maybe a -> MaybeValidated a
    outOfDateItemBecause RecompReason
    MissingDynHiFile Maybe ModIface
    forall a. Maybe a
    Nothing
                    Just ModIface
    dyn_iface | ModIfaceBackend -> Fingerprint
    mi_iface_hash (ModIface -> IfaceBackendExts 'ModIfaceFinal
    forall (phase :: ModIfacePhase).
    ModIface_ phase -> IfaceBackendExts phase
    mi_final_exts ModIface
    dyn_iface)
                                        Fingerprint -> Fingerprint -> AnyHpcUsage
    forall a. Eq a => a -> a -> AnyHpcUsage
    /= ModIfaceBackend -> Fingerprint
    mi_iface_hash (ModIface -> IfaceBackendExts 'ModIfaceFinal
    forall (phase :: ModIfacePhase).
    ModIface_ phase -> IfaceBackendExts phase
    mi_final_exts ModIface
    normal_iface)
                      -> MaybeValidated ModIface -> IfG (MaybeValidated ModIface)
    forall a. a -> IOEnv (Env IfGblEnv ()) a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (MaybeValidated ModIface -> IfG (MaybeValidated ModIface))
    -> MaybeValidated ModIface -> IfG (MaybeValidated ModIface)
    forall a b. (a -> b) -> a -> b
    $ RecompReason -> Maybe ModIface -> MaybeValidated ModIface
    forall a. RecompReason -> Maybe a -> MaybeValidated a
    outOfDateItemBecause RecompReason
    MismatchedDynHiFile Maybe ModIface
    forall a. Maybe a
    Nothing
                    Just {} -> MaybeValidated ModIface -> IfG (MaybeValidated ModIface)
    forall a. a -> IOEnv (Env IfGblEnv ()) a
    forall (m :: * -> *) a. Monad m => a -> m a
    return MaybeValidated ModIface
    res
                MaybeValidated ModIface
    _ -> MaybeValidated ModIface -> IfG (MaybeValidated ModIface)
    forall a. a -> IOEnv (Env IfGblEnv ()) a
    forall (m :: * -> *) a. Monad m => a -> m a
    return MaybeValidated ModIface
    res
            check_dyn_hi ModIface
    _ IfG (MaybeValidated ModIface)
    recomp_check = IfG (MaybeValidated ModIface)
    recomp_check

            src_changed :: AnyHpcUsage
    src_changed
                | GeneralFlag -> DynFlags -> AnyHpcUsage
    gopt GeneralFlag
    Opt_ForceRecomp DynFlags
    dflags    = AnyHpcUsage
    True
                | AnyHpcUsage
    otherwise = AnyHpcUsage
    False
        in do
            AnyHpcUsage
    -> IOEnv (Env IfGblEnv ()) () -> IOEnv (Env IfGblEnv ()) ()
    forall (f :: * -> *). Applicative f => AnyHpcUsage -> f () -> f ()
    when AnyHpcUsage
    src_changed (IOEnv (Env IfGblEnv ()) () -> IOEnv (Env IfGblEnv ()) ())
    -> IOEnv (Env IfGblEnv ()) () -> IOEnv (Env IfGblEnv ()) ()
    forall a b. (a -> b) -> a -> b
    $
                IO () -> IOEnv (Env IfGblEnv ()) ()
    forall a. IO a -> IOEnv (Env IfGblEnv ()) a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> IOEnv (Env IfGblEnv ()) ())
    -> IO () -> IOEnv (Env IfGblEnv ()) ()
    forall a b. (a -> b) -> a -> b
    $ Logger -> SDoc -> IO ()
    trace_hi_diffs Logger
    logger (Int -> SDoc -> SDoc
    nest Int
    4 (SDoc -> SDoc) -> SDoc -> SDoc
    forall a b. (a -> b) -> a -> b
    $ String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "Recompilation check turned off")

            case AnyHpcUsage
    src_changed of
                -- If the source has changed and we're in interactive mode,
                -- avoid reading an interface; just return the one we might
                -- have been supplied with.
                AnyHpcUsage
    True | AnyHpcUsage -> AnyHpcUsage
    not (Backend -> AnyHpcUsage
    backendWritesFiles (Backend -> AnyHpcUsage) -> Backend -> AnyHpcUsage
    forall a b. (a -> b) -> a -> b
    $ DynFlags -> Backend
    backend DynFlags
    dflags) ->
                    MaybeValidated ModIface -> IfG (MaybeValidated ModIface)
    forall a. a -> IOEnv (Env IfGblEnv ()) a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (MaybeValidated ModIface -> IfG (MaybeValidated ModIface))
    -> MaybeValidated ModIface -> IfG (MaybeValidated ModIface)
    forall a b. (a -> b) -> a -> b
    $ CompileReason -> Maybe ModIface -> MaybeValidated ModIface
    forall a. CompileReason -> Maybe a -> MaybeValidated a
    OutOfDateItem CompileReason
    MustCompile Maybe ModIface
    maybe_iface

                -- Try and read the old interface for the current module
                -- from the .hi file left from the last time we compiled it
                AnyHpcUsage
    True -> do
                    maybe_iface' <- IO (Maybe ModIface) -> IOEnv (Env IfGblEnv ()) (Maybe ModIface)
    forall a. IO a -> IOEnv (Env IfGblEnv ()) a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO (Maybe ModIface) -> IOEnv (Env IfGblEnv ()) (Maybe ModIface))
    -> IO (Maybe ModIface) -> IOEnv (Env IfGblEnv ()) (Maybe ModIface)
    forall a b. (a -> b) -> a -> b
    $ IO (Maybe ModIface)
    getIface
                    return $ OutOfDateItem MustCompile maybe_iface'

                AnyHpcUsage
    False -> do
                    maybe_iface' <- IO (Maybe ModIface) -> IOEnv (Env IfGblEnv ()) (Maybe ModIface)
    forall a. IO a -> IOEnv (Env IfGblEnv ()) a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO (Maybe ModIface) -> IOEnv (Env IfGblEnv ()) (Maybe ModIface))
    -> IO (Maybe ModIface) -> IOEnv (Env IfGblEnv ()) (Maybe ModIface)
    forall a b. (a -> b) -> a -> b
    $ IO (Maybe ModIface)
    getIface
                    case maybe_iface' of
                        -- We can't retrieve the iface
                        Maybe ModIface
    Nothing    -> MaybeValidated ModIface -> IfG (MaybeValidated ModIface)
    forall a. a -> IOEnv (Env IfGblEnv ()) a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (MaybeValidated ModIface -> IfG (MaybeValidated ModIface))
    -> MaybeValidated ModIface -> IfG (MaybeValidated ModIface)
    forall a b. (a -> b) -> a -> b
    $ CompileReason -> Maybe ModIface -> MaybeValidated ModIface
    forall a. CompileReason -> Maybe a -> MaybeValidated a
    OutOfDateItem CompileReason
    MustCompile Maybe ModIface
    forall a. Maybe a
    Nothing

                        -- We have got the old iface; check its versions
                        -- even in the SourceUnmodifiedAndStable case we
                        -- should check versions because some packages
                        -- might have changed or gone away.
                        Just ModIface
    iface ->
                          ModIface
    -> IfG (MaybeValidated ModIface) -> IfG (MaybeValidated ModIface)
    check_dyn_hi ModIface
    iface (IfG (MaybeValidated ModIface) -> IfG (MaybeValidated ModIface))
    -> IfG (MaybeValidated ModIface) -> IfG (MaybeValidated ModIface)
    forall a b. (a -> b) -> a -> b
    $ HscEnv -> ModSummary -> ModIface -> IfG (MaybeValidated ModIface)
    checkVersions HscEnv
    hsc_env ModSummary
    mod_summary ModIface
    iface

    -- | Check if a module is still the same 'version'.
    --
    -- This function is called in the recompilation checker after we have
    -- determined that the module M being checked hasn't had any changes
    -- to its source file since we last compiled M. So at this point in general
    -- two things may have changed that mean we should recompile M:
    --   * The interface export by a dependency of M has changed.
    --   * The compiler flags specified this time for M have changed
    --     in a manner that is significant for recompilation.
    -- We return not just if we should recompile the object file but also
    -- if we should rebuild the interface file.
    checkVersions :: HscEnv
                  -> ModSummary
                  -> ModIface       -- Old interface
                  -> IfG (MaybeValidated ModIface)
    checkVersions :: HscEnv -> ModSummary -> ModIface -> IfG (MaybeValidated ModIface)
    checkVersions HscEnv
    hsc_env ModSummary
    mod_summary ModIface
    iface
      = do { IO () -> IOEnv (Env IfGblEnv ()) ()
    forall a. IO a -> IOEnv (Env IfGblEnv ()) a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> IOEnv (Env IfGblEnv ()) ())
    -> IO () -> IOEnv (Env IfGblEnv ()) ()
    forall a b. (a -> b) -> a -> b
    $ Logger -> SDoc -> IO ()
    trace_hi_diffs Logger
    logger
                            (String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "Considering whether compilation is required for" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+>
                            Module -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr (ModIface -> Module
    forall (phase :: ModIfacePhase). ModIface_ phase -> Module
    mi_module ModIface
    iface) SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <> SDoc
    forall doc. IsLine doc => doc
    colon)

           -- readIface will have verified that the UnitId matches,
           -- but we ALSO must make sure the instantiation matches up.  See
           -- test case bkpcabal04!
           ; hsc_env <- TcRnIf IfGblEnv () HscEnv
    forall gbl lcl. TcRnIf gbl lcl HscEnv
    getTopEnv
           ; if mi_src_hash iface /= ms_hs_hash mod_summary
                then return $ outOfDateItemBecause SourceFileChanged Nothing else do {
           ; if not (isHomeModule home_unit (mi_module iface))
                then return $ outOfDateItemBecause ThisUnitIdChanged Nothing else do {
           ; recomp <- liftIO $ checkFlagHash hsc_env iface
                                 `recompThen` checkOptimHash hsc_env iface
                                 `recompThen` checkHpcHash hsc_env iface
                                 `recompThen` checkMergedSignatures hsc_env mod_summary iface
                                 `recompThen` checkHsig logger home_unit mod_summary iface
                                 `recompThen` pure (checkHie dflags mod_summary)
           ; case recomp of (NeedsRecompile CompileReason
    reason) -> MaybeValidated ModIface -> IfG (MaybeValidated ModIface)
    forall a. a -> IOEnv (Env IfGblEnv ()) a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (MaybeValidated ModIface -> IfG (MaybeValidated ModIface))
    -> MaybeValidated ModIface -> IfG (MaybeValidated ModIface)
    forall a b. (a -> b) -> a -> b
    $ CompileReason -> Maybe ModIface -> MaybeValidated ModIface
    forall a. CompileReason -> Maybe a -> MaybeValidated a
    OutOfDateItem CompileReason
    reason Maybe ModIface
    forall a. Maybe a
    Nothing ; RecompileRequired
    _ -> do {
           ; recomp <- HscEnv
    -> ModSummary
    -> ModIface
    -> IOEnv (Env IfGblEnv ()) RecompileRequired
    checkDependencies HscEnv
    hsc_env ModSummary
    mod_summary ModIface
    iface
           ; case recomp of (NeedsRecompile CompileReason
    reason) -> MaybeValidated ModIface -> IfG (MaybeValidated ModIface)
    forall a. a -> IOEnv (Env IfGblEnv ()) a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (MaybeValidated ModIface -> IfG (MaybeValidated ModIface))
    -> MaybeValidated ModIface -> IfG (MaybeValidated ModIface)
    forall a b. (a -> b) -> a -> b
    $ CompileReason -> Maybe ModIface -> MaybeValidated ModIface
    forall a. CompileReason -> Maybe a -> MaybeValidated a
    OutOfDateItem CompileReason
    reason (ModIface -> Maybe ModIface
    forall a. a -> Maybe a
    Just ModIface
    iface) ; RecompileRequired
    _ -> do {
           ; recomp <- Plugins -> ModIface -> IOEnv (Env IfGblEnv ()) RecompileRequired
    checkPlugins (HscEnv -> Plugins
    hsc_plugins HscEnv
    hsc_env) ModIface
    iface
           ; case recomp of (NeedsRecompile CompileReason
    reason) -> MaybeValidated ModIface -> IfG (MaybeValidated ModIface)
    forall a. a -> IOEnv (Env IfGblEnv ()) a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (MaybeValidated ModIface -> IfG (MaybeValidated ModIface))
    -> MaybeValidated ModIface -> IfG (MaybeValidated ModIface)
    forall a b. (a -> b) -> a -> b
    $ CompileReason -> Maybe ModIface -> MaybeValidated ModIface
    forall a. CompileReason -> Maybe a -> MaybeValidated a
    OutOfDateItem CompileReason
    reason Maybe ModIface
    forall a. Maybe a
    Nothing ; RecompileRequired
    _ -> do {

           -- Source code unchanged and no errors yet... carry on
           --
           -- First put the dependent-module info, read from the old
           -- interface, into the envt, so that when we look for
           -- interfaces we look for the right one (.hi or .hi-boot)
           --
           -- It's just temporary because either the usage check will succeed
           -- (in which case we are done with this module) or it'll fail (in which
           -- case we'll compile the module from scratch anyhow).

           AnyHpcUsage
    -> IOEnv (Env IfGblEnv ()) () -> IOEnv (Env IfGblEnv ()) ()
    forall (f :: * -> *). Applicative f => AnyHpcUsage -> f () -> f ()
    when (GhcMode -> AnyHpcUsage
    isOneShot (DynFlags -> GhcMode
    ghcMode (HscEnv -> DynFlags
    hsc_dflags HscEnv
    hsc_env))) (IOEnv (Env IfGblEnv ()) () -> IOEnv (Env IfGblEnv ()) ())
    -> IOEnv (Env IfGblEnv ()) () -> IOEnv (Env IfGblEnv ()) ()
    forall a b. (a -> b) -> a -> b
    $ do {
              ; (ExternalPackageState -> ExternalPackageState)
    -> IOEnv (Env IfGblEnv ()) ()
    forall gbl lcl.
    (ExternalPackageState -> ExternalPackageState) -> TcRnIf gbl lcl ()
    updateEps_ ((ExternalPackageState -> ExternalPackageState)
     -> IOEnv (Env IfGblEnv ()) ())
    -> (ExternalPackageState -> ExternalPackageState)
    -> IOEnv (Env IfGblEnv ()) ()
    forall a b. (a -> b) -> a -> b
    $ \ExternalPackageState
    eps  -> ExternalPackageState
    eps { eps_is_boot = mkModDeps $ dep_boot_mods (mi_deps iface) }
           }
           ; recomp <- [IOEnv (Env IfGblEnv ()) RecompileRequired]
    -> IOEnv (Env IfGblEnv ()) RecompileRequired
    forall (m :: * -> *).
    Monad m =>
    [m RecompileRequired] -> m RecompileRequired
    checkList [FinderCache -> Usage -> IOEnv (Env IfGblEnv ()) RecompileRequired
    checkModUsage (HscEnv -> FinderCache
    hsc_FC HscEnv
    hsc_env) Usage
    u
                                 | Usage
    u <- ModIface -> [Usage]
    forall (phase :: ModIfacePhase). ModIface_ phase -> [Usage]
    mi_usages ModIface
    iface]
           ; case recomp of (NeedsRecompile CompileReason
    reason) -> MaybeValidated ModIface -> IfG (MaybeValidated ModIface)
    forall a. a -> IOEnv (Env IfGblEnv ()) a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (MaybeValidated ModIface -> IfG (MaybeValidated ModIface))
    -> MaybeValidated ModIface -> IfG (MaybeValidated ModIface)
    forall a b. (a -> b) -> a -> b
    $ CompileReason -> Maybe ModIface -> MaybeValidated ModIface
    forall a. CompileReason -> Maybe a -> MaybeValidated a
    OutOfDateItem CompileReason
    reason (ModIface -> Maybe ModIface
    forall a. a -> Maybe a
    Just ModIface
    iface) ; RecompileRequired
    _ -> do {
           ; MaybeValidated ModIface -> IfG (MaybeValidated ModIface)
    forall a. a -> IOEnv (Env IfGblEnv ()) a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (MaybeValidated ModIface -> IfG (MaybeValidated ModIface))
    -> MaybeValidated ModIface -> IfG (MaybeValidated ModIface)
    forall a b. (a -> b) -> a -> b
    $ ModIface -> MaybeValidated ModIface
    forall a. a -> MaybeValidated a
    UpToDateItem ModIface
    iface
        }}}}}}}
      where
        logger :: Logger
    logger = HscEnv -> Logger
    hsc_logger HscEnv
    hsc_env
        dflags :: DynFlags
    dflags = HscEnv -> DynFlags
    hsc_dflags HscEnv
    hsc_env
        home_unit :: HomeUnit
    home_unit = HscEnv -> HomeUnit
    hsc_home_unit HscEnv
    hsc_env

    -- | Check if any plugins are requesting recompilation
    checkPlugins :: Plugins -> ModIface -> IfG RecompileRequired
    checkPlugins :: Plugins -> ModIface -> IOEnv (Env IfGblEnv ()) RecompileRequired
    checkPlugins Plugins
    plugins ModIface
    iface = IO RecompileRequired -> IOEnv (Env IfGblEnv ()) RecompileRequired
    forall a. IO a -> IOEnv (Env IfGblEnv ()) a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO RecompileRequired -> IOEnv (Env IfGblEnv ()) RecompileRequired)
    -> IO RecompileRequired
    -> IOEnv (Env IfGblEnv ()) RecompileRequired
    forall a b. (a -> b) -> a -> b
    $ do
      recomp <- Plugins -> IO PluginRecompile
    recompPlugins Plugins
    plugins
      let new_fingerprint = PluginRecompile -> Fingerprint
    fingerprintPluginRecompile PluginRecompile
    recomp
      let old_fingerprint = ModIfaceBackend -> Fingerprint
    mi_plugin_hash (ModIface -> IfaceBackendExts 'ModIfaceFinal
    forall (phase :: ModIfacePhase).
    ModIface_ phase -> IfaceBackendExts phase
    mi_final_exts ModIface
    iface)
      return $ pluginRecompileToRecompileRequired old_fingerprint new_fingerprint recomp

    recompPlugins :: Plugins -> IO PluginRecompile
    recompPlugins :: Plugins -> IO PluginRecompile
    recompPlugins Plugins
    plugins = [PluginRecompile] -> PluginRecompile
    forall a. Monoid a => [a] -> a
    mconcat ([PluginRecompile] -> PluginRecompile)
    -> IO [PluginRecompile] -> IO PluginRecompile
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> (PluginWithArgs -> IO PluginRecompile)
    -> [PluginWithArgs] -> IO [PluginRecompile]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    (a -> m b) -> t a -> m (t b)
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
    mapM PluginWithArgs -> IO PluginRecompile
    pluginRecompile' (Plugins -> [PluginWithArgs]
    pluginsWithArgs Plugins
    plugins)

    fingerprintPlugins :: Plugins -> IO Fingerprint
    fingerprintPlugins :: Plugins -> IO Fingerprint
    fingerprintPlugins Plugins
    plugins = PluginRecompile -> Fingerprint
    fingerprintPluginRecompile (PluginRecompile -> Fingerprint)
    -> IO PluginRecompile -> IO Fingerprint
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Plugins -> IO PluginRecompile
    recompPlugins Plugins
    plugins

    fingerprintPluginRecompile :: PluginRecompile -> Fingerprint
    fingerprintPluginRecompile :: PluginRecompile -> Fingerprint
    fingerprintPluginRecompile PluginRecompile
    recomp = case PluginRecompile
    recomp of
      PluginRecompile
    NoForceRecompile  -> String -> Fingerprint
    fingerprintString String
    "NoForceRecompile"
      PluginRecompile
    ForceRecompile    -> String -> Fingerprint
    fingerprintString String
    "ForceRecompile"
      -- is the chance of collision worth worrying about?
      -- An alternative is to fingerprintFingerprints [fingerprintString
      -- "maybeRecompile", fp]
      MaybeRecompile Fingerprint
    fp -> Fingerprint
    fp

    pluginRecompileToRecompileRequired
        :: Fingerprint -> Fingerprint -> PluginRecompile -> RecompileRequired
    pluginRecompileToRecompileRequired :: Fingerprint -> Fingerprint -> PluginRecompile -> RecompileRequired
    pluginRecompileToRecompileRequired Fingerprint
    old_fp Fingerprint
    new_fp PluginRecompile
    pr
      | Fingerprint
    old_fp Fingerprint -> Fingerprint -> AnyHpcUsage
    forall a. Eq a => a -> a -> AnyHpcUsage
    == Fingerprint
    new_fp =
        case PluginRecompile
    pr of
          PluginRecompile
    NoForceRecompile  -> RecompileRequired
    UpToDate

          -- we already checked the fingerprint above so a mismatch is not possible
          -- here, remember that: `fingerprint (MaybeRecomp x) == x`.
          MaybeRecompile Fingerprint
    _  -> RecompileRequired
    UpToDate

          -- when we have an impure plugin in the stack we have to unconditionally
          -- recompile since it might integrate all sorts of crazy IO results into
          -- its compilation output.
          PluginRecompile
    ForceRecompile    -> RecompReason -> RecompileRequired
    needsRecompileBecause RecompReason
    ImpurePlugin

      | Fingerprint
    old_fp Fingerprint -> [Fingerprint] -> AnyHpcUsage
    forall a. Eq a => a -> [a] -> AnyHpcUsage
    forall (t :: * -> *) a.
    (Foldable t, Eq a) =>
    a -> t a -> AnyHpcUsage
    `elem` [Fingerprint]
    magic_fingerprints AnyHpcUsage -> AnyHpcUsage -> AnyHpcUsage
    ||
        Fingerprint
    new_fp Fingerprint -> [Fingerprint] -> AnyHpcUsage
    forall a. Eq a => a -> [a] -> AnyHpcUsage
    forall (t :: * -> *) a.
    (Foldable t, Eq a) =>
    a -> t a -> AnyHpcUsage
    `elem` [Fingerprint]
    magic_fingerprints
        -- The fingerprints do not match either the old or new one is a magic
        -- fingerprint. This happens when non-pure plugins are added for the first
        -- time or when we go from one recompilation strategy to another: (force ->
        -- no-force, maybe-recomp -> no-force, no-force -> maybe-recomp etc.)
        --
        -- For example when we go from ForceRecomp to NoForceRecomp
        -- recompilation is triggered since the old impure plugins could have
        -- changed the build output which is now back to normal.
        = RecompReason -> RecompileRequired
    needsRecompileBecause RecompReason
    PluginsChanged

      | AnyHpcUsage
    otherwise =
        case PluginRecompile
    pr of
          -- even though a plugin is forcing recompilation the fingerprint changed
          -- which would cause recompilation anyways so we report the fingerprint
          -- change instead.
          PluginRecompile
    ForceRecompile   -> RecompReason -> RecompileRequired
    needsRecompileBecause RecompReason
    PluginFingerprintChanged

          PluginRecompile
    _                -> RecompReason -> RecompileRequired
    needsRecompileBecause RecompReason
    PluginFingerprintChanged

     where
       magic_fingerprints :: [Fingerprint]
    magic_fingerprints =
           [ String -> Fingerprint
    fingerprintString String
    "NoForceRecompile"
           , String -> Fingerprint
    fingerprintString String
    "ForceRecompile"
           ]

    -- | Check if an hsig file needs recompilation because its
    -- implementing module has changed.
    checkHsig :: Logger -> HomeUnit -> ModSummary -> ModIface -> IO RecompileRequired
    checkHsig :: Logger
    -> HomeUnit -> ModSummary -> ModIface -> IO RecompileRequired
    checkHsig Logger
    logger HomeUnit
    home_unit ModSummary
    mod_summary ModIface
    iface = do
        let outer_mod :: Module
    outer_mod = ModSummary -> Module
    ms_mod ModSummary
    mod_summary
            inner_mod :: Module
    inner_mod = HomeUnit -> ModuleName -> Module
    homeModuleNameInstantiation HomeUnit
    home_unit (Module -> ModuleName
    forall unit. GenModule unit -> ModuleName
    moduleName Module
    outer_mod)
        AnyHpcUsage -> IO ()
    forall (m :: * -> *).
    (HasCallStack, Applicative m) =>
    AnyHpcUsage -> m ()
    massert (HomeUnit -> Module -> AnyHpcUsage
    isHomeModule HomeUnit
    home_unit Module
    outer_mod)
        case Module
    inner_mod Module -> Module -> AnyHpcUsage
    forall a. Eq a => a -> a -> AnyHpcUsage
    == ModIface -> Module
    forall (phase :: ModIfacePhase). ModIface_ phase -> Module
    mi_semantic_module ModIface
    iface of
            AnyHpcUsage
    True -> Logger -> SDoc -> IO RecompileRequired
    up_to_date Logger
    logger (String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "implementing module unchanged")
            AnyHpcUsage
    False -> RecompileRequired -> IO RecompileRequired
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (RecompileRequired -> IO RecompileRequired)
    -> RecompileRequired -> IO RecompileRequired
    forall a b. (a -> b) -> a -> b
    $ RecompReason -> RecompileRequired
    needsRecompileBecause RecompReason
    ModuleInstChanged

    -- | Check if @.hie@ file is out of date or missing.
    checkHie :: DynFlags -> ModSummary -> RecompileRequired
    checkHie :: DynFlags -> ModSummary -> RecompileRequired
    checkHie DynFlags
    dflags ModSummary
    mod_summary =
        let hie_date_opt :: Maybe UTCTime
    hie_date_opt = ModSummary -> Maybe UTCTime
    ms_hie_date ModSummary
    mod_summary
            hi_date :: Maybe UTCTime
    hi_date = ModSummary -> Maybe UTCTime
    ms_iface_date ModSummary
    mod_summary
        in if AnyHpcUsage -> AnyHpcUsage
    not (GeneralFlag -> DynFlags -> AnyHpcUsage
    gopt GeneralFlag
    Opt_WriteHie DynFlags
    dflags)
          then RecompileRequired
    UpToDate
          else case (Maybe UTCTime
    hie_date_opt, Maybe UTCTime
    hi_date) of
                 (Maybe UTCTime
    Nothing, Maybe UTCTime
    _) -> RecompReason -> RecompileRequired
    needsRecompileBecause RecompReason
    HieMissing
                 (Just UTCTime
    hie_date, Just UTCTime
    hi_date)
                     | UTCTime
    hie_date UTCTime -> UTCTime -> AnyHpcUsage
    forall a. Ord a => a -> a -> AnyHpcUsage
    < UTCTime
    hi_date
                     -> RecompReason -> RecompileRequired
    needsRecompileBecause RecompReason
    HieOutdated
                 (Maybe UTCTime, Maybe UTCTime)
    _ -> RecompileRequired
    UpToDate

    -- | Check the flags haven't changed
    checkFlagHash :: HscEnv -> ModIface -> IO RecompileRequired
    checkFlagHash :: HscEnv -> ModIface -> IO RecompileRequired
    checkFlagHash HscEnv
    hsc_env ModIface
    iface = do
        let logger :: Logger
    logger   = HscEnv -> Logger
    hsc_logger HscEnv
    hsc_env
        let old_hash :: Fingerprint
    old_hash = ModIfaceBackend -> Fingerprint
    mi_flag_hash (ModIface -> IfaceBackendExts 'ModIfaceFinal
    forall (phase :: ModIfacePhase).
    ModIface_ phase -> IfaceBackendExts phase
    mi_final_exts ModIface
    iface)
        new_hash <- HscEnv -> Module -> (BinHandle -> Name -> IO ()) -> IO Fingerprint
    fingerprintDynFlags HscEnv
    hsc_env (ModIface -> Module
    forall (phase :: ModIfacePhase). ModIface_ phase -> Module
    mi_module ModIface
    iface) BinHandle -> Name -> IO ()
    putNameLiterally
        case old_hash == new_hash of
            AnyHpcUsage
    True  -> Logger -> SDoc -> IO RecompileRequired
    up_to_date Logger
    logger (String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "Module flags unchanged")
            AnyHpcUsage
    False -> Logger
    -> RecompReason
    -> SDoc
    -> Fingerprint
    -> Fingerprint
    -> IO RecompileRequired
    out_of_date_hash Logger
    logger RecompReason
    FlagsChanged
                         (String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "  Module flags have changed")
                         Fingerprint
    old_hash Fingerprint
    new_hash

    -- | Check the optimisation flags haven't changed
    checkOptimHash :: HscEnv -> ModIface -> IO RecompileRequired
    checkOptimHash :: HscEnv -> ModIface -> IO RecompileRequired
    checkOptimHash HscEnv
    hsc_env ModIface
    iface = do
        let logger :: Logger
    logger   = HscEnv -> Logger
    hsc_logger HscEnv
    hsc_env
        let old_hash :: Fingerprint
    old_hash = ModIfaceBackend -> Fingerprint
    mi_opt_hash (ModIface -> IfaceBackendExts 'ModIfaceFinal
    forall (phase :: ModIfacePhase).
    ModIface_ phase -> IfaceBackendExts phase
    mi_final_exts ModIface
    iface)
        new_hash <- DynFlags -> (BinHandle -> Name -> IO ()) -> IO Fingerprint
    fingerprintOptFlags (HscEnv -> DynFlags
    hsc_dflags HscEnv
    hsc_env)
                                                   BinHandle -> Name -> IO ()
    putNameLiterally
        if | old_hash == new_hash
             -> up_to_date logger (text "Optimisation flags unchanged")
           | gopt Opt_IgnoreOptimChanges (hsc_dflags hsc_env)
             -> up_to_date logger (text "Optimisation flags changed; ignoring")
           | otherwise
             -> out_of_date_hash logger OptimFlagsChanged
                         (text "  Optimisation flags have changed")
                         old_hash new_hash

    -- | Check the HPC flags haven't changed
    checkHpcHash :: HscEnv -> ModIface -> IO RecompileRequired
    checkHpcHash :: HscEnv -> ModIface -> IO RecompileRequired
    checkHpcHash HscEnv
    hsc_env ModIface
    iface = do
        let logger :: Logger
    logger   = HscEnv -> Logger
    hsc_logger HscEnv
    hsc_env
        let old_hash :: Fingerprint
    old_hash = ModIfaceBackend -> Fingerprint
    mi_hpc_hash (ModIface -> IfaceBackendExts 'ModIfaceFinal
    forall (phase :: ModIfacePhase).
    ModIface_ phase -> IfaceBackendExts phase
    mi_final_exts ModIface
    iface)
        new_hash <- DynFlags -> (BinHandle -> Name -> IO ()) -> IO Fingerprint
    fingerprintHpcFlags (HscEnv -> DynFlags
    hsc_dflags HscEnv
    hsc_env)
                                                   BinHandle -> Name -> IO ()
    putNameLiterally
        if | old_hash == new_hash
             -> up_to_date logger (text "HPC flags unchanged")
           | gopt Opt_IgnoreHpcChanges (hsc_dflags hsc_env)
             -> up_to_date logger (text "HPC flags changed; ignoring")
           | otherwise
             -> out_of_date_hash logger HpcFlagsChanged
                         (text "  HPC flags have changed")
                         old_hash new_hash

    -- Check that the set of signatures we are merging in match.
    -- If the -unit-id flags change, this can change too.
    checkMergedSignatures :: HscEnv -> ModSummary -> ModIface -> IO RecompileRequired
    checkMergedSignatures :: HscEnv -> ModSummary -> ModIface -> IO RecompileRequired
    checkMergedSignatures HscEnv
    hsc_env ModSummary
    mod_summary ModIface
    iface = do
        let logger :: Logger
    logger     = HscEnv -> Logger
    hsc_logger HscEnv
    hsc_env
        let unit_state :: UnitState
    unit_state = HasDebugCallStack => HscEnv -> UnitState
    HscEnv -> UnitState
    hsc_units HscEnv
    hsc_env
        let old_merged :: [Module]
    old_merged = [Module] -> [Module]
    forall a. Ord a => [a] -> [a]
    sort [ Module
    mod | UsageMergedRequirement{ usg_mod :: Usage -> Module
    usg_mod = Module
    mod } <- ModIface -> [Usage]
    forall (phase :: ModIfacePhase). ModIface_ phase -> [Usage]
    mi_usages ModIface
    iface ]
            new_merged :: [Module]
    new_merged = case UniqMap ModuleName [InstantiatedModule]
    -> ModuleName -> Maybe [InstantiatedModule]
    forall k a. Uniquable k => UniqMap k a -> k -> Maybe a
    lookupUniqMap (UnitState -> UniqMap ModuleName [InstantiatedModule]
    requirementContext UnitState
    unit_state)
                              (ModSummary -> ModuleName
    ms_mod_name ModSummary
    mod_summary) of
                            Maybe [InstantiatedModule]
    Nothing -> []
                            Just [InstantiatedModule]
    r -> [Module] -> [Module]
    forall a. Ord a => [a] -> [a]
    sort ([Module] -> [Module]) -> [Module] -> [Module]
    forall a b. (a -> b) -> a -> b
    $ (InstantiatedModule -> Module) -> [InstantiatedModule] -> [Module]
    forall a b. (a -> b) -> [a] -> [b]
    map (UnitState -> InstantiatedModule -> Module
    instModuleToModule UnitState
    unit_state) [InstantiatedModule]
    r
        if [Module]
    old_merged [Module] -> [Module] -> AnyHpcUsage
    forall a. Eq a => a -> a -> AnyHpcUsage
    == [Module]
    new_merged
            then Logger -> SDoc -> IO RecompileRequired
    up_to_date Logger
    logger (String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "signatures to merge in unchanged" SDoc -> SDoc -> SDoc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$ [Module] -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr [Module]
    new_merged)
            else RecompileRequired -> IO RecompileRequired
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (RecompileRequired -> IO RecompileRequired)
    -> RecompileRequired -> IO RecompileRequired
    forall a b. (a -> b) -> a -> b
    $ RecompReason -> RecompileRequired
    needsRecompileBecause RecompReason
    SigsMergeChanged

    -- If the direct imports of this module are resolved to targets that
    -- are not among the dependencies of the previous interface file,
    -- then we definitely need to recompile.  This catches cases like
    --   - an exposed package has been upgraded
    --   - we are compiling with different package flags
    --   - a home module that was shadowing a package module has been removed
    --   - a new home module has been added that shadows a package module
    -- See bug #1372.
    --
    -- Returns (RecompBecause <reason>) if recompilation is required.
    checkDependencies :: HscEnv -> ModSummary -> ModIface -> IfG RecompileRequired
    checkDependencies :: HscEnv
    -> ModSummary
    -> ModIface
    -> IOEnv (Env IfGblEnv ()) RecompileRequired
    checkDependencies HscEnv
    hsc_env ModSummary
    summary ModIface
    iface
     = do
        res_normal <- (ModuleName -> PkgQual -> IO FindResult)
    -> [(PkgQual, GenLocated SrcSpan ModuleName)]
    -> IfG
         [Either
            CompileReason (Either (UnitId, ModuleName) (FastString, UnitId))]
    forall t l.
    (ModuleName -> t -> IO FindResult)
    -> [(t, GenLocated l ModuleName)]
    -> IfG
         [Either
            CompileReason (Either (UnitId, ModuleName) (FastString, UnitId))]
    classify_import (HscEnv -> ModuleName -> PkgQual -> IO FindResult
    findImportedModule HscEnv
    hsc_env) (ModSummary -> [(PkgQual, GenLocated SrcSpan ModuleName)]
    ms_textual_imps ModSummary
    summary [(PkgQual, GenLocated SrcSpan ModuleName)]
    -> [(PkgQual, GenLocated SrcSpan ModuleName)]
    -> [(PkgQual, GenLocated SrcSpan ModuleName)]
    forall a. [a] -> [a] -> [a]
    ++ ModSummary -> [(PkgQual, GenLocated SrcSpan ModuleName)]
    ms_srcimps ModSummary
    summary)
        res_plugin <- classify_import (\ModuleName
    mod PkgQual
    _ -> FinderCache
    -> FinderOpts
    -> UnitState
    -> Maybe HomeUnit
    -> ModuleName
    -> IO FindResult
    findPluginModule FinderCache
    fc FinderOpts
    fopts UnitState
    units Maybe HomeUnit
    mhome_unit ModuleName
    mod) (ms_plugin_imps summary)
        case sequence (res_normal ++ res_plugin ++ [Right (fake_ghc_prim_import)| ms_ghc_prim_import summary]) of
          Left CompileReason
    recomp -> RecompileRequired -> IOEnv (Env IfGblEnv ()) RecompileRequired
    forall a. a -> IOEnv (Env IfGblEnv ()) a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (RecompileRequired -> IOEnv (Env IfGblEnv ()) RecompileRequired)
    -> RecompileRequired -> IOEnv (Env IfGblEnv ()) RecompileRequired
    forall a b. (a -> b) -> a -> b
    $ CompileReason -> RecompileRequired
    NeedsRecompile CompileReason
    recomp
          Right [Either (UnitId, ModuleName) (FastString, UnitId)]
    es -> do
            let ([(UnitId, ModuleName)]
    hs, [(FastString, UnitId)]
    ps) = [Either (UnitId, ModuleName) (FastString, UnitId)]
    -> ([(UnitId, ModuleName)], [(FastString, UnitId)])
    forall a b. [Either a b] -> ([a], [b])
    partitionEithers [Either (UnitId, ModuleName) (FastString, UnitId)]
    es
            IO RecompileRequired -> IOEnv (Env IfGblEnv ()) RecompileRequired
    forall a. IO a -> IOEnv (Env IfGblEnv ()) a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO RecompileRequired -> IOEnv (Env IfGblEnv ()) RecompileRequired)
    -> IO RecompileRequired
    -> IOEnv (Env IfGblEnv ()) RecompileRequired
    forall a b. (a -> b) -> a -> b
    $
              [(UnitId, ModuleName)]
    -> [(UnitId, ModuleName)] -> IO RecompileRequired
    check_mods ([(UnitId, ModuleName)] -> [(UnitId, ModuleName)]
    forall a. Ord a => [a] -> [a]
    sort [(UnitId, ModuleName)]
    hs) [(UnitId, ModuleName)]
    prev_dep_mods
              IO RecompileRequired
    -> IO RecompileRequired -> IO RecompileRequired
    forall (m :: * -> *).
    Monad m =>
    m RecompileRequired -> m RecompileRequired -> m RecompileRequired
    `recompThen`
                let allPkgDeps :: [(FastString, UnitId)]
    allPkgDeps = ((FastString, UnitId) -> (FastString, UnitId) -> Ordering)
    -> [(FastString, UnitId)] -> [(FastString, UnitId)]
    forall a. (a -> a -> Ordering) -> [a] -> [a]
    sortBy (((FastString, UnitId) -> UnitId)
    -> (FastString, UnitId) -> (FastString, UnitId) -> Ordering
    forall a b. Ord a => (b -> a) -> b -> b -> Ordering
    comparing (FastString, UnitId) -> UnitId
    forall a b. (a, b) -> b
    snd) ([(FastString, UnitId)] -> [(FastString, UnitId)])
    -> [(FastString, UnitId)] -> [(FastString, UnitId)]
    forall a b. (a -> b) -> a -> b
    $ ((FastString, UnitId) -> UnitId)
    -> [(FastString, UnitId)] -> [(FastString, UnitId)]
    forall b a. Ord b => (a -> b) -> [a] -> [a]
    nubOrdOn (FastString, UnitId) -> UnitId
    forall a b. (a, b) -> b
    snd ([(FastString, UnitId)]
    ps [(FastString, UnitId)]
    -> [(FastString, UnitId)] -> [(FastString, UnitId)]
    forall a. [a] -> [a] -> [a]
    ++ [(FastString, UnitId)]
    implicit_deps)
                in [(FastString, UnitId)] -> [UnitId] -> IO RecompileRequired
    check_packages [(FastString, UnitId)]
    allPkgDeps [UnitId]
    prev_dep_pkgs
     where

       classify_import :: (ModuleName -> t -> IO FindResult)
                          -> [(t, GenLocated l ModuleName)]
                        -> IfG
                           [Either
                              CompileReason (Either (UnitId, ModuleName) (FastString, UnitId))]
       classify_import :: forall t l.
    (ModuleName -> t -> IO FindResult)
    -> [(t, GenLocated l ModuleName)]
    -> IfG
         [Either
            CompileReason (Either (UnitId, ModuleName) (FastString, UnitId))]
    classify_import ModuleName -> t -> IO FindResult
    find_import [(t, GenLocated l ModuleName)]
    imports =
        IO
      [Either
         CompileReason (Either (UnitId, ModuleName) (FastString, UnitId))]
    -> IfG
         [Either
            CompileReason (Either (UnitId, ModuleName) (FastString, UnitId))]
    forall a. IO a -> IOEnv (Env IfGblEnv ()) a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO
       [Either
          CompileReason (Either (UnitId, ModuleName) (FastString, UnitId))]
     -> IfG
          [Either
             CompileReason (Either (UnitId, ModuleName) (FastString, UnitId))])
    -> IO
         [Either
            CompileReason (Either (UnitId, ModuleName) (FastString, UnitId))]
    -> IfG
         [Either
            CompileReason (Either (UnitId, ModuleName) (FastString, UnitId))]
    forall a b. (a -> b) -> a -> b
    $ ((t, GenLocated l ModuleName)
     -> IO
          (Either
             CompileReason (Either (UnitId, ModuleName) (FastString, UnitId))))
    -> [(t, GenLocated l ModuleName)]
    -> IO
         [Either
            CompileReason (Either (UnitId, ModuleName) (FastString, UnitId))]
    forall (t :: * -> *) (f :: * -> *) a b.
    (Traversable t, Applicative f) =>
    (a -> f b) -> t a -> f (t b)
    forall (f :: * -> *) a b.
    Applicative f =>
    (a -> f b) -> [a] -> f [b]
    traverse (\(t
    mb_pkg, L l
    _ ModuleName
    mod) ->
               let reason :: RecompReason
    reason = ModuleName -> RecompReason
    ModuleChanged ModuleName
    mod
               in RecompReason
    -> FindResult
    -> Either
         CompileReason (Either (UnitId, ModuleName) (FastString, UnitId))
    classify RecompReason
    reason (FindResult
     -> Either
          CompileReason (Either (UnitId, ModuleName) (FastString, UnitId)))
    -> IO FindResult
    -> IO
         (Either
            CompileReason (Either (UnitId, ModuleName) (FastString, UnitId)))
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> ModuleName -> t -> IO FindResult
    find_import ModuleName
    mod t
    mb_pkg)
               [(t, GenLocated l ModuleName)]
    imports
       dflags :: DynFlags
    dflags        = HscEnv -> DynFlags
    hsc_dflags HscEnv
    hsc_env
       fopts :: FinderOpts
    fopts         = DynFlags -> FinderOpts
    initFinderOpts DynFlags
    dflags
       logger :: Logger
    logger        = HscEnv -> Logger
    hsc_logger HscEnv
    hsc_env
       fc :: FinderCache
    fc            = HscEnv -> FinderCache
    hsc_FC HscEnv
    hsc_env
       mhome_unit :: Maybe HomeUnit
    mhome_unit    = HscEnv -> Maybe HomeUnit
    hsc_home_unit_maybe HscEnv
    hsc_env
       all_home_units :: Set UnitId
    all_home_units = HscEnv -> Set UnitId
    hsc_all_home_unit_ids HscEnv
    hsc_env
       units :: UnitState
    units         = HasDebugCallStack => HscEnv -> UnitState
    HscEnv -> UnitState
    hsc_units HscEnv
    hsc_env
       prev_dep_mods :: [(UnitId, ModuleName)]
    prev_dep_mods = ((UnitId, ModuleNameWithIsBoot) -> (UnitId, ModuleName))
    -> [(UnitId, ModuleNameWithIsBoot)] -> [(UnitId, ModuleName)]
    forall a b. (a -> b) -> [a] -> [b]
    map ((ModuleNameWithIsBoot -> ModuleName)
    -> (UnitId, ModuleNameWithIsBoot) -> (UnitId, ModuleName)
    forall b c a. (b -> c) -> (a, b) -> (a, c)
    forall (p :: * -> * -> *) b c a.
    Bifunctor p =>
    (b -> c) -> p a b -> p a c
    second ModuleNameWithIsBoot -> ModuleName
    forall mod. GenWithIsBoot mod -> mod
    gwib_mod) ([(UnitId, ModuleNameWithIsBoot)] -> [(UnitId, ModuleName)])
    -> [(UnitId, ModuleNameWithIsBoot)] -> [(UnitId, ModuleName)]
    forall a b. (a -> b) -> a -> b
    $ Set (UnitId, ModuleNameWithIsBoot)
    -> [(UnitId, ModuleNameWithIsBoot)]
    forall a. Set a -> [a]
    Set.toAscList (Set (UnitId, ModuleNameWithIsBoot)
     -> [(UnitId, ModuleNameWithIsBoot)])
    -> Set (UnitId, ModuleNameWithIsBoot)
    -> [(UnitId, ModuleNameWithIsBoot)]
    forall a b. (a -> b) -> a -> b
    $ Dependencies -> Set (UnitId, ModuleNameWithIsBoot)
    dep_direct_mods (ModIface -> Dependencies
    forall (phase :: ModIfacePhase). ModIface_ phase -> Dependencies
    mi_deps ModIface
    iface)
       prev_dep_pkgs :: [UnitId]
    prev_dep_pkgs = Set UnitId -> [UnitId]
    forall a. Set a -> [a]
    Set.toAscList (Set UnitId -> Set UnitId -> Set UnitId
    forall a. Ord a => Set a -> Set a -> Set a
    Set.union (Dependencies -> Set UnitId
    dep_direct_pkgs (ModIface -> Dependencies
    forall (phase :: ModIfacePhase). ModIface_ phase -> Dependencies
    mi_deps ModIface
    iface))
                                                (Dependencies -> Set UnitId
    dep_plugin_pkgs (ModIface -> Dependencies
    forall (phase :: ModIfacePhase). ModIface_ phase -> Dependencies
    mi_deps ModIface
    iface)))

       implicit_deps :: [(FastString, UnitId)]
    implicit_deps = (UnitId -> (FastString, UnitId))
    -> [UnitId] -> [(FastString, UnitId)]
    forall a b. (a -> b) -> [a] -> [b]
    map (String -> FastString
    fsLit String
    "Implicit",) (DynFlags -> [UnitId]
    implicitPackageDeps DynFlags
    dflags)

       -- GHC.Prim is very special and doesn't appear in ms_textual_imps but
       -- ghc-prim will appear in the package dependencies still. In order to not confuse
       -- the recompilation logic we need to not forget we imported GHC.Prim.
       fake_ghc_prim_import :: Either (UnitId, ModuleName) (FastString, UnitId)
    fake_ghc_prim_import =  case Maybe HomeUnit
    mhome_unit of
                                  Just HomeUnit
    home_unit
                                    | HomeUnit -> UnitId
    forall u. GenHomeUnit u -> UnitId
    homeUnitId HomeUnit
    home_unit UnitId -> UnitId -> AnyHpcUsage
    forall a. Eq a => a -> a -> AnyHpcUsage
    == UnitId
    primUnitId
                                    -> (UnitId, ModuleName)
    -> Either (UnitId, ModuleName) (FastString, UnitId)
    forall a b. a -> Either a b
    Left (UnitId
    primUnitId, String -> ModuleName
    mkModuleName String
    "GHC.Prim")
                                  Maybe HomeUnit
    _ -> (FastString, UnitId)
    -> Either (UnitId, ModuleName) (FastString, UnitId)
    forall a b. b -> Either a b
    Right (String -> FastString
    fsLit String
    "GHC.Prim", UnitId
    primUnitId)

       classify :: RecompReason
    -> FindResult
    -> Either
         CompileReason (Either (UnitId, ModuleName) (FastString, UnitId))
    classify RecompReason
    _ (Found ModLocation
    _ Module
    mod)
        | (Unit -> UnitId
    toUnitId (Unit -> UnitId) -> Unit -> UnitId
    forall a b. (a -> b) -> a -> b
    $ Module -> Unit
    forall unit. GenModule unit -> unit
    moduleUnit Module
    mod) UnitId -> Set UnitId -> AnyHpcUsage
    forall a. Eq a => a -> Set a -> AnyHpcUsage
    forall (t :: * -> *) a.
    (Foldable t, Eq a) =>
    a -> t a -> AnyHpcUsage
    `elem` Set UnitId
    all_home_units = Either (UnitId, ModuleName) (FastString, UnitId)
    -> Either
         CompileReason (Either (UnitId, ModuleName) (FastString, UnitId))
    forall a b. b -> Either a b
    Right ((UnitId, ModuleName)
    -> Either (UnitId, ModuleName) (FastString, UnitId)
    forall a b. a -> Either a b
    Left ((Unit -> UnitId
    toUnitId (Unit -> UnitId) -> Unit -> UnitId
    forall a b. (a -> b) -> a -> b
    $ Module -> Unit
    forall unit. GenModule unit -> unit
    moduleUnit Module
    mod), Module -> ModuleName
    forall unit. GenModule unit -> ModuleName
    moduleName Module
    mod))
        | AnyHpcUsage
    otherwise = Either (UnitId, ModuleName) (FastString, UnitId)
    -> Either
         CompileReason (Either (UnitId, ModuleName) (FastString, UnitId))
    forall a b. b -> Either a b
    Right ((FastString, UnitId)
    -> Either (UnitId, ModuleName) (FastString, UnitId)
    forall a b. b -> Either a b
    Right (ModuleName -> FastString
    moduleNameFS (Module -> ModuleName
    forall unit. GenModule unit -> ModuleName
    moduleName Module
    mod), Unit -> UnitId
    toUnitId (Unit -> UnitId) -> Unit -> UnitId
    forall a b. (a -> b) -> a -> b
    $ Module -> Unit
    forall unit. GenModule unit -> unit
    moduleUnit Module
    mod))
       classify RecompReason
    reason FindResult
    _ = CompileReason
    -> Either
         CompileReason (Either (UnitId, ModuleName) (FastString, UnitId))
    forall a b. a -> Either a b
    Left (RecompReason -> CompileReason
    RecompBecause RecompReason
    reason)

       check_mods :: [(UnitId, ModuleName)] -> [(UnitId, ModuleName)] -> IO RecompileRequired
       check_mods :: [(UnitId, ModuleName)]
    -> [(UnitId, ModuleName)] -> IO RecompileRequired
    check_mods [] [] = RecompileRequired -> IO RecompileRequired
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return RecompileRequired
    UpToDate
       check_mods [] ((UnitId, ModuleName)
    old:[(UnitId, ModuleName)]
    _) = do
         -- This case can happen when a module is change from HPT to package import
         Logger -> SDoc -> IO ()
    trace_hi_diffs Logger
    logger (SDoc -> IO ()) -> SDoc -> IO ()
    forall a b. (a -> b) -> a -> b
    $
          String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "module no longer" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> SDoc -> SDoc
    quotes ((UnitId, ModuleName) -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr (UnitId, ModuleName)
    old) SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+>
            String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "in dependencies"

         RecompileRequired -> IO RecompileRequired
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (RecompileRequired -> IO RecompileRequired)
    -> RecompileRequired -> IO RecompileRequired
    forall a b. (a -> b) -> a -> b
    $ RecompReason -> RecompileRequired
    needsRecompileBecause (RecompReason -> RecompileRequired)
    -> RecompReason -> RecompileRequired
    forall a b. (a -> b) -> a -> b
    $ (UnitId, ModuleName) -> RecompReason
    ModuleRemoved (UnitId, ModuleName)
    old
       check_mods ((UnitId, ModuleName)
    new:[(UnitId, ModuleName)]
    news) [(UnitId, ModuleName)]
    olds
        | Just ((UnitId, ModuleName)
    old, [(UnitId, ModuleName)]
    olds') <- [(UnitId, ModuleName)]
    -> Maybe ((UnitId, ModuleName), [(UnitId, ModuleName)])
    forall a. [a] -> Maybe (a, [a])
    uncons [(UnitId, ModuleName)]
    olds
        , (UnitId, ModuleName)
    new (UnitId, ModuleName) -> (UnitId, ModuleName) -> AnyHpcUsage
    forall a. Eq a => a -> a -> AnyHpcUsage
    == (UnitId, ModuleName)
    old = [(UnitId, ModuleName)]
    -> [(UnitId, ModuleName)] -> IO RecompileRequired
    check_mods (((UnitId, ModuleName) -> AnyHpcUsage)
    -> [(UnitId, ModuleName)] -> [(UnitId, ModuleName)]
    forall a. (a -> AnyHpcUsage) -> [a] -> [a]
    dropWhile ((UnitId, ModuleName) -> (UnitId, ModuleName) -> AnyHpcUsage
    forall a. Eq a => a -> a -> AnyHpcUsage
    == (UnitId, ModuleName)
    new) [(UnitId, ModuleName)]
    news) [(UnitId, ModuleName)]
    olds'
        | AnyHpcUsage
    otherwise = do
            Logger -> SDoc -> IO ()
    trace_hi_diffs Logger
    logger (SDoc -> IO ()) -> SDoc -> IO ()
    forall a b. (a -> b) -> a -> b
    $
               String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "imported module " SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <> SDoc -> SDoc
    quotes ((UnitId, ModuleName) -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr (UnitId, ModuleName)
    new) SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <>
               String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    " not among previous dependencies"
            RecompileRequired -> IO RecompileRequired
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (RecompileRequired -> IO RecompileRequired)
    -> RecompileRequired -> IO RecompileRequired
    forall a b. (a -> b) -> a -> b
    $ RecompReason -> RecompileRequired
    needsRecompileBecause (RecompReason -> RecompileRequired)
    -> RecompReason -> RecompileRequired
    forall a b. (a -> b) -> a -> b
    $ (UnitId, ModuleName) -> RecompReason
    ModuleAdded (UnitId, ModuleName)
    new

       check_packages :: [(FastString, UnitId)] -> [UnitId] -> IO RecompileRequired
       check_packages :: [(FastString, UnitId)] -> [UnitId] -> IO RecompileRequired
    check_packages [] [] = RecompileRequired -> IO RecompileRequired
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return RecompileRequired
    UpToDate
       check_packages [] (UnitId
    old:[UnitId]
    _) = do
         Logger -> SDoc -> IO ()
    trace_hi_diffs Logger
    logger (SDoc -> IO ()) -> SDoc -> IO ()
    forall a b. (a -> b) -> a -> b
    $
          String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "package " SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <> SDoc -> SDoc
    quotes (UnitId -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr UnitId
    old) SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <>
            String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "no longer in dependencies"
         RecompileRequired -> IO RecompileRequired
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (RecompileRequired -> IO RecompileRequired)
    -> RecompileRequired -> IO RecompileRequired
    forall a b. (a -> b) -> a -> b
    $ RecompReason -> RecompileRequired
    needsRecompileBecause (RecompReason -> RecompileRequired)
    -> RecompReason -> RecompileRequired
    forall a b. (a -> b) -> a -> b
    $ UnitId -> RecompReason
    UnitDepRemoved UnitId
    old
       check_packages ((FastString
    new_name, UnitId
    new_unit):[(FastString, UnitId)]
    news) [UnitId]
    olds
        | Just (UnitId
    old, [UnitId]
    olds') <- [UnitId] -> Maybe (UnitId, [UnitId])
    forall a. [a] -> Maybe (a, [a])
    uncons [UnitId]
    olds
        , UnitId
    new_unit UnitId -> UnitId -> AnyHpcUsage
    forall a. Eq a => a -> a -> AnyHpcUsage
    == UnitId
    old = [(FastString, UnitId)] -> [UnitId] -> IO RecompileRequired
    check_packages (((FastString, UnitId) -> AnyHpcUsage)
    -> [(FastString, UnitId)] -> [(FastString, UnitId)]
    forall a. (a -> AnyHpcUsage) -> [a] -> [a]
    dropWhile ((UnitId -> UnitId -> AnyHpcUsage
    forall a. Eq a => a -> a -> AnyHpcUsage
    == UnitId
    new_unit) (UnitId -> AnyHpcUsage)
    -> ((FastString, UnitId) -> UnitId)
    -> (FastString, UnitId)
    -> AnyHpcUsage
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (FastString, UnitId) -> UnitId
    forall a b. (a, b) -> b
    snd) [(FastString, UnitId)]
    news) [UnitId]
    olds'
        | AnyHpcUsage
    otherwise = do
            Logger -> SDoc -> IO ()
    trace_hi_diffs Logger
    logger (SDoc -> IO ()) -> SDoc -> IO ()
    forall a b. (a -> b) -> a -> b
    $
             String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "imported package" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> FastString -> SDoc
    forall doc. IsLine doc => FastString -> doc
    ftext FastString
    new_name SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> UnitId -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr UnitId
    new_unit SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+>
               String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "not among previous dependencies"
            RecompileRequired -> IO RecompileRequired
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (RecompileRequired -> IO RecompileRequired)
    -> RecompileRequired -> IO RecompileRequired
    forall a b. (a -> b) -> a -> b
    $ RecompReason -> RecompileRequired
    needsRecompileBecause (RecompReason -> RecompileRequired)
    -> RecompReason -> RecompileRequired
    forall a b. (a -> b) -> a -> b
    $ FastString -> RecompReason
    ModulePackageChanged FastString
    new_name

    needInterface :: Module -> (ModIface -> IO RecompileRequired)
                 -> IfG RecompileRequired
    needInterface :: Module
    -> (ModIface -> IO RecompileRequired)
    -> IOEnv (Env IfGblEnv ()) RecompileRequired
    needInterface Module
    mod ModIface -> IO RecompileRequired
    continue
      = do
          mb_recomp <- String -> Module -> IOEnv (Env IfGblEnv ()) (Maybe ModIface)
    tryGetModIface
            String
    "need version info for"
            Module
    mod
          case mb_recomp of
            Maybe ModIface
    Nothing -> RecompileRequired -> IOEnv (Env IfGblEnv ()) RecompileRequired
    forall a. a -> IOEnv (Env IfGblEnv ()) a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (RecompileRequired -> IOEnv (Env IfGblEnv ()) RecompileRequired)
    -> RecompileRequired -> IOEnv (Env IfGblEnv ()) RecompileRequired
    forall a b. (a -> b) -> a -> b
    $ CompileReason -> RecompileRequired
    NeedsRecompile CompileReason
    MustCompile
            Just ModIface
    iface -> IO RecompileRequired -> IOEnv (Env IfGblEnv ()) RecompileRequired
    forall a. IO a -> IOEnv (Env IfGblEnv ()) a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO RecompileRequired -> IOEnv (Env IfGblEnv ()) RecompileRequired)
    -> IO RecompileRequired
    -> IOEnv (Env IfGblEnv ()) RecompileRequired
    forall a b. (a -> b) -> a -> b
    $ ModIface -> IO RecompileRequired
    continue ModIface
    iface

    tryGetModIface :: String -> Module -> IfG (Maybe ModIface)
    tryGetModIface :: String -> Module -> IOEnv (Env IfGblEnv ()) (Maybe ModIface)
    tryGetModIface String
    doc_msg Module
    mod
      = do  -- Load the imported interface if possible
        logger <- IOEnv (Env IfGblEnv ()) Logger
    forall (m :: * -> *). HasLogger m => m Logger
    getLogger
        let doc_str = [SDoc] -> SDoc
    forall doc. IsLine doc => [doc] -> doc
    sep [String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    doc_msg, Module -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Module
    mod]
        liftIO $ trace_hi_diffs logger (text "Checking interface for module" <+> ppr mod <+> ppr (moduleUnit mod))

        mb_iface <- loadInterface doc_str mod ImportBySystem
            -- Load the interface, but don't complain on failure;
            -- Instead, get an Either back which we can test

        case mb_iface of
          Failed MissingInterfaceError
    _ -> do
            IO () -> IOEnv (Env IfGblEnv ()) ()
    forall a. IO a -> IOEnv (Env IfGblEnv ()) a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> IOEnv (Env IfGblEnv ()) ())
    -> IO () -> IOEnv (Env IfGblEnv ()) ()
    forall a b. (a -> b) -> a -> b
    $ Logger -> SDoc -> IO ()
    trace_hi_diffs Logger
    logger ([SDoc] -> SDoc
    forall doc. IsLine doc => [doc] -> doc
    sep [String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "Couldn't load interface for module", Module -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Module
    mod])
            Maybe ModIface -> IOEnv (Env IfGblEnv ()) (Maybe ModIface)
    forall a. a -> IOEnv (Env IfGblEnv ()) a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Maybe ModIface
    forall a. Maybe a
    Nothing
                      -- Couldn't find or parse a module mentioned in the
                      -- old interface file.  Don't complain: it might
                      -- just be that the current module doesn't need that
                      -- import and it's been deleted
          Succeeded ModIface
    iface -> Maybe ModIface -> IOEnv (Env IfGblEnv ()) (Maybe ModIface)
    forall a. a -> IOEnv (Env IfGblEnv ()) a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (Maybe ModIface -> IOEnv (Env IfGblEnv ()) (Maybe ModIface))
    -> Maybe ModIface -> IOEnv (Env IfGblEnv ()) (Maybe ModIface)
    forall a b. (a -> b) -> a -> b
    $ ModIface -> Maybe ModIface
    forall a. a -> Maybe a
    Just ModIface
    iface

    -- | Given the usage information extracted from the old
    -- M.hi file for the module being compiled, figure out
    -- whether M needs to be recompiled.
    checkModUsage :: FinderCache -> Usage -> IfG RecompileRequired
    checkModUsage :: FinderCache -> Usage -> IOEnv (Env IfGblEnv ()) RecompileRequired
    checkModUsage FinderCache
    _ UsagePackageModule{
                                    usg_mod :: Usage -> Module
    usg_mod = Module
    mod,
                                    usg_mod_hash :: Usage -> Fingerprint
    usg_mod_hash = Fingerprint
    old_mod_hash } = do
      logger <- IOEnv (Env IfGblEnv ()) Logger
    forall (m :: * -> *). HasLogger m => m Logger
    getLogger
      needInterface mod $ \ModIface
    iface -> do
        let reason :: RecompReason
    reason = ModuleName -> RecompReason
    ModuleChanged (Module -> ModuleName
    forall unit. GenModule unit -> ModuleName
    moduleName Module
    mod)
        Logger
    -> RecompReason
    -> Fingerprint
    -> Fingerprint
    -> IO RecompileRequired
    checkModuleFingerprint Logger
    logger RecompReason
    reason Fingerprint
    old_mod_hash (ModIfaceBackend -> Fingerprint
    mi_mod_hash (ModIface -> IfaceBackendExts 'ModIfaceFinal
    forall (phase :: ModIfacePhase).
    ModIface_ phase -> IfaceBackendExts phase
    mi_final_exts ModIface
    iface))
            -- We only track the ABI hash of package modules, rather than
            -- individual entity usages, so if the ABI hash changes we must
            -- recompile.  This is safe but may entail more recompilation when
            -- a dependent package has changed.

    checkModUsage FinderCache
    _ UsageMergedRequirement{ usg_mod :: Usage -> Module
    usg_mod = Module
    mod, usg_mod_hash :: Usage -> Fingerprint
    usg_mod_hash = Fingerprint
    old_mod_hash } = do
      logger <- IOEnv (Env IfGblEnv ()) Logger
    forall (m :: * -> *). HasLogger m => m Logger
    getLogger
      needInterface mod $ \ModIface
    iface -> do
        let reason :: RecompReason
    reason = ModuleName -> RecompReason
    ModuleChangedRaw (Module -> ModuleName
    forall unit. GenModule unit -> ModuleName
    moduleName Module
    mod)
        Logger
    -> RecompReason
    -> Fingerprint
    -> Fingerprint
    -> IO RecompileRequired
    checkModuleFingerprint Logger
    logger RecompReason
    reason Fingerprint
    old_mod_hash (ModIfaceBackend -> Fingerprint
    mi_mod_hash (ModIface -> IfaceBackendExts 'ModIfaceFinal
    forall (phase :: ModIfacePhase).
    ModIface_ phase -> IfaceBackendExts phase
    mi_final_exts ModIface
    iface))
    checkModUsage FinderCache
    _  UsageHomeModuleInterface{ usg_mod_name :: Usage -> ModuleName
    usg_mod_name = ModuleName
    mod_name
                                                     , usg_unit_id :: Usage -> UnitId
    usg_unit_id = UnitId
    uid
                                                     , usg_iface_hash :: Usage -> Fingerprint
    usg_iface_hash = Fingerprint
    old_mod_hash } = do
      let mod :: Module
    mod = Unit -> ModuleName -> Module
    forall u. u -> ModuleName -> GenModule u
    mkModule (Definite UnitId -> Unit
    forall uid. Definite uid -> GenUnit uid
    RealUnit (UnitId -> Definite UnitId
    forall unit. unit -> Definite unit
    Definite UnitId
    uid)) ModuleName
    mod_name
      logger <- IOEnv (Env IfGblEnv ()) Logger
    forall (m :: * -> *). HasLogger m => m Logger
    getLogger
      needInterface mod $ \ModIface
    iface -> do
        let reason :: RecompReason
    reason = ModuleName -> RecompReason
    ModuleChangedIface ModuleName
    mod_name
        Logger
    -> RecompReason
    -> Fingerprint
    -> Fingerprint
    -> IO RecompileRequired
    checkIfaceFingerprint Logger
    logger RecompReason
    reason Fingerprint
    old_mod_hash (ModIfaceBackend -> Fingerprint
    mi_iface_hash (ModIface -> IfaceBackendExts 'ModIfaceFinal
    forall (phase :: ModIfacePhase).
    ModIface_ phase -> IfaceBackendExts phase
    mi_final_exts ModIface
    iface))

    checkModUsage FinderCache
    _ UsageHomeModule{
                                    usg_mod_name :: Usage -> ModuleName
    usg_mod_name = ModuleName
    mod_name,
                                    usg_unit_id :: Usage -> UnitId
    usg_unit_id  = UnitId
    uid,
                                    usg_mod_hash :: Usage -> Fingerprint
    usg_mod_hash = Fingerprint
    old_mod_hash,
                                    usg_exports :: Usage -> Maybe Fingerprint
    usg_exports = Maybe Fingerprint
    maybe_old_export_hash,
                                    usg_entities :: Usage -> [(OccName, Fingerprint)]
    usg_entities = [(OccName, Fingerprint)]
    old_decl_hash }
      = do
        let mod :: Module
    mod = Unit -> ModuleName -> Module
    forall u. u -> ModuleName -> GenModule u
    mkModule (Definite UnitId -> Unit
    forall uid. Definite uid -> GenUnit uid
    RealUnit (UnitId -> Definite UnitId
    forall unit. unit -> Definite unit
    Definite UnitId
    uid)) ModuleName
    mod_name
        logger <- IOEnv (Env IfGblEnv ()) Logger
    forall (m :: * -> *). HasLogger m => m Logger
    getLogger
        needInterface mod $ \ModIface
    iface -> do
         let
             new_mod_hash :: Fingerprint
    new_mod_hash    = ModIfaceBackend -> Fingerprint
    mi_mod_hash (ModIface -> IfaceBackendExts 'ModIfaceFinal
    forall (phase :: ModIfacePhase).
    ModIface_ phase -> IfaceBackendExts phase
    mi_final_exts ModIface
    iface)
             new_decl_hash :: OccName -> Maybe (OccName, Fingerprint)
    new_decl_hash   = ModIfaceBackend -> OccName -> Maybe (OccName, Fingerprint)
    mi_hash_fn  (ModIface -> IfaceBackendExts 'ModIfaceFinal
    forall (phase :: ModIfacePhase).
    ModIface_ phase -> IfaceBackendExts phase
    mi_final_exts ModIface
    iface)
             new_export_hash :: Fingerprint
    new_export_hash = ModIfaceBackend -> Fingerprint
    mi_exp_hash (ModIface -> IfaceBackendExts 'ModIfaceFinal
    forall (phase :: ModIfacePhase).
    ModIface_ phase -> IfaceBackendExts phase
    mi_final_exts ModIface
    iface)

             reason :: RecompReason
    reason = ModuleName -> RecompReason
    ModuleChanged (Module -> ModuleName
    forall unit. GenModule unit -> ModuleName
    moduleName Module
    mod)

         IO RecompileRequired -> IO RecompileRequired
    forall a. IO a -> IO a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO RecompileRequired -> IO RecompileRequired)
    -> IO RecompileRequired -> IO RecompileRequired
    forall a b. (a -> b) -> a -> b
    $ do
               -- CHECK MODULE
           recompile <- Logger
    -> RecompReason
    -> Fingerprint
    -> Fingerprint
    -> IO RecompileRequired
    checkModuleFingerprint Logger
    logger RecompReason
    reason Fingerprint
    old_mod_hash Fingerprint
    new_mod_hash
           if not (recompileRequired recompile)
             then return UpToDate
             else checkList
               [ -- CHECK EXPORT LIST
                 checkMaybeHash logger reason maybe_old_export_hash new_export_hash
                   (text "  Export list changed")
               , -- CHECK ITEMS ONE BY ONE
                 checkList [ checkEntityUsage logger reason new_decl_hash u
                           | u <- old_decl_hash]
               , up_to_date logger (text "  Great!  The bits I use are up to date")
               ]

    checkModUsage FinderCache
    fc UsageFile{ usg_file_path :: Usage -> FastString
    usg_file_path = FastString
    file,
                                usg_file_hash :: Usage -> Fingerprint
    usg_file_hash = Fingerprint
    old_hash,
                                usg_file_label :: Usage -> Maybe String
    usg_file_label = Maybe String
    mlabel } =
      IO RecompileRequired -> IOEnv (Env IfGblEnv ()) RecompileRequired
    forall a. IO a -> IOEnv (Env IfGblEnv ()) a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO RecompileRequired -> IOEnv (Env IfGblEnv ()) RecompileRequired)
    -> IO RecompileRequired
    -> IOEnv (Env IfGblEnv ()) RecompileRequired
    forall a b. (a -> b) -> a -> b
    $
        (IOException -> IO RecompileRequired)
    -> IO RecompileRequired -> IO RecompileRequired
    forall a. (IOException -> IO a) -> IO a -> IO a
    handleIO IOException -> IO RecompileRequired
    handler (IO RecompileRequired -> IO RecompileRequired)
    -> IO RecompileRequired -> IO RecompileRequired
    forall a b. (a -> b) -> a -> b
    $ do
          new_hash <- FinderCache -> String -> IO Fingerprint
    lookupFileCache FinderCache
    fc (String -> IO Fingerprint) -> String -> IO Fingerprint
    forall a b. (a -> b) -> a -> b
    $ FastString -> String
    unpackFS FastString
    file
          if (old_hash /= new_hash)
             then return recomp
             else return UpToDate
     where
       reason :: RecompReason
    reason = String -> RecompReason
    FileChanged (String -> RecompReason) -> String -> RecompReason
    forall a b. (a -> b) -> a -> b
    $ FastString -> String
    unpackFS FastString
    file
       recomp :: RecompileRequired
    recomp  = RecompReason -> RecompileRequired
    needsRecompileBecause (RecompReason -> RecompileRequired)
    -> RecompReason -> RecompileRequired
    forall a b. (a -> b) -> a -> b
    $ RecompReason -> Maybe RecompReason -> RecompReason
    forall a. a -> Maybe a -> a
    fromMaybe RecompReason
    reason (Maybe RecompReason -> RecompReason)
    -> Maybe RecompReason -> RecompReason
    forall a b. (a -> b) -> a -> b
    $ (String -> RecompReason) -> Maybe String -> Maybe RecompReason
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap String -> RecompReason
    CustomReason Maybe String
    mlabel
       handler :: IOException -> IO RecompileRequired
    handler = if AnyHpcUsage
    debugIsOn
          then \IOException
    e -> String -> SDoc -> IO RecompileRequired -> IO RecompileRequired
    forall a. String -> SDoc -> a -> a
    pprTrace String
    "UsageFile" (String -> SDoc
    forall doc. IsLine doc => String -> doc
    text (IOException -> String
    forall a. Show a => a -> String
    show IOException
    e)) (IO RecompileRequired -> IO RecompileRequired)
    -> IO RecompileRequired -> IO RecompileRequired
    forall a b. (a -> b) -> a -> b
    $ RecompileRequired -> IO RecompileRequired
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return RecompileRequired
    recomp
          else \IOException
    _ -> RecompileRequired -> IO RecompileRequired
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return RecompileRequired
    recomp -- if we can't find the file, just recompile, don't fail

    ------------------------
    checkModuleFingerprint
      :: Logger
      -> RecompReason
      -> Fingerprint
      -> Fingerprint
      -> IO RecompileRequired
    checkModuleFingerprint :: Logger
    -> RecompReason
    -> Fingerprint
    -> Fingerprint
    -> IO RecompileRequired
    checkModuleFingerprint Logger
    logger RecompReason
    reason Fingerprint
    old_mod_hash Fingerprint
    new_mod_hash
      | Fingerprint
    new_mod_hash Fingerprint -> Fingerprint -> AnyHpcUsage
    forall a. Eq a => a -> a -> AnyHpcUsage
    == Fingerprint
    old_mod_hash
      = Logger -> SDoc -> IO RecompileRequired
    up_to_date Logger
    logger (String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "Module fingerprint unchanged")

      | AnyHpcUsage
    otherwise
      = Logger
    -> RecompReason
    -> SDoc
    -> Fingerprint
    -> Fingerprint
    -> IO RecompileRequired
    out_of_date_hash Logger
    logger RecompReason
    reason (String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "  Module fingerprint has changed")
                         Fingerprint
    old_mod_hash Fingerprint
    new_mod_hash

    checkIfaceFingerprint
      :: Logger
      -> RecompReason
      -> Fingerprint
      -> Fingerprint
      -> IO RecompileRequired
    checkIfaceFingerprint :: Logger
    -> RecompReason
    -> Fingerprint
    -> Fingerprint
    -> IO RecompileRequired
    checkIfaceFingerprint Logger
    logger RecompReason
    reason Fingerprint
    old_mod_hash Fingerprint
    new_mod_hash
      | Fingerprint
    new_mod_hash Fingerprint -> Fingerprint -> AnyHpcUsage
    forall a. Eq a => a -> a -> AnyHpcUsage
    == Fingerprint
    old_mod_hash
      = Logger -> SDoc -> IO RecompileRequired
    up_to_date Logger
    logger (String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "Iface fingerprint unchanged")

      | AnyHpcUsage
    otherwise
      = Logger
    -> RecompReason
    -> SDoc
    -> Fingerprint
    -> Fingerprint
    -> IO RecompileRequired
    out_of_date_hash Logger
    logger RecompReason
    reason (String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "  Iface fingerprint has changed")
                         Fingerprint
    old_mod_hash Fingerprint
    new_mod_hash

    ------------------------
    checkMaybeHash
      :: Logger
      -> RecompReason
      -> Maybe Fingerprint
      -> Fingerprint
      -> SDoc
      -> IO RecompileRequired
    checkMaybeHash :: Logger
    -> RecompReason
    -> Maybe Fingerprint
    -> Fingerprint
    -> SDoc
    -> IO RecompileRequired
    checkMaybeHash Logger
    logger RecompReason
    reason Maybe Fingerprint
    maybe_old_hash Fingerprint
    new_hash SDoc
    doc
      | Just Fingerprint
    hash <- Maybe Fingerprint
    maybe_old_hash, Fingerprint
    hash Fingerprint -> Fingerprint -> AnyHpcUsage
    forall a. Eq a => a -> a -> AnyHpcUsage
    /= Fingerprint
    new_hash
      = Logger
    -> RecompReason
    -> SDoc
    -> Fingerprint
    -> Fingerprint
    -> IO RecompileRequired
    out_of_date_hash Logger
    logger RecompReason
    reason SDoc
    doc Fingerprint
    hash Fingerprint
    new_hash
      | AnyHpcUsage
    otherwise
      = RecompileRequired -> IO RecompileRequired
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return RecompileRequired
    UpToDate

    ------------------------
    checkEntityUsage :: Logger
                     -> RecompReason
                     -> (OccName -> Maybe (OccName, Fingerprint))
                     -> (OccName, Fingerprint)
                     -> IO RecompileRequired
    checkEntityUsage :: Logger
    -> RecompReason
    -> (OccName -> Maybe (OccName, Fingerprint))
    -> (OccName, Fingerprint)
    -> IO RecompileRequired
    checkEntityUsage Logger
    logger RecompReason
    reason OccName -> Maybe (OccName, Fingerprint)
    new_hash (OccName
    name,Fingerprint
    old_hash) = do
      case OccName -> Maybe (OccName, Fingerprint)
    new_hash OccName
    name of
        -- We used it before, but it ain't there now
        Maybe (OccName, Fingerprint)
    Nothing       -> Logger -> RecompReason -> SDoc -> IO RecompileRequired
    out_of_date Logger
    logger RecompReason
    reason ([SDoc] -> SDoc
    forall doc. IsLine doc => [doc] -> doc
    sep [String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "No longer exported:", OccName -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr OccName
    name])
        -- It's there, but is it up to date?
        Just (OccName
    _, Fingerprint
    new_hash)
          | Fingerprint
    new_hash Fingerprint -> Fingerprint -> AnyHpcUsage
    forall a. Eq a => a -> a -> AnyHpcUsage
    == Fingerprint
    old_hash
          -> do Logger -> SDoc -> IO ()
    trace_hi_diffs Logger
    logger (String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "  Up to date" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> OccName -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr OccName
    name SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc
    parens (Fingerprint -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Fingerprint
    new_hash))
                RecompileRequired -> IO RecompileRequired
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return RecompileRequired
    UpToDate
          | AnyHpcUsage
    otherwise
          -> Logger
    -> RecompReason
    -> SDoc
    -> Fingerprint
    -> Fingerprint
    -> IO RecompileRequired
    out_of_date_hash Logger
    logger RecompReason
    reason (String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "  Out of date:" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> OccName -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr OccName
    name) Fingerprint
    old_hash Fingerprint
    new_hash

    up_to_date :: Logger -> SDoc -> IO RecompileRequired
    up_to_date :: Logger -> SDoc -> IO RecompileRequired
    up_to_date Logger
    logger SDoc
    msg = Logger -> SDoc -> IO ()
    trace_hi_diffs Logger
    logger SDoc
    msg IO () -> IO RecompileRequired -> IO RecompileRequired
    forall a b. IO a -> IO b -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> RecompileRequired -> IO RecompileRequired
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return RecompileRequired
    UpToDate

    out_of_date :: Logger -> RecompReason -> SDoc -> IO RecompileRequired
    out_of_date :: Logger -> RecompReason -> SDoc -> IO RecompileRequired
    out_of_date Logger
    logger RecompReason
    reason SDoc
    msg = Logger -> SDoc -> IO ()
    trace_hi_diffs Logger
    logger SDoc
    msg IO () -> IO RecompileRequired -> IO RecompileRequired
    forall a b. IO a -> IO b -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> RecompileRequired -> IO RecompileRequired
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (RecompReason -> RecompileRequired
    needsRecompileBecause RecompReason
    reason)

    out_of_date_hash :: Logger -> RecompReason -> SDoc -> Fingerprint -> Fingerprint -> IO RecompileRequired
    out_of_date_hash :: Logger
    -> RecompReason
    -> SDoc
    -> Fingerprint
    -> Fingerprint
    -> IO RecompileRequired
    out_of_date_hash Logger
    logger RecompReason
    reason SDoc
    msg Fingerprint
    old_hash Fingerprint
    new_hash
      = Logger -> RecompReason -> SDoc -> IO RecompileRequired
    out_of_date Logger
    logger RecompReason
    reason ([SDoc] -> SDoc
    forall doc. IsLine doc => [doc] -> doc
    hsep [SDoc
    msg, Fingerprint -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Fingerprint
    old_hash, String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "->", Fingerprint -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Fingerprint
    new_hash])

    -- ---------------------------------------------------------------------------
    -- Compute fingerprints for the interface

    {-
    Note [Fingerprinting IfaceDecls]
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    The general idea here is that we first examine the 'IfaceDecl's and determine
    the recursive groups of them. We then walk these groups in dependency order,
    serializing each contained 'IfaceDecl' to a "Binary" buffer which we then
    hash using MD5 to produce a fingerprint for the group.

    However, the serialization that we use is a bit funny: we override the @putName@
    operation with our own which serializes the hash of a 'Name' instead of the
    'Name' itself. This ensures that the fingerprint of a decl changes if anything
    in its transitive closure changes. This trick is why we must be careful about
    traversing in dependency order: we need to ensure that we have hashes for
    everything referenced by the decl which we are fingerprinting.

    Moreover, we need to be careful to distinguish between serialization of binding
    Names (e.g. the ifName field of a IfaceDecl) and non-binding (e.g. the ifInstCls
    field of a IfaceClsInst): only in the non-binding case should we include the
    fingerprint; in the binding case we shouldn't since it is merely the name of the
    thing that we are currently fingerprinting.

    Note [Fingerprinting recursive groups]
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    The fingerprinting of a single recursive group is a rather subtle affair, as
    seen in #18733.

    How not to fingerprint
    ----------------------

    Prior to fixing #18733 we used the following (flawed) scheme to fingerprint a
    group in hash environment `hash_env0`:

     1. extend hash_env0, giving each declaration in the group the fingerprint 0
     2. use this environment to hash the declarations' ABIs, resulting in
        group_fingerprint
     3. produce the final hash environment by extending hash_env0, mapping each
        declaration of the group to group_fingerprint

    However, this is wrong. Consider, for instance, a program like:

        data A = ARecu B | ABase String deriving (Show)
        data B = BRecu A | BBase Int deriving (Show)

        info :: B
        info = BBase 1

    A consequence of (3) is that A and B will have the same fingerprint. This means
    that if the user changes `info` to:

        info :: A
        info = ABase "hello"

    The program's ABI fingerprint will not change despite `info`'s type, and
    therefore ABI, being clearly different.

    However, the incorrectness doesn't end there: (1) means that all recursive
    occurrences of names within the group will be given the same fingerprint. This
    means that the group's fingerprint won't change if we change an occurrence of A
    to B.

    Surprisingly, this bug (#18733) lurked for many years before being uncovered.

    How we now fingerprint
    ----------------------

    As seen above, the fingerprinting function must ensure that a groups
    fingerprint captures the structure of within-group occurrences. The scheme that
    we use is:

     0. To ensure determinism, sort the declarations into a stable order by
        declaration name

     1. Extend hash_env0, giving each declaration in the group a sequential
        fingerprint (e.g. 0, 1, 2, ...).

     2. Use this environment to hash the declarations' ABIs, resulting in
        group_fingerprint.

        Since we included the sequence number in step (1) programs identical up to
        transposition of recursive occurrences are distinguishable, avoiding the
        second issue mentioned above.

     3. Produce the final environment by extending hash_env, mapping each
        declaration of the group to the hash of (group_fingerprint, i), where
        i is the position of the declaration in the stable ordering.

        Including i in the hash ensures that the first issue noted above is
        avoided.

    -}

    -- | Add fingerprints for top-level declarations to a 'ModIface'.
    --
    -- See Note [Fingerprinting IfaceDecls]
    addFingerprints
            :: HscEnv
            -> PartialModIface
            -> IO ModIface
    addFingerprints :: HscEnv -> PartialModIface -> IO ModIface
    addFingerprints HscEnv
    hsc_env PartialModIface
    iface0
     = do
       eps <- HscEnv -> IO ExternalPackageState
    hscEPS HscEnv
    hsc_env
       let
           decls = PartialModIface -> [IfaceDeclExts 'ModIfaceCore]
    forall (phase :: ModIfacePhase).
    ModIface_ phase -> [IfaceDeclExts phase]
    mi_decls PartialModIface
    iface0
           decl_warn_fn = Warnings GhcRn -> OccName -> Maybe (WarningTxt GhcRn)
    forall p. Warnings p -> OccName -> Maybe (WarningTxt p)
    mkIfaceDeclWarnCache (IfaceWarnings -> Warnings GhcRn
    fromIfaceWarnings (IfaceWarnings -> Warnings GhcRn)
    -> IfaceWarnings -> Warnings GhcRn
    forall a b. (a -> b) -> a -> b
    $ PartialModIface -> IfaceWarnings
    forall (phase :: ModIfacePhase). ModIface_ phase -> IfaceWarnings
    mi_warns PartialModIface
    iface0)
           export_warn_fn = Warnings GhcRn -> Name -> Maybe (WarningTxt GhcRn)
    forall p. Warnings p -> Name -> Maybe (WarningTxt p)
    mkIfaceExportWarnCache (IfaceWarnings -> Warnings GhcRn
    fromIfaceWarnings (IfaceWarnings -> Warnings GhcRn)
    -> IfaceWarnings -> Warnings GhcRn
    forall a b. (a -> b) -> a -> b
    $ PartialModIface -> IfaceWarnings
    forall (phase :: ModIfacePhase). ModIface_ phase -> IfaceWarnings
    mi_warns PartialModIface
    iface0)
           fix_fn = [(OccName, Fixity)] -> OccName -> Maybe Fixity
    mkIfaceFixCache (PartialModIface -> [(OccName, Fixity)]
    forall (phase :: ModIfacePhase).
    ModIface_ phase -> [(OccName, Fixity)]
    mi_fixities PartialModIface
    iface0)

            -- The ABI of a declaration represents everything that is made
            -- visible about the declaration that a client can depend on.
            -- see IfaceDeclABI below.
           declABI :: IfaceDecl -> IfaceDeclABI
           -- TODO: I'm not sure if this should be semantic_mod or this_mod.
           -- See also Note [Identity versus semantic module]
           declABI IfaceDecl
    decl = (Module
    this_mod, IfaceDecl
    decl, IfaceDeclExtras
    extras)
            where extras :: IfaceDeclExtras
    extras = (OccName -> Maybe Fixity)
    -> (OccName -> [AnnPayload])
    -> OccEnv [IfaceRule]
    -> OccEnv [IfaceClsInst]
    -> OccEnv [IfaceFamInst]
    -> OccEnv Name
    -> IfaceDecl
    -> IfaceDeclExtras
    declExtras OccName -> Maybe Fixity
    fix_fn OccName -> [AnnPayload]
    ann_fn OccEnv [IfaceRule]
    non_orph_rules OccEnv [IfaceClsInst]
    non_orph_insts
                                      OccEnv [IfaceFamInst]
    non_orph_fis OccEnv Name
    top_lvl_name_env IfaceDecl
    decl

           -- This is used for looking up the Name of a default method
           -- from its OccName. See Note [default method Name]
           top_lvl_name_env =
             [(OccName, Name)] -> OccEnv Name
    forall a. [(OccName, a)] -> OccEnv a
    mkOccEnv [ (Name -> OccName
    nameOccName Name
    nm, Name
    nm)
                      | IfaceId { ifName :: IfaceDecl -> Name
    ifName = Name
    nm } <- [IfaceDecl]
    [IfaceDeclExts 'ModIfaceCore]
    decls ]

           -- Dependency edges between declarations in the current module.
           -- This is computed by finding the free external names of each
           -- declaration, including IfaceDeclExtras (things that a
           -- declaration implicitly depends on).
           edges :: [ Node OccName IfaceDeclABI ]
           edges = [ IfaceDeclABI -> OccName -> [OccName] -> Node OccName IfaceDeclABI
    forall key payload. payload -> key -> [key] -> Node key payload
    DigraphNode IfaceDeclABI
    abi (IfaceDecl -> OccName
    forall a. NamedThing a => a -> OccName
    getOccName IfaceDecl
    decl) [OccName]
    out
                   | IfaceDecl
    decl <- [IfaceDecl]
    [IfaceDeclExts 'ModIfaceCore]
    decls
                   , let abi :: IfaceDeclABI
    abi = IfaceDecl -> IfaceDeclABI
    declABI IfaceDecl
    decl
                   , let out :: [OccName]
    out = UniqSet Name -> [OccName]
    localOccs (UniqSet Name -> [OccName]) -> UniqSet Name -> [OccName]
    forall a b. (a -> b) -> a -> b
    $ IfaceDeclABI -> UniqSet Name
    freeNamesDeclABI IfaceDeclABI
    abi
                   ]

           name_module Name
    n = AnyHpcUsage -> SDoc -> Module -> Module
    forall a. HasCallStack => AnyHpcUsage -> SDoc -> a -> a
    assertPpr (Name -> AnyHpcUsage
    isExternalName Name
    n) (Name -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Name
    n) (HasDebugCallStack => Name -> Module
    Name -> Module
    nameModule Name
    n)
           localOccs =
             (Name -> OccName) -> [Name] -> [OccName]
    forall a b. (a -> b) -> [a] -> [b]
    map (OccName -> OccName
    getParent (OccName -> OccName) -> (Name -> OccName) -> Name -> OccName
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Name -> OccName
    forall a. NamedThing a => a -> OccName
    getOccName)
                            -- NB: names always use semantic module, so
                            -- filtering must be on the semantic module!
                            -- See Note [Identity versus semantic module]
                            ([Name] -> [OccName])
    -> (UniqSet Name -> [Name]) -> UniqSet Name -> [OccName]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Name -> AnyHpcUsage) -> [Name] -> [Name]
    forall a. (a -> AnyHpcUsage) -> [a] -> [a]
    filter ((Module -> Module -> AnyHpcUsage
    forall a. Eq a => a -> a -> AnyHpcUsage
    == Module
    semantic_mod) (Module -> AnyHpcUsage) -> (Name -> Module) -> Name -> AnyHpcUsage
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Name -> Module
    name_module)
                            ([Name] -> [Name])
    -> (UniqSet Name -> [Name]) -> UniqSet Name -> [Name]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . UniqSet Name -> [Name]
    forall elt. UniqSet elt -> [elt]
    nonDetEltsUniqSet
                       -- It's OK to use nonDetEltsUFM as localOccs is only
                       -- used to construct the edges and
                       -- stronglyConnCompFromEdgedVertices is deterministic
                       -- even with non-deterministic order of edges as
                       -- explained in Note [Deterministic SCC] in GHC.Data.Graph.Directed.
              where getParent :: OccName -> OccName
                    getParent :: OccName -> OccName
    getParent OccName
    occ = OccEnv OccName -> OccName -> Maybe OccName
    forall a. OccEnv a -> OccName -> Maybe a
    lookupOccEnv OccEnv OccName
    parent_map OccName
    occ Maybe OccName -> OccName -> OccName
    forall a. Maybe a -> a -> a
    `orElse` OccName
    occ

            -- maps OccNames to their parents in the current module.
            -- e.g. a reference to a constructor must be turned into a reference
            -- to the TyCon for the purposes of calculating dependencies.
           parent_map :: OccEnv OccName
           parent_map = (OccEnv OccName -> IfaceDecl -> OccEnv OccName)
    -> OccEnv OccName -> [IfaceDecl] -> OccEnv OccName
    forall b a. (b -> a -> b) -> b -> [a] -> b
    forall (t :: * -> *) b a.
    Foldable t =>
    (b -> a -> b) -> b -> t a -> b
    foldl' OccEnv OccName -> IfaceDecl -> OccEnv OccName
    extend OccEnv OccName
    forall a. OccEnv a
    emptyOccEnv [IfaceDecl]
    [IfaceDeclExts 'ModIfaceCore]
    decls
              where extend :: OccEnv OccName -> IfaceDecl -> OccEnv OccName
    extend OccEnv OccName
    env IfaceDecl
    d =
                      OccEnv OccName -> [(OccName, OccName)] -> OccEnv OccName
    forall a. OccEnv a -> [(OccName, a)] -> OccEnv a
    extendOccEnvList OccEnv OccName
    env [ (OccName
    b,OccName
    n) | OccName
    b <- IfaceDecl -> [OccName]
    ifaceDeclImplicitBndrs IfaceDecl
    d ]
                      where n :: OccName
    n = IfaceDecl -> OccName
    forall a. NamedThing a => a -> OccName
    getOccName IfaceDecl
    d

            -- Strongly-connected groups of declarations, in dependency order
           groups :: [SCC IfaceDeclABI]
           groups = [Node OccName IfaceDeclABI] -> [SCC IfaceDeclABI]
    forall key payload. Ord key => [Node key payload] -> [SCC payload]
    stronglyConnCompFromEdgedVerticesOrd [Node OccName IfaceDeclABI]
    edges

           global_hash_fn = HscEnv -> ExternalPackageState -> Name -> IO Fingerprint
    mkHashFun HscEnv
    hsc_env ExternalPackageState
    eps

            -- How to output Names when generating the data to fingerprint.
            -- Here we want to output the fingerprint for each top-level
            -- Name, whether it comes from the current module or another
            -- module.  In this way, the fingerprint for a declaration will
            -- change if the fingerprint for anything it refers to (transitively)
            -- changes.
           mk_put_name :: OccEnv (OccName,Fingerprint)
                       -> BinHandle -> Name -> IO  ()
           mk_put_name OccEnv (OccName, Fingerprint)
    local_env BinHandle
    bh Name
    name
              | Name -> AnyHpcUsage
    isWiredInName Name
    name  =  BinHandle -> Name -> IO ()
    putNameLiterally BinHandle
    bh Name
    name
               -- wired-in names don't have fingerprints
              | AnyHpcUsage
    otherwise
              = AnyHpcUsage -> SDoc -> IO () -> IO ()
    forall a. HasCallStack => AnyHpcUsage -> SDoc -> a -> a
    assertPpr (Name -> AnyHpcUsage
    isExternalName Name
    name) (Name -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Name
    name) (IO () -> IO ()) -> IO () -> IO ()
    forall a b. (a -> b) -> a -> b
    $
                let hash :: IO Fingerprint
    hash | HasDebugCallStack => Name -> Module
    Name -> Module
    nameModule Name
    name Module -> Module -> AnyHpcUsage
    forall a. Eq a => a -> a -> AnyHpcUsage
    /= Module
    semantic_mod =  Name -> IO Fingerprint
    global_hash_fn Name
    name
                         -- Get it from the REAL interface!!
                         -- This will trigger when we compile an hsig file
                         -- and we know a backing impl for it.
                         -- See Note [Identity versus semantic module]
                         | Module
    semantic_mod Module -> Module -> AnyHpcUsage
    forall a. Eq a => a -> a -> AnyHpcUsage
    /= Module
    this_mod
                         , AnyHpcUsage -> AnyHpcUsage
    not (Module -> AnyHpcUsage
    forall u. GenModule (GenUnit u) -> AnyHpcUsage
    isHoleModule Module
    semantic_mod) = Name -> IO Fingerprint
    global_hash_fn Name
    name
                         | AnyHpcUsage
    otherwise = Fingerprint -> IO Fingerprint
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ((OccName, Fingerprint) -> Fingerprint
    forall a b. (a, b) -> b
    snd (OccEnv (OccName, Fingerprint)
    -> OccName -> Maybe (OccName, Fingerprint)
    forall a. OccEnv a -> OccName -> Maybe a
    lookupOccEnv OccEnv (OccName, Fingerprint)
    local_env (Name -> OccName
    forall a. NamedThing a => a -> OccName
    getOccName Name
    name)
                               Maybe (OccName, Fingerprint)
    -> (OccName, Fingerprint) -> (OccName, Fingerprint)
    forall a. Maybe a -> a -> a
    `orElse` String -> SDoc -> (OccName, Fingerprint)
    forall a. HasCallStack => String -> SDoc -> a
    pprPanic String
    "urk! lookup local fingerprint"
                                           (Name -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Name
    name SDoc -> SDoc -> SDoc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$ OccEnv (OccName, Fingerprint) -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr OccEnv (OccName, Fingerprint)
    local_env)))
                    -- This panic indicates that we got the dependency
                    -- analysis wrong, because we needed a fingerprint for
                    -- an entity that wasn't in the environment.  To debug
                    -- it, turn the panic into a trace, uncomment the
                    -- pprTraces below, run the compile again, and inspect
                    -- the output and the generated .hi file with
                    -- --show-iface.
                in IO Fingerprint
    hash IO Fingerprint -> (Fingerprint -> IO ()) -> IO ()
    forall a b. IO a -> (a -> IO b) -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= BinHandle -> Fingerprint -> IO ()
    forall a. Binary a => BinHandle -> a -> IO ()
    put_ BinHandle
    bh

            -- take a strongly-connected group of declarations and compute
            -- its fingerprint.

           fingerprint_group :: (OccEnv (OccName,Fingerprint),
                                 [(Fingerprint,IfaceDecl)])
                             -> SCC IfaceDeclABI
                             -> IO (OccEnv (OccName,Fingerprint),
                                    [(Fingerprint,IfaceDecl)])

           fingerprint_group (OccEnv (OccName, Fingerprint)
    local_env, [(Fingerprint, IfaceDecl)]
    decls_w_hashes) (AcyclicSCC IfaceDeclABI
    abi)
              = do let hash_fn :: BinHandle -> Name -> IO ()
    hash_fn = OccEnv (OccName, Fingerprint) -> BinHandle -> Name -> IO ()
    mk_put_name OccEnv (OccName, Fingerprint)
    local_env
                       decl :: IfaceDecl
    decl = IfaceDeclABI -> IfaceDecl
    abiDecl IfaceDeclABI
    abi
                   --pprTrace "fingerprinting" (ppr (ifName decl) ) $ do
                   hash <- (BinHandle -> Name -> IO ()) -> IfaceDeclABI -> IO Fingerprint
    forall a.
    Binary a =>
    (BinHandle -> Name -> IO ()) -> a -> IO Fingerprint
    computeFingerprint BinHandle -> Name -> IO ()
    hash_fn IfaceDeclABI
    abi
                   env' <- extend_hash_env local_env (hash,decl)
                   return (env', (hash,decl) : decls_w_hashes)

           fingerprint_group (OccEnv (OccName, Fingerprint)
    local_env, [(Fingerprint, IfaceDecl)]
    decls_w_hashes) (CyclicSCC [IfaceDeclABI]
    abis)
              = do let stable_abis :: [IfaceDeclABI]
    stable_abis = (IfaceDeclABI -> IfaceDeclABI -> Ordering)
    -> [IfaceDeclABI] -> [IfaceDeclABI]
    forall a. (a -> a -> Ordering) -> [a] -> [a]
    sortBy IfaceDeclABI -> IfaceDeclABI -> Ordering
    cmp_abiNames [IfaceDeclABI]
    abis
                       stable_decls :: [IfaceDecl]
    stable_decls = (IfaceDeclABI -> IfaceDecl) -> [IfaceDeclABI] -> [IfaceDecl]
    forall a b. (a -> b) -> [a] -> [b]
    map IfaceDeclABI -> IfaceDecl
    abiDecl [IfaceDeclABI]
    stable_abis
                   local_env1 <- (OccEnv (OccName, Fingerprint)
     -> (Fingerprint, IfaceDecl) -> IO (OccEnv (OccName, Fingerprint)))
    -> OccEnv (OccName, Fingerprint)
    -> [(Fingerprint, IfaceDecl)]
    -> IO (OccEnv (OccName, Fingerprint))
    forall (t :: * -> *) (m :: * -> *) b a.
    (Foldable t, Monad m) =>
    (b -> a -> m b) -> b -> t a -> m b
    foldM OccEnv (OccName, Fingerprint)
    -> (Fingerprint, IfaceDecl) -> IO (OccEnv (OccName, Fingerprint))
    extend_hash_env OccEnv (OccName, Fingerprint)
    local_env
                                       ([Fingerprint] -> [IfaceDecl] -> [(Fingerprint, IfaceDecl)]
    forall a b. [a] -> [b] -> [(a, b)]
    zip ((Word64 -> Fingerprint) -> [Word64] -> [Fingerprint]
    forall a b. (a -> b) -> [a] -> [b]
    map Word64 -> Fingerprint
    mkRecFingerprint [Word64
    0..]) [IfaceDecl]
    stable_decls)
                    -- See Note [Fingerprinting recursive groups]
                   let hash_fn = OccEnv (OccName, Fingerprint) -> BinHandle -> Name -> IO ()
    mk_put_name OccEnv (OccName, Fingerprint)
    local_env1
                   -- pprTrace "fingerprinting" (ppr (map ifName decls) ) $ do
                    -- put the cycle in a canonical order
                   hash <- computeFingerprint hash_fn stable_abis
                   let pairs = [Fingerprint] -> [IfaceDecl] -> [(Fingerprint, IfaceDecl)]
    forall a b. [a] -> [b] -> [(a, b)]
    zip ((Word64 -> Fingerprint) -> [Word64] -> [Fingerprint]
    forall a b. (a -> b) -> [a] -> [b]
    map (Fingerprint -> Word64 -> Fingerprint
    bumpFingerprint Fingerprint
    hash) [Word64
    0..]) [IfaceDecl]
    stable_decls
                    -- See Note [Fingerprinting recursive groups]
                   local_env2 <- foldM extend_hash_env local_env pairs
                   return (local_env2, pairs ++ decls_w_hashes)

           -- Make a fingerprint from the ordinal position of a binding in its group.
           mkRecFingerprint :: Word64 -> Fingerprint
           mkRecFingerprint Word64
    i = Word64 -> Word64 -> Fingerprint
    Fingerprint Word64
    0 Word64
    i

           bumpFingerprint :: Fingerprint -> Word64 -> Fingerprint
           bumpFingerprint Fingerprint
    fp Word64
    n = [Fingerprint] -> Fingerprint
    fingerprintFingerprints [ Fingerprint
    fp, Word64 -> Fingerprint
    mkRecFingerprint Word64
    n ]

           -- we have fingerprinted the whole declaration, but we now need
           -- to assign fingerprints to all the OccNames that it binds, to
           -- use when referencing those OccNames in later declarations.
           --
           extend_hash_env :: OccEnv (OccName,Fingerprint)
                           -> (Fingerprint,IfaceDecl)
                           -> IO (OccEnv (OccName,Fingerprint))
           extend_hash_env OccEnv (OccName, Fingerprint)
    env0 (Fingerprint
    hash,IfaceDecl
    d) =
              OccEnv (OccName, Fingerprint) -> IO (OccEnv (OccName, Fingerprint))
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (((OccName, Fingerprint)
     -> OccEnv (OccName, Fingerprint) -> OccEnv (OccName, Fingerprint))
    -> OccEnv (OccName, Fingerprint)
    -> [(OccName, Fingerprint)]
    -> OccEnv (OccName, Fingerprint)
    forall a b. (a -> b -> b) -> b -> [a] -> b
    forall (t :: * -> *) a b.
    Foldable t =>
    (a -> b -> b) -> b -> t a -> b
    foldr (\(OccName
    b,Fingerprint
    fp) OccEnv (OccName, Fingerprint)
    env -> OccEnv (OccName, Fingerprint)
    -> OccName
    -> (OccName, Fingerprint)
    -> OccEnv (OccName, Fingerprint)
    forall a. OccEnv a -> OccName -> a -> OccEnv a
    extendOccEnv OccEnv (OccName, Fingerprint)
    env OccName
    b (OccName
    b,Fingerprint
    fp)) OccEnv (OccName, Fingerprint)
    env0
                     (Fingerprint -> IfaceDecl -> [(OccName, Fingerprint)]
    ifaceDeclFingerprints Fingerprint
    hash IfaceDecl
    d))

       --
       (local_env, decls_w_hashes) <-
           foldM fingerprint_group (emptyOccEnv, []) groups

       -- when calculating fingerprints, we always need to use canonical ordering
       -- for lists of things. The mi_deps has various lists of modules and
       -- suchlike, which are stored in canonical order:
       let sorted_deps :: Dependencies
           sorted_deps = PartialModIface -> Dependencies
    forall (phase :: ModIfacePhase). ModIface_ phase -> Dependencies
    mi_deps PartialModIface
    iface0

       -- The export hash of a module depends on the orphan hashes of the
       -- orphan modules below us in the dependency tree.  This is the way
       -- that changes in orphans get propagated all the way up the
       -- dependency tree.
       --
       -- Note [A bad dep_orphs optimization]
       -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       -- In a previous version of this code, we filtered out orphan modules which
       -- were not from the home package, justifying it by saying that "we'd
       -- pick up the ABI hashes of the external module instead".  This is wrong.
       -- Suppose that we have:
       --
       --       module External where
       --           instance Show (a -> b)
       --
       --       module Home1 where
       --           import External
       --
       --       module Home2 where
       --           import Home1
       --
       -- The export hash of Home1 needs to reflect the orphan instances of
       -- External. It's true that Home1 will get rebuilt if the orphans
       -- of External, but we also need to make sure Home2 gets rebuilt
       -- as well.  See #12733 for more details.
       let orph_mods
            = (Module -> AnyHpcUsage) -> [Module] -> [Module]
    forall a. (a -> AnyHpcUsage) -> [a] -> [a]
    filter (Module -> Module -> AnyHpcUsage
    forall a. Eq a => a -> a -> AnyHpcUsage
    /= Module
    this_mod) -- Note [Do not update EPS with your own hi-boot]
            ([Module] -> [Module]) -> [Module] -> [Module]
    forall a b. (a -> b) -> a -> b
    $ Dependencies -> [Module]
    dep_orphs Dependencies
    sorted_deps
       dep_orphan_hashes <- getOrphanHashes hsc_env orph_mods

       -- Note [Do not update EPS with your own hi-boot]
       -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       -- (See also #10182).  When your hs-boot file includes an orphan
       -- instance declaration, you may find that the dep_orphs of a module you
       -- import contains reference to yourself.  DO NOT actually load this module
       -- or add it to the orphan hashes: you're going to provide the orphan
       -- instances yourself, no need to consult hs-boot; if you do load the
       -- interface into EPS, you will see a duplicate orphan instance.

       orphan_hash <- computeFingerprint (mk_put_name local_env)
                                         (map ifDFun orph_insts, orph_rules, orph_fis)

       -- Hash of the transitive things in dependencies
       dep_hash <- computeFingerprint putNameLiterally
                           (dep_sig_mods (mi_deps iface0),
                            dep_boot_mods (mi_deps iface0),
                            -- Trusted packages are like orphans
                            dep_trusted_pkgs (mi_deps iface0),
                           -- See Note [Export hash depends on non-orphan family instances]
                            dep_finsts (mi_deps iface0) )

       -- the export list hash doesn't depend on the fingerprints of
       -- the Names it mentions, only the Names themselves, hence putNameLiterally.
       export_hash <- computeFingerprint putNameLiterally
                          (mi_exports iface0,
                           orphan_hash,
                           dep_hash,
                           dep_orphan_hashes,
                           mi_trust iface0)
                            -- Make sure change of Safe Haskell mode causes recomp.

       -- Note [Export hash depends on non-orphan family instances]
       -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       --
       -- Suppose we have:
       --
       --   module A where
       --       type instance F Int = Bool
       --
       --   module B where
       --       import A
       --
       --   module C where
       --       import B
       --
       -- The family instance consistency check for C depends on the dep_finsts of
       -- B.  If we rename module A to A2, when the dep_finsts of B changes, we need
       -- to make sure that C gets rebuilt. Effectively, the dep_finsts are part of
       -- the exports of B, because C always considers them when checking
       -- consistency.
       --
       -- A full discussion is in #12723.
       --
       -- We do NOT need to hash dep_orphs, because this is implied by
       -- dep_orphan_hashes, and we do not need to hash ordinary class instances,
       -- because there is no eager consistency check as there is with type families
       -- (also we didn't store it anywhere!)
       --

       -- put the declarations in a canonical order, sorted by OccName
       let sorted_decls :: [(Fingerprint, IfaceDecl)]
           sorted_decls = Map OccName (Fingerprint, IfaceDecl) -> [(Fingerprint, IfaceDecl)]
    forall k a. Map k a -> [a]
    Map.elems (Map OccName (Fingerprint, IfaceDecl)
     -> [(Fingerprint, IfaceDecl)])
    -> Map OccName (Fingerprint, IfaceDecl)
    -> [(Fingerprint, IfaceDecl)]
    forall a b. (a -> b) -> a -> b
    $ [(OccName, (Fingerprint, IfaceDecl))]
    -> Map OccName (Fingerprint, IfaceDecl)
    forall k a. Ord k => [(k, a)] -> Map k a
    Map.fromList ([(OccName, (Fingerprint, IfaceDecl))]
     -> Map OccName (Fingerprint, IfaceDecl))
    -> [(OccName, (Fingerprint, IfaceDecl))]
    -> Map OccName (Fingerprint, IfaceDecl)
    forall a b. (a -> b) -> a -> b
    $
                              [(IfaceDecl -> OccName
    forall a. NamedThing a => a -> OccName
    getOccName IfaceDecl
    d, (Fingerprint, IfaceDecl)
    e) | e :: (Fingerprint, IfaceDecl)
    e@(Fingerprint
    _, IfaceDecl
    d) <- [(Fingerprint, IfaceDecl)]
    decls_w_hashes]

           -- This key is safe because mi_extra_decls contains tidied things.
           getOcc (IfGblTopBndr Name
    b) = Name -> OccName
    forall a. NamedThing a => a -> OccName
    getOccName Name
    b
           getOcc (IfLclTopBndr FastString
    fs IfaceType
    _ IfaceIdInfo
    _ IfaceIdDetails
    details) =
            case IfaceIdDetails
    details of
              IfRecSelId { ifRecSelFirstCon :: IfaceIdDetails -> Name
    ifRecSelFirstCon = Name
    first_con }
                -> FastString -> FastString -> OccName
    mkRecFieldOccFS (Name -> FastString
    forall a. NamedThing a => a -> FastString
    getOccFS Name
    first_con) FastString
    fs
              IfaceIdDetails
    _ -> FastString -> OccName
    mkVarOccFS FastString
    fs

           binding_key (IfaceNonRec IfaceTopBndrInfo
    b b
    _) = OccName -> () -> IfaceBindingX () OccName
    forall r b. b -> r -> IfaceBindingX r b
    IfaceNonRec (IfaceTopBndrInfo -> OccName
    getOcc IfaceTopBndrInfo
    b) ()
           binding_key (IfaceRec [(IfaceTopBndrInfo, b)]
    bs) = [(OccName, ())] -> IfaceBindingX () OccName
    forall r b. [(b, r)] -> IfaceBindingX r b
    IfaceRec (((IfaceTopBndrInfo, b) -> (OccName, ()))
    -> [(IfaceTopBndrInfo, b)] -> [(OccName, ())]
    forall a b. (a -> b) -> [a] -> [b]
    map (\(IfaceTopBndrInfo
    b, b
    _) -> (IfaceTopBndrInfo -> OccName
    getOcc IfaceTopBndrInfo
    b, ())) [(IfaceTopBndrInfo, b)]
    bs)

           sorted_extra_decls :: Maybe [IfaceBindingX IfaceMaybeRhs IfaceTopBndrInfo]
           sorted_extra_decls = (IfaceBindingX IfaceMaybeRhs IfaceTopBndrInfo
     -> IfaceBindingX () OccName)
    -> [IfaceBindingX IfaceMaybeRhs IfaceTopBndrInfo]
    -> [IfaceBindingX IfaceMaybeRhs IfaceTopBndrInfo]
    forall b a. Ord b => (a -> b) -> [a] -> [a]
    sortOn IfaceBindingX IfaceMaybeRhs IfaceTopBndrInfo
    -> IfaceBindingX () OccName
    forall {b}.
    IfaceBindingX b IfaceTopBndrInfo -> IfaceBindingX () OccName
    binding_key ([IfaceBindingX IfaceMaybeRhs IfaceTopBndrInfo]
     -> [IfaceBindingX IfaceMaybeRhs IfaceTopBndrInfo])
    -> Maybe [IfaceBindingX IfaceMaybeRhs IfaceTopBndrInfo]
    -> Maybe [IfaceBindingX IfaceMaybeRhs IfaceTopBndrInfo]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> PartialModIface
    -> Maybe [IfaceBindingX IfaceMaybeRhs IfaceTopBndrInfo]
    forall (phase :: ModIfacePhase).
    ModIface_ phase
    -> Maybe [IfaceBindingX IfaceMaybeRhs IfaceTopBndrInfo]
    mi_extra_decls PartialModIface
    iface0

       -- the flag hash depends on:
       --   - (some of) dflags
       -- it returns two hashes, one that shouldn't change
       -- the abi hash and one that should
       flag_hash <- fingerprintDynFlags hsc_env this_mod putNameLiterally

       opt_hash <- fingerprintOptFlags dflags putNameLiterally

       hpc_hash <- fingerprintHpcFlags dflags putNameLiterally

       plugin_hash <- fingerprintPlugins (hsc_plugins hsc_env)

       -- the ABI hash depends on:
       --   - decls
       --   - export list
       --   - orphans
       --   - deprecations
       --   - flag abi hash
       mod_hash <- computeFingerprint putNameLiterally
                          (map fst sorted_decls,
                           export_hash,  -- includes orphan_hash
                           mi_warns iface0)

       -- The interface hash depends on:
       --   - the ABI hash, plus
       --   - the source file hash,
       --   - the module level annotations,
       --   - usages
       --   - deps (home and external packages, dependent files)
       --   - hpc
       iface_hash <- computeFingerprint putNameLiterally
                          (mod_hash,
                           mi_src_hash iface0,
                           ann_fn (mkVarOccFS (fsLit "module")),  -- See mkIfaceAnnCache
                           mi_usages iface0,
                           sorted_deps,
                           mi_hpc iface0)

       let
        final_iface_exts = ModIfaceBackend
          { mi_iface_hash :: Fingerprint
    mi_iface_hash     = Fingerprint
    iface_hash
          , mi_mod_hash :: Fingerprint
    mi_mod_hash       = Fingerprint
    mod_hash
          , mi_flag_hash :: Fingerprint
    mi_flag_hash      = Fingerprint
    flag_hash
          , mi_opt_hash :: Fingerprint
    mi_opt_hash       = Fingerprint
    opt_hash
          , mi_hpc_hash :: Fingerprint
    mi_hpc_hash       = Fingerprint
    hpc_hash
          , mi_plugin_hash :: Fingerprint
    mi_plugin_hash    = Fingerprint
    plugin_hash
          , mi_orphan :: AnyHpcUsage
    mi_orphan         = AnyHpcUsage -> AnyHpcUsage
    not (   (IfaceRule -> AnyHpcUsage) -> [IfaceRule] -> AnyHpcUsage
    forall (t :: * -> *) a.
    Foldable t =>
    (a -> AnyHpcUsage) -> t a -> AnyHpcUsage
    all IfaceRule -> AnyHpcUsage
    ifRuleAuto [IfaceRule]
    orph_rules
                                          -- See Note [Orphans and auto-generated rules]
                                     AnyHpcUsage -> AnyHpcUsage -> AnyHpcUsage
    && [IfaceClsInst] -> AnyHpcUsage
    forall a. [a] -> AnyHpcUsage
    forall (t :: * -> *) a. Foldable t => t a -> AnyHpcUsage
    null [IfaceClsInst]
    orph_insts
                                     AnyHpcUsage -> AnyHpcUsage -> AnyHpcUsage
    && [IfaceFamInst] -> AnyHpcUsage
    forall a. [a] -> AnyHpcUsage
    forall (t :: * -> *) a. Foldable t => t a -> AnyHpcUsage
    null [IfaceFamInst]
    orph_fis)
          , mi_finsts :: AnyHpcUsage
    mi_finsts         = AnyHpcUsage -> AnyHpcUsage
    not ([IfaceFamInst] -> AnyHpcUsage
    forall a. [a] -> AnyHpcUsage
    forall (t :: * -> *) a. Foldable t => t a -> AnyHpcUsage
    null (PartialModIface -> [IfaceFamInst]
    forall (phase :: ModIfacePhase). ModIface_ phase -> [IfaceFamInst]
    mi_fam_insts PartialModIface
    iface0))
          , mi_exp_hash :: Fingerprint
    mi_exp_hash       = Fingerprint
    export_hash
          , mi_orphan_hash :: Fingerprint
    mi_orphan_hash    = Fingerprint
    orphan_hash
          , mi_decl_warn_fn :: OccName -> Maybe (WarningTxt GhcRn)
    mi_decl_warn_fn   = OccName -> Maybe (WarningTxt GhcRn)
    decl_warn_fn
          , mi_export_warn_fn :: Name -> Maybe (WarningTxt GhcRn)
    mi_export_warn_fn = Name -> Maybe (WarningTxt GhcRn)
    export_warn_fn
          , mi_fix_fn :: OccName -> Maybe Fixity
    mi_fix_fn         = OccName -> Maybe Fixity
    fix_fn
          , mi_hash_fn :: OccName -> Maybe (OccName, Fingerprint)
    mi_hash_fn        = OccEnv (OccName, Fingerprint)
    -> OccName -> Maybe (OccName, Fingerprint)
    forall a. OccEnv a -> OccName -> Maybe a
    lookupOccEnv OccEnv (OccName, Fingerprint)
    local_env
          }
        final_iface = PartialModIface
    iface0 { mi_decls = sorted_decls, mi_extra_decls = sorted_extra_decls, mi_final_exts = final_iface_exts }
       --
       return final_iface

      where
        this_mod :: Module
    this_mod = PartialModIface -> Module
    forall (phase :: ModIfacePhase). ModIface_ phase -> Module
    mi_module PartialModIface
    iface0
        semantic_mod :: Module
    semantic_mod = PartialModIface -> Module
    forall (phase :: ModIfacePhase). ModIface_ phase -> Module
    mi_semantic_module PartialModIface
    iface0
        dflags :: DynFlags
    dflags = HscEnv -> DynFlags
    hsc_dflags HscEnv
    hsc_env
        (OccEnv [IfaceClsInst]
    non_orph_insts, [IfaceClsInst]
    orph_insts) = (IfaceClsInst -> IsOrphan)
    -> [IfaceClsInst] -> (OccEnv [IfaceClsInst], [IfaceClsInst])
    forall decl.
    (decl -> IsOrphan) -> [decl] -> (OccEnv [decl], [decl])
    mkOrphMap IfaceClsInst -> IsOrphan
    ifInstOrph    (PartialModIface -> [IfaceClsInst]
    forall (phase :: ModIfacePhase). ModIface_ phase -> [IfaceClsInst]
    mi_insts PartialModIface
    iface0)
        (OccEnv [IfaceRule]
    non_orph_rules, [IfaceRule]
    orph_rules) = (IfaceRule -> IsOrphan)
    -> [IfaceRule] -> (OccEnv [IfaceRule], [IfaceRule])
    forall decl.
    (decl -> IsOrphan) -> [decl] -> (OccEnv [decl], [decl])
    mkOrphMap IfaceRule -> IsOrphan
    ifRuleOrph    (PartialModIface -> [IfaceRule]
    forall (phase :: ModIfacePhase). ModIface_ phase -> [IfaceRule]
    mi_rules PartialModIface
    iface0)
        (OccEnv [IfaceFamInst]
    non_orph_fis,   [IfaceFamInst]
    orph_fis)   = (IfaceFamInst -> IsOrphan)
    -> [IfaceFamInst] -> (OccEnv [IfaceFamInst], [IfaceFamInst])
    forall decl.
    (decl -> IsOrphan) -> [decl] -> (OccEnv [decl], [decl])
    mkOrphMap IfaceFamInst -> IsOrphan
    ifFamInstOrph (PartialModIface -> [IfaceFamInst]
    forall (phase :: ModIfacePhase). ModIface_ phase -> [IfaceFamInst]
    mi_fam_insts PartialModIface
    iface0)
        ann_fn :: OccName -> [AnnPayload]
    ann_fn = [IfaceAnnotation] -> OccName -> [AnnPayload]
    mkIfaceAnnCache (PartialModIface -> [IfaceAnnotation]
    forall (phase :: ModIfacePhase).
    ModIface_ phase -> [IfaceAnnotation]
    mi_anns PartialModIface
    iface0)

    -- | Retrieve the orphan hashes 'mi_orphan_hash' for a list of modules
    -- (in particular, the orphan modules which are transitively imported by the
    -- current module).
    --
    -- Q: Why do we need the hash at all, doesn't the list of transitively
    -- imported orphan modules suffice?
    --
    -- A: If one of our transitive imports adds a new orphan instance, our
    -- export hash must change so that modules which import us rebuild.  If we just
    -- hashed the [Module], the hash would not change even when a new instance was
    -- added to a module that already had an orphan instance.
    --
    -- Q: Why don't we just hash the orphan hashes of our direct dependencies?
    -- Why the full transitive closure?
    --
    -- A: Suppose we have these modules:
    --
    --      module A where
    --          instance Show (a -> b) where
    --      module B where
    --          import A -- **
    --      module C where
    --          import A
    --          import B
    --
    -- Whether or not we add or remove the import to A in B affects the
    -- orphan hash of B.  But it shouldn't really affect the orphan hash
    -- of C.  If we hashed only direct dependencies, there would be no
    -- way to tell that the net effect was a wash, and we'd be forced
    -- to recompile C and everything else.
    getOrphanHashes :: HscEnv -> [Module] -> IO [Fingerprint]
    getOrphanHashes :: HscEnv -> [Module] -> IO [Fingerprint]
    getOrphanHashes HscEnv
    hsc_env [Module]
    mods = do
      let
        dflags :: DynFlags
    dflags     = HscEnv -> DynFlags
    hsc_dflags HscEnv
    hsc_env
        ctx :: SDocContext
    ctx        = DynFlags -> PprStyle -> SDocContext
    initSDocContext DynFlags
    dflags PprStyle
    defaultUserStyle
        get_orph_hash :: Module -> IO Fingerprint
    get_orph_hash Module
    mod = do
              iface <- HscEnv -> IfG ModIface -> IO ModIface
    forall a. HscEnv -> IfG a -> IO a
    initIfaceLoad HscEnv
    hsc_env (IfG ModIface -> IO ModIface)
    -> (IfM () (MaybeErr MissingInterfaceError ModIface)
        -> IfG ModIface)
    -> IfM () (MaybeErr MissingInterfaceError ModIface)
    -> IO ModIface
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . SDocContext
    -> IfM () (MaybeErr MissingInterfaceError ModIface) -> IfG ModIface
    forall (m :: * -> *) a.
    MonadIO m =>
    SDocContext -> m (MaybeErr MissingInterfaceError a) -> m a
    withIfaceErr SDocContext
    ctx
                                (IfM () (MaybeErr MissingInterfaceError ModIface) -> IO ModIface)
    -> IfM () (MaybeErr MissingInterfaceError ModIface) -> IO ModIface
    forall a b. (a -> b) -> a -> b
    $ SDoc
    -> Module
    -> WhereFrom
    -> IfM () (MaybeErr MissingInterfaceError ModIface)
    forall lcl.
    SDoc
    -> Module
    -> WhereFrom
    -> IfM lcl (MaybeErr MissingInterfaceError ModIface)
    loadInterface (String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "getOrphanHashes") Module
    mod WhereFrom
    ImportBySystem
              return (mi_orphan_hash (mi_final_exts iface))

      (Module -> IO Fingerprint) -> [Module] -> IO [Fingerprint]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    (a -> m b) -> t a -> m (t b)
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
    mapM Module -> IO Fingerprint
    get_orph_hash [Module]
    mods

    {-
    ************************************************************************
    *                                                                      *
              The ABI of an IfaceDecl
    *                                                                      *
    ************************************************************************

    Note [The ABI of an IfaceDecl]
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    The ABI of a declaration consists of:

       (a) the full name of the identifier (inc. module and package,
           because these are used to construct the symbol name by which
           the identifier is known externally).

       (b) the declaration itself, as exposed to clients.  That is, the
           definition of an Id is included in the fingerprint only if
           it is made available as an unfolding in the interface.

       (c) the fixity of the identifier (if it exists)
       (d) for Ids: rules
       (e) for classes: instances, fixity & rules for methods
       (f) for datatypes: instances, fixity & rules for constrs

    Items (c)-(f) are not stored in the IfaceDecl, but instead appear
    elsewhere in the interface file.  But they are *fingerprinted* with
    the declaration itself. This is done by grouping (c)-(f) in IfaceDeclExtras,
    and fingerprinting that as part of the declaration.
    -}

    type IfaceDeclABI = (Module, IfaceDecl, IfaceDeclExtras)

    data IfaceDeclExtras
      = IfaceIdExtras IfaceIdExtras

      | IfaceDataExtras
           (Maybe Fixity)           -- Fixity of the tycon itself (if it exists)
           [IfaceInstABI]           -- Local class and family instances of this tycon
                                    -- See Note [Orphans] in GHC.Core.InstEnv
           [AnnPayload]             -- Annotations of the type itself
           [IfaceIdExtras]          -- For each constructor: fixity, RULES and annotations

      | IfaceClassExtras
           (Maybe Fixity)           -- Fixity of the class itself (if it exists)
           [IfaceInstABI]           -- Local instances of this class *or*
                                    --   of its associated data types
                                    -- See Note [Orphans] in GHC.Core.InstEnv
           [AnnPayload]             -- Annotations of the type itself
           [IfaceIdExtras]          -- For each class method: fixity, RULES and annotations
           [IfExtName]              -- Default methods. If a module
                                    -- mentions a class, then it can
                                    -- instantiate the class and thereby
                                    -- use the default methods, so we must
                                    -- include these in the fingerprint of
                                    -- a class.

      | IfaceSynonymExtras (Maybe Fixity) [AnnPayload]

      | IfaceFamilyExtras   (Maybe Fixity) [IfaceInstABI] [AnnPayload]

      | IfaceOtherDeclExtras

    data IfaceIdExtras
      = IdExtras
           (Maybe Fixity)           -- Fixity of the Id (if it exists)
           [IfaceRule]              -- Rules for the Id
           [AnnPayload]             -- Annotations for the Id

    -- When hashing a class or family instance, we hash only the
    -- DFunId or CoAxiom, because that depends on all the
    -- information about the instance.
    --
    type IfaceInstABI = IfExtName   -- Name of DFunId or CoAxiom that is evidence for the instance

    abiDecl :: IfaceDeclABI -> IfaceDecl
    abiDecl :: IfaceDeclABI -> IfaceDecl
    abiDecl (Module
    _, IfaceDecl
    decl, IfaceDeclExtras
    _) = IfaceDecl
    decl

    cmp_abiNames :: IfaceDeclABI -> IfaceDeclABI -> Ordering
    cmp_abiNames :: IfaceDeclABI -> IfaceDeclABI -> Ordering
    cmp_abiNames IfaceDeclABI
    abi1 IfaceDeclABI
    abi2 = IfaceDecl -> OccName
    forall a. NamedThing a => a -> OccName
    getOccName (IfaceDeclABI -> IfaceDecl
    abiDecl IfaceDeclABI
    abi1) OccName -> OccName -> Ordering
    forall a. Ord a => a -> a -> Ordering
    `compare`
                             IfaceDecl -> OccName
    forall a. NamedThing a => a -> OccName
    getOccName (IfaceDeclABI -> IfaceDecl
    abiDecl IfaceDeclABI
    abi2)

    freeNamesDeclABI :: IfaceDeclABI -> NameSet
    freeNamesDeclABI :: IfaceDeclABI -> UniqSet Name
    freeNamesDeclABI (Module
    _mod, IfaceDecl
    decl, IfaceDeclExtras
    extras) =
      IfaceDecl -> UniqSet Name
    freeNamesIfDecl IfaceDecl
    decl UniqSet Name -> UniqSet Name -> UniqSet Name
    `unionNameSet` IfaceDeclExtras -> UniqSet Name
    freeNamesDeclExtras IfaceDeclExtras
    extras

    freeNamesDeclExtras :: IfaceDeclExtras -> NameSet
    freeNamesDeclExtras :: IfaceDeclExtras -> UniqSet Name
    freeNamesDeclExtras (IfaceIdExtras IfaceIdExtras
    id_extras)
      = IfaceIdExtras -> UniqSet Name
    freeNamesIdExtras IfaceIdExtras
    id_extras
    freeNamesDeclExtras (IfaceDataExtras  Maybe Fixity
    _ [Name]
    insts [AnnPayload]
    _ [IfaceIdExtras]
    subs)
      = [UniqSet Name] -> UniqSet Name
    unionNameSets ([Name] -> UniqSet Name
    mkNameSet [Name]
    insts UniqSet Name -> [UniqSet Name] -> [UniqSet Name]
    forall a. a -> [a] -> [a]
    : (IfaceIdExtras -> UniqSet Name)
    -> [IfaceIdExtras] -> [UniqSet Name]
    forall a b. (a -> b) -> [a] -> [b]
    map IfaceIdExtras -> UniqSet Name
    freeNamesIdExtras [IfaceIdExtras]
    subs)
    freeNamesDeclExtras (IfaceClassExtras Maybe Fixity
    _ [Name]
    insts [AnnPayload]
    _ [IfaceIdExtras]
    subs [Name]
    defms)
      = [UniqSet Name] -> UniqSet Name
    unionNameSets ([UniqSet Name] -> UniqSet Name) -> [UniqSet Name] -> UniqSet Name
    forall a b. (a -> b) -> a -> b
    $
          [Name] -> UniqSet Name
    mkNameSet [Name]
    insts UniqSet Name -> [UniqSet Name] -> [UniqSet Name]
    forall a. a -> [a] -> [a]
    : [Name] -> UniqSet Name
    mkNameSet [Name]
    defms UniqSet Name -> [UniqSet Name] -> [UniqSet Name]
    forall a. a -> [a] -> [a]
    : (IfaceIdExtras -> UniqSet Name)
    -> [IfaceIdExtras] -> [UniqSet Name]
    forall a b. (a -> b) -> [a] -> [b]
    map IfaceIdExtras -> UniqSet Name
    freeNamesIdExtras [IfaceIdExtras]
    subs
    freeNamesDeclExtras (IfaceSynonymExtras Maybe Fixity
    _ [AnnPayload]
    _)
      = UniqSet Name
    emptyNameSet
    freeNamesDeclExtras (IfaceFamilyExtras Maybe Fixity
    _ [Name]
    insts [AnnPayload]
    _)
      = [Name] -> UniqSet Name
    mkNameSet [Name]
    insts
    freeNamesDeclExtras IfaceDeclExtras
    IfaceOtherDeclExtras
      = UniqSet Name
    emptyNameSet

    freeNamesIdExtras :: IfaceIdExtras -> NameSet
    freeNamesIdExtras :: IfaceIdExtras -> UniqSet Name
    freeNamesIdExtras (IdExtras Maybe Fixity
    _ [IfaceRule]
    rules [AnnPayload]
    _) = [UniqSet Name] -> UniqSet Name
    unionNameSets ((IfaceRule -> UniqSet Name) -> [IfaceRule] -> [UniqSet Name]
    forall a b. (a -> b) -> [a] -> [b]
    map IfaceRule -> UniqSet Name
    freeNamesIfRule [IfaceRule]
    rules)

    instance Outputable IfaceDeclExtras where
      ppr :: IfaceDeclExtras -> SDoc
    ppr IfaceDeclExtras
    IfaceOtherDeclExtras       = SDoc
    forall doc. IsOutput doc => doc
    Outputable.empty
      ppr (IfaceIdExtras  IfaceIdExtras
    extras)    = IfaceIdExtras -> SDoc
    ppr_id_extras IfaceIdExtras
    extras
      ppr (IfaceSynonymExtras Maybe Fixity
    fix [AnnPayload]
    anns) = [SDoc] -> SDoc
    forall doc. IsDoc doc => [doc] -> doc
    vcat [Maybe Fixity -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Maybe Fixity
    fix, [AnnPayload] -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr [AnnPayload]
    anns]
      ppr (IfaceFamilyExtras Maybe Fixity
    fix [Name]
    finsts [AnnPayload]
    anns) = [SDoc] -> SDoc
    forall doc. IsDoc doc => [doc] -> doc
    vcat [Maybe Fixity -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Maybe Fixity
    fix, [Name] -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr [Name]
    finsts, [AnnPayload] -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr [AnnPayload]
    anns]
      ppr (IfaceDataExtras Maybe Fixity
    fix [Name]
    insts [AnnPayload]
    anns [IfaceIdExtras]
    stuff) = [SDoc] -> SDoc
    forall doc. IsDoc doc => [doc] -> doc
    vcat [Maybe Fixity -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Maybe Fixity
    fix, [Name] -> SDoc
    ppr_insts [Name]
    insts, [AnnPayload] -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr [AnnPayload]
    anns,
                                                    [IfaceIdExtras] -> SDoc
    ppr_id_extras_s [IfaceIdExtras]
    stuff]
      ppr (IfaceClassExtras Maybe Fixity
    fix [Name]
    insts [AnnPayload]
    anns [IfaceIdExtras]
    stuff [Name]
    defms) =
        [SDoc] -> SDoc
    forall doc. IsDoc doc => [doc] -> doc
    vcat [Maybe Fixity -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Maybe Fixity
    fix, [Name] -> SDoc
    ppr_insts [Name]
    insts, [AnnPayload] -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr [AnnPayload]
    anns,
              [IfaceIdExtras] -> SDoc
    ppr_id_extras_s [IfaceIdExtras]
    stuff, [Name] -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr [Name]
    defms]

    ppr_insts :: [IfaceInstABI] -> SDoc
    ppr_insts :: [Name] -> SDoc
    ppr_insts [Name]
    _ = String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "<insts>"

    ppr_id_extras_s :: [IfaceIdExtras] -> SDoc
    ppr_id_extras_s :: [IfaceIdExtras] -> SDoc
    ppr_id_extras_s [IfaceIdExtras]
    stuff = [SDoc] -> SDoc
    forall doc. IsDoc doc => [doc] -> doc
    vcat ((IfaceIdExtras -> SDoc) -> [IfaceIdExtras] -> [SDoc]
    forall a b. (a -> b) -> [a] -> [b]
    map IfaceIdExtras -> SDoc
    ppr_id_extras [IfaceIdExtras]
    stuff)

    ppr_id_extras :: IfaceIdExtras -> SDoc
    ppr_id_extras :: IfaceIdExtras -> SDoc
    ppr_id_extras (IdExtras Maybe Fixity
    fix [IfaceRule]
    rules [AnnPayload]
    anns) = Maybe Fixity -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Maybe Fixity
    fix SDoc -> SDoc -> SDoc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$ [SDoc] -> SDoc
    forall doc. IsDoc doc => [doc] -> doc
    vcat ((IfaceRule -> SDoc) -> [IfaceRule] -> [SDoc]
    forall a b. (a -> b) -> [a] -> [b]
    map IfaceRule -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr [IfaceRule]
    rules) SDoc -> SDoc -> SDoc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$ [SDoc] -> SDoc
    forall doc. IsDoc doc => [doc] -> doc
    vcat ((AnnPayload -> SDoc) -> [AnnPayload] -> [SDoc]
    forall a b. (a -> b) -> [a] -> [b]
    map AnnPayload -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr [AnnPayload]
    anns)

    -- This instance is used only to compute fingerprints
    instance Binary IfaceDeclExtras where
      get :: BinHandle -> IO IfaceDeclExtras
    get BinHandle
    _bh = String -> IO IfaceDeclExtras
    forall a. HasCallStack => String -> a
    panic String
    "no get for IfaceDeclExtras"
      put_ :: BinHandle -> IfaceDeclExtras -> IO ()
    put_ BinHandle
    bh (IfaceIdExtras IfaceIdExtras
    extras) = do
       BinHandle -> Word8 -> IO ()
    putByte BinHandle
    bh Word8
    1; BinHandle -> IfaceIdExtras -> IO ()
    forall a. Binary a => BinHandle -> a -> IO ()
    put_ BinHandle
    bh IfaceIdExtras
    extras
      put_ BinHandle
    bh (IfaceDataExtras Maybe Fixity
    fix [Name]
    insts [AnnPayload]
    anns [IfaceIdExtras]
    cons) = do
       BinHandle -> Word8 -> IO ()
    putByte BinHandle
    bh Word8
    2; BinHandle -> Maybe Fixity -> IO ()
    forall a. Binary a => BinHandle -> a -> IO ()
    put_ BinHandle
    bh Maybe Fixity
    fix; BinHandle -> [Name] -> IO ()
    forall a. Binary a => BinHandle -> a -> IO ()
    put_ BinHandle
    bh [Name]
    insts; BinHandle -> [AnnPayload] -> IO ()
    forall a. Binary a => BinHandle -> a -> IO ()
    put_ BinHandle
    bh [AnnPayload]
    anns; BinHandle -> [IfaceIdExtras] -> IO ()
    forall a. Binary a => BinHandle -> a -> IO ()
    put_ BinHandle
    bh [IfaceIdExtras]
    cons
      put_ BinHandle
    bh (IfaceClassExtras Maybe Fixity
    fix [Name]
    insts [AnnPayload]
    anns [IfaceIdExtras]
    methods [Name]
    defms) = do
       BinHandle -> Word8 -> IO ()
    putByte BinHandle
    bh Word8
    3
       BinHandle -> Maybe Fixity -> IO ()
    forall a. Binary a => BinHandle -> a -> IO ()
    put_ BinHandle
    bh Maybe Fixity
    fix
       BinHandle -> [Name] -> IO ()
    forall a. Binary a => BinHandle -> a -> IO ()
    put_ BinHandle
    bh [Name]
    insts
       BinHandle -> [AnnPayload] -> IO ()
    forall a. Binary a => BinHandle -> a -> IO ()
    put_ BinHandle
    bh [AnnPayload]
    anns
       BinHandle -> [IfaceIdExtras] -> IO ()
    forall a. Binary a => BinHandle -> a -> IO ()
    put_ BinHandle
    bh [IfaceIdExtras]
    methods
       BinHandle -> [Name] -> IO ()
    forall a. Binary a => BinHandle -> a -> IO ()
    put_ BinHandle
    bh [Name]
    defms
      put_ BinHandle
    bh (IfaceSynonymExtras Maybe Fixity
    fix [AnnPayload]
    anns) = do
       BinHandle -> Word8 -> IO ()
    putByte BinHandle
    bh Word8
    4; BinHandle -> Maybe Fixity -> IO ()
    forall a. Binary a => BinHandle -> a -> IO ()
    put_ BinHandle
    bh Maybe Fixity
    fix; BinHandle -> [AnnPayload] -> IO ()
    forall a. Binary a => BinHandle -> a -> IO ()
    put_ BinHandle
    bh [AnnPayload]
    anns
      put_ BinHandle
    bh (IfaceFamilyExtras Maybe Fixity
    fix [Name]
    finsts [AnnPayload]
    anns) = do
       BinHandle -> Word8 -> IO ()
    putByte BinHandle
    bh Word8
    5; BinHandle -> Maybe Fixity -> IO ()
    forall a. Binary a => BinHandle -> a -> IO ()
    put_ BinHandle
    bh Maybe Fixity
    fix; BinHandle -> [Name] -> IO ()
    forall a. Binary a => BinHandle -> a -> IO ()
    put_ BinHandle
    bh [Name]
    finsts; BinHandle -> [AnnPayload] -> IO ()
    forall a. Binary a => BinHandle -> a -> IO ()
    put_ BinHandle
    bh [AnnPayload]
    anns
      put_ BinHandle
    bh IfaceDeclExtras
    IfaceOtherDeclExtras = BinHandle -> Word8 -> IO ()
    putByte BinHandle
    bh Word8
    6

    instance Binary IfaceIdExtras where
      get :: BinHandle -> IO IfaceIdExtras
    get BinHandle
    _bh = String -> IO IfaceIdExtras
    forall a. HasCallStack => String -> a
    panic String
    "no get for IfaceIdExtras"
      put_ :: BinHandle -> IfaceIdExtras -> IO ()
    put_ BinHandle
    bh (IdExtras Maybe Fixity
    fix [IfaceRule]
    rules [AnnPayload]
    anns)= do { BinHandle -> Maybe Fixity -> IO ()
    forall a. Binary a => BinHandle -> a -> IO ()
    put_ BinHandle
    bh Maybe Fixity
    fix; BinHandle -> [IfaceRule] -> IO ()
    forall a. Binary a => BinHandle -> a -> IO ()
    put_ BinHandle
    bh [IfaceRule]
    rules; BinHandle -> [AnnPayload] -> IO ()
    forall a. Binary a => BinHandle -> a -> IO ()
    put_ BinHandle
    bh [AnnPayload]
    anns }

    declExtras :: (OccName -> Maybe Fixity)
               -> (OccName -> [AnnPayload])
               -> OccEnv [IfaceRule]
               -> OccEnv [IfaceClsInst]
               -> OccEnv [IfaceFamInst]
               -> OccEnv IfExtName          -- lookup default method names
               -> IfaceDecl
               -> IfaceDeclExtras

    declExtras :: (OccName -> Maybe Fixity)
    -> (OccName -> [AnnPayload])
    -> OccEnv [IfaceRule]
    -> OccEnv [IfaceClsInst]
    -> OccEnv [IfaceFamInst]
    -> OccEnv Name
    -> IfaceDecl
    -> IfaceDeclExtras
    declExtras OccName -> Maybe Fixity
    fix_fn OccName -> [AnnPayload]
    ann_fn OccEnv [IfaceRule]
    rule_env OccEnv [IfaceClsInst]
    inst_env OccEnv [IfaceFamInst]
    fi_env OccEnv Name
    dm_env IfaceDecl
    decl
      = case IfaceDecl
    decl of
          IfaceId{} -> IfaceIdExtras -> IfaceDeclExtras
    IfaceIdExtras (OccName -> IfaceIdExtras
    id_extras OccName
    n)
          IfaceData{ifCons :: IfaceDecl -> IfaceConDecls
    ifCons=IfaceConDecls
    cons} ->
                         Maybe Fixity
    -> [Name] -> [AnnPayload] -> [IfaceIdExtras] -> IfaceDeclExtras
    IfaceDataExtras (OccName -> Maybe Fixity
    fix_fn OccName
    n)
                            ((IfaceFamInst -> Name) -> [IfaceFamInst] -> [Name]
    forall a b. (a -> b) -> [a] -> [b]
    map IfaceFamInst -> Name
    ifFamInstAxiom (OccEnv [IfaceFamInst] -> OccName -> [IfaceFamInst]
    forall v. OccEnv [v] -> OccName -> [v]
    lookupOccEnvL OccEnv [IfaceFamInst]
    fi_env OccName
    n) [Name] -> [Name] -> [Name]
    forall a. [a] -> [a] -> [a]
    ++
                             (IfaceClsInst -> Name) -> [IfaceClsInst] -> [Name]
    forall a b. (a -> b) -> [a] -> [b]
    map IfaceClsInst -> Name
    ifDFun         (OccEnv [IfaceClsInst] -> OccName -> [IfaceClsInst]
    forall v. OccEnv [v] -> OccName -> [v]
    lookupOccEnvL OccEnv [IfaceClsInst]
    inst_env OccName
    n))
                            (OccName -> [AnnPayload]
    ann_fn OccName
    n)
                            ((IfaceConDecl -> IfaceIdExtras)
    -> [IfaceConDecl] -> [IfaceIdExtras]
    forall a b. (a -> b) -> [a] -> [b]
    map (OccName -> IfaceIdExtras
    id_extras (OccName -> IfaceIdExtras)
    -> (IfaceConDecl -> OccName) -> IfaceConDecl -> IfaceIdExtras
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Name -> OccName
    forall name. HasOccName name => name -> OccName
    occName (Name -> OccName)
    -> (IfaceConDecl -> Name) -> IfaceConDecl -> OccName
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . IfaceConDecl -> Name
    ifConName) (IfaceConDecls -> [IfaceConDecl]
    visibleIfConDecls IfaceConDecls
    cons))
          IfaceClass{ifBody :: IfaceDecl -> IfaceClassBody
    ifBody = IfConcreteClass { ifSigs :: IfaceClassBody -> [IfaceClassOp]
    ifSigs=[IfaceClassOp]
    sigs, ifATs :: IfaceClassBody -> [IfaceAT]
    ifATs=[IfaceAT]
    ats }} ->
                         Maybe Fixity
    -> [Name]
    -> [AnnPayload]
    -> [IfaceIdExtras]
    -> [Name]
    -> IfaceDeclExtras
    IfaceClassExtras (OccName -> Maybe Fixity
    fix_fn OccName
    n) [Name]
    insts (OccName -> [AnnPayload]
    ann_fn OccName
    n) [IfaceIdExtras]
    meths [Name]
    defms
              where
                insts :: [Name]
    insts = ((IfaceClsInst -> Name) -> [IfaceClsInst] -> [Name]
    forall a b. (a -> b) -> [a] -> [b]
    map IfaceClsInst -> Name
    ifDFun ([IfaceClsInst] -> [Name]) -> [IfaceClsInst] -> [Name]
    forall a b. (a -> b) -> a -> b
    $ ((IfaceAT -> [IfaceClsInst]) -> [IfaceAT] -> [IfaceClsInst]
    forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
    concatMap IfaceAT -> [IfaceClsInst]
    at_extras [IfaceAT]
    ats)
                                        [IfaceClsInst] -> [IfaceClsInst] -> [IfaceClsInst]
    forall a. [a] -> [a] -> [a]
    ++ OccEnv [IfaceClsInst] -> OccName -> [IfaceClsInst]
    forall v. OccEnv [v] -> OccName -> [v]
    lookupOccEnvL OccEnv [IfaceClsInst]
    inst_env OccName
    n)
                               -- Include instances of the associated types
                               -- as well as instances of the class (#5147)
                meths :: [IfaceIdExtras]
    meths = [OccName -> IfaceIdExtras
    id_extras (Name -> OccName
    forall a. NamedThing a => a -> OccName
    getOccName Name
    op) | IfaceClassOp Name
    op IfaceType
    _ Maybe (DefMethSpec IfaceType)
    _ <- [IfaceClassOp]
    sigs]
                -- Names of all the default methods (see Note [default method Name])
                defms :: [Name]
    defms = [ Name
    dmName
                        | IfaceClassOp Name
    bndr IfaceType
    _ (Just DefMethSpec IfaceType
    _) <- [IfaceClassOp]
    sigs
                        , let dmOcc :: OccName
    dmOcc = OccName -> OccName
    mkDefaultMethodOcc (Name -> OccName
    nameOccName Name
    bndr)
                        , Just Name
    dmName <- [OccEnv Name -> OccName -> Maybe Name
    forall a. OccEnv a -> OccName -> Maybe a
    lookupOccEnv OccEnv Name
    dm_env OccName
    dmOcc] ]
          IfaceSynonym{} -> Maybe Fixity -> [AnnPayload] -> IfaceDeclExtras
    IfaceSynonymExtras (OccName -> Maybe Fixity
    fix_fn OccName
    n)
                                               (OccName -> [AnnPayload]
    ann_fn OccName
    n)
          IfaceFamily{} -> Maybe Fixity -> [Name] -> [AnnPayload] -> IfaceDeclExtras
    IfaceFamilyExtras (OccName -> Maybe Fixity
    fix_fn OccName
    n)
                            ((IfaceFamInst -> Name) -> [IfaceFamInst] -> [Name]
    forall a b. (a -> b) -> [a] -> [b]
    map IfaceFamInst -> Name
    ifFamInstAxiom (OccEnv [IfaceFamInst] -> OccName -> [IfaceFamInst]
    forall v. OccEnv [v] -> OccName -> [v]
    lookupOccEnvL OccEnv [IfaceFamInst]
    fi_env OccName
    n))
                            (OccName -> [AnnPayload]
    ann_fn OccName
    n)
          IfaceDecl
    _other -> IfaceDeclExtras
    IfaceOtherDeclExtras
      where
            n :: OccName
    n = IfaceDecl -> OccName
    forall a. NamedThing a => a -> OccName
    getOccName IfaceDecl
    decl
            id_extras :: OccName -> IfaceIdExtras
    id_extras OccName
    occ = Maybe Fixity -> [IfaceRule] -> [AnnPayload] -> IfaceIdExtras
    IdExtras (OccName -> Maybe Fixity
    fix_fn OccName
    occ) (OccEnv [IfaceRule] -> OccName -> [IfaceRule]
    forall v. OccEnv [v] -> OccName -> [v]
    lookupOccEnvL OccEnv [IfaceRule]
    rule_env OccName
    occ) (OccName -> [AnnPayload]
    ann_fn OccName
    occ)
            at_extras :: IfaceAT -> [IfaceClsInst]
    at_extras (IfaceAT IfaceDecl
    decl Maybe IfaceType
    _) = OccEnv [IfaceClsInst] -> OccName -> [IfaceClsInst]
    forall v. OccEnv [v] -> OccName -> [v]
    lookupOccEnvL OccEnv [IfaceClsInst]
    inst_env (IfaceDecl -> OccName
    forall a. NamedThing a => a -> OccName
    getOccName IfaceDecl
    decl)

    {- Note [default method Name] (see also #15970)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~

    The Names for the default methods aren't available in Iface syntax.

    * We originally start with a DefMethInfo from the class, contain a
      Name for the default method

    * We turn that into Iface syntax as a DefMethSpec which lacks a Name
      entirely. Why? Because the Name can be derived from the method name
      (in GHC.IfaceToCore), so doesn't need to be serialised into the interface
      file.

    But now we have to get the Name back, because the class declaration's
    fingerprint needs to depend on it (this was the bug in #15970).  This
    is done in a slightly convoluted way:

    * Then, in addFingerprints we build a map that maps OccNames to Names

    * We pass that map to declExtras which laboriously looks up in the map
      (using the derived occurrence name) to recover the Name we have just
      thrown away.
    -}

    lookupOccEnvL :: OccEnv [v] -> OccName -> [v]
    lookupOccEnvL :: forall v. OccEnv [v] -> OccName -> [v]
    lookupOccEnvL OccEnv [v]
    env OccName
    k = OccEnv [v] -> OccName -> Maybe [v]
    forall a. OccEnv a -> OccName -> Maybe a
    lookupOccEnv OccEnv [v]
    env OccName
    k Maybe [v] -> [v] -> [v]
    forall a. Maybe a -> a -> a
    `orElse` []

    {-
    -- for testing: use the md5sum command to generate fingerprints and
    -- compare the results against our built-in version.
      fp' <- oldMD5 dflags bh
      if fp /= fp' then pprPanic "computeFingerprint" (ppr fp <+> ppr fp')
                   else return fp

    oldMD5 dflags bh = do
      tmp <- newTempName dflags CurrentModule "bin"
      writeBinMem bh tmp
      tmp2 <- newTempName dflags CurrentModule "md5"
      let cmd = "md5sum " ++ tmp ++ " >" ++ tmp2
      r <- system cmd
      case r of
        ExitFailure _ -> throwGhcExceptionIO (PhaseFailed cmd r)
        ExitSuccess -> do
            hash_str <- readFile tmp2
            return $! readHexFingerprint hash_str
    -}

    ----------------------
    -- mkOrphMap partitions instance decls or rules into
    --      (a) an OccEnv for ones that are not orphans,
    --          mapping the local OccName to a list of its decls
    --      (b) a list of orphan decls
    mkOrphMap :: (decl -> IsOrphan) -- Extract orphan status from decl
              -> [decl]             -- Sorted into canonical order
              -> (OccEnv [decl],    -- Non-orphan decls associated with their key;
                                    --      each sublist in canonical order
                  [decl])           -- Orphan decls; in canonical order
    mkOrphMap :: forall decl.
    (decl -> IsOrphan) -> [decl] -> (OccEnv [decl], [decl])
    mkOrphMap decl -> IsOrphan
    get_key [decl]
    decls
      = ((OccEnv [decl], [decl]) -> decl -> (OccEnv [decl], [decl]))
    -> (OccEnv [decl], [decl]) -> [decl] -> (OccEnv [decl], [decl])
    forall b a. (b -> a -> b) -> b -> [a] -> b
    forall (t :: * -> *) b a.
    Foldable t =>
    (b -> a -> b) -> b -> t a -> b
    foldl' (OccEnv [decl], [decl]) -> decl -> (OccEnv [decl], [decl])
    go (OccEnv [decl]
    forall a. OccEnv a
    emptyOccEnv, []) [decl]
    decls
      where
        go :: (OccEnv [decl], [decl]) -> decl -> (OccEnv [decl], [decl])
    go (OccEnv [decl]
    non_orphs, [decl]
    orphs) decl
    d
            | NotOrphan OccName
    occ <- decl -> IsOrphan
    get_key decl
    d
            = ((decl -> [decl] -> [decl])
    -> (decl -> [decl])
    -> OccEnv [decl]
    -> OccName
    -> decl
    -> OccEnv [decl]
    forall a b.
    (a -> b -> b) -> (a -> b) -> OccEnv b -> OccName -> a -> OccEnv b
    extendOccEnv_Acc (:) decl -> [decl]
    forall a. a -> [a]
    Utils.singleton OccEnv [decl]
    non_orphs OccName
    occ decl
    d, [decl]
    orphs)
            | AnyHpcUsage
    otherwise = (OccEnv [decl]
    non_orphs, decl
    ddecl -> [decl] -> [decl]
    forall a. a -> [a] -> [a]
    :[decl]
    orphs)

    -- -----------------------------------------------------------------------------
    -- Look up parents and versions of Names

    -- This is like a global version of the mi_hash_fn field in each ModIface.
    -- Given a Name, it finds the ModIface, and then uses mi_hash_fn to get
    -- the parent and version info.

    mkHashFun
            :: HscEnv                       -- needed to look up versions
            -> ExternalPackageState         -- ditto
            -> (Name -> IO Fingerprint)
    mkHashFun :: HscEnv -> ExternalPackageState -> Name -> IO Fingerprint
    mkHashFun HscEnv
    hsc_env ExternalPackageState
    eps Name
    name
      | Module -> AnyHpcUsage
    forall u. GenModule (GenUnit u) -> AnyHpcUsage
    isHoleModule Module
    orig_mod
      = Module -> IO Fingerprint
    lookup (HomeUnit -> ModuleName -> Module
    mkHomeModule HomeUnit
    home_unit (Module -> ModuleName
    forall unit. GenModule unit -> ModuleName
    moduleName Module
    orig_mod))
      | AnyHpcUsage
    otherwise
      = Module -> IO Fingerprint
    lookup Module
    orig_mod
      where
          home_unit :: HomeUnit
    home_unit = HscEnv -> HomeUnit
    hsc_home_unit HscEnv
    hsc_env
          dflags :: DynFlags
    dflags = HscEnv -> DynFlags
    hsc_dflags HscEnv
    hsc_env
          hpt :: HomeUnitGraph
    hpt = HscEnv -> HomeUnitGraph
    hsc_HUG HscEnv
    hsc_env
          pit :: PackageIfaceTable
    pit = ExternalPackageState -> PackageIfaceTable
    eps_PIT ExternalPackageState
    eps
          ctx :: SDocContext
    ctx = DynFlags -> PprStyle -> SDocContext
    initSDocContext DynFlags
    dflags PprStyle
    defaultUserStyle
          occ :: OccName
    occ = Name -> OccName
    nameOccName Name
    name
          orig_mod :: Module
    orig_mod = HasDebugCallStack => Name -> Module
    Name -> Module
    nameModule Name
    name
          lookup :: Module -> IO Fingerprint
    lookup Module
    mod = do
            AnyHpcUsage -> SDoc -> IO ()
    forall (m :: * -> *).
    (HasCallStack, Applicative m) =>
    AnyHpcUsage -> SDoc -> m ()
    massertPpr (Name -> AnyHpcUsage
    isExternalName Name
    name) (Name -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Name
    name)
            iface <- case HomeUnitGraph -> PackageIfaceTable -> Module -> Maybe ModIface
    lookupIfaceByModule HomeUnitGraph
    hpt PackageIfaceTable
    pit Module
    mod of
                      Just ModIface
    iface -> ModIface -> IO ModIface
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ModIface
    iface
                      Maybe ModIface
    Nothing ->
                          -- This can occur when we're writing out ifaces for
                          -- requirements; we didn't do any /real/ typechecking
                          -- so there's no guarantee everything is loaded.
                          -- Kind of a heinous hack.
                          HscEnv -> IfG ModIface -> IO ModIface
    forall a. HscEnv -> IfG a -> IO a
    initIfaceLoad HscEnv
    hsc_env (IfG ModIface -> IO ModIface)
    -> (IfM () (MaybeErr MissingInterfaceError ModIface)
        -> IfG ModIface)
    -> IfM () (MaybeErr MissingInterfaceError ModIface)
    -> IO ModIface
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . SDocContext
    -> IfM () (MaybeErr MissingInterfaceError ModIface) -> IfG ModIface
    forall (m :: * -> *) a.
    MonadIO m =>
    SDocContext -> m (MaybeErr MissingInterfaceError a) -> m a
    withIfaceErr SDocContext
    ctx
                              (IfM () (MaybeErr MissingInterfaceError ModIface) -> IO ModIface)
    -> IfM () (MaybeErr MissingInterfaceError ModIface) -> IO ModIface
    forall a b. (a -> b) -> a -> b
    $ IfM () (MaybeErr MissingInterfaceError ModIface)
    -> IfM () (MaybeErr MissingInterfaceError ModIface)
    forall gbl lcl a. TcRnIf gbl lcl a -> TcRnIf gbl lcl a
    withoutDynamicNow
                                -- If you try and load interfaces when dynamic-too
                                -- enabled then it attempts to load the dyn_hi and hi
                                -- interface files. Backpack doesn't really care about
                                -- dynamic object files as it isn't doing any code
                                -- generation so -dynamic-too is turned off.
                                -- Some tests fail without doing this (such as T16219),
                                -- but they fail because dyn_hi files are not found for
                                -- one of the dependencies (because they are deliberately turned off)
                                -- Why is this check turned off here? That is unclear but
                                -- just one of the many horrible hacks in the backpack
                                -- implementation.
                              (IfM () (MaybeErr MissingInterfaceError ModIface)
     -> IfM () (MaybeErr MissingInterfaceError ModIface))
    -> IfM () (MaybeErr MissingInterfaceError ModIface)
    -> IfM () (MaybeErr MissingInterfaceError ModIface)
    forall a b. (a -> b) -> a -> b
    $ SDoc
    -> Module
    -> WhereFrom
    -> IfM () (MaybeErr MissingInterfaceError ModIface)
    forall lcl.
    SDoc
    -> Module
    -> WhereFrom
    -> IfM lcl (MaybeErr MissingInterfaceError ModIface)
    loadInterface (String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "lookupVers2") Module
    mod WhereFrom
    ImportBySystem
            return $ snd (mi_hash_fn (mi_final_exts iface) occ `orElse`
                      pprPanic "lookupVers1" (ppr mod <+> ppr occ))

    -- | Creates cached lookup for the 'mi_anns' field of ModIface
    -- Hackily, we use "module" as the OccName for any module-level annotations
    mkIfaceAnnCache :: [IfaceAnnotation] -> OccName -> [AnnPayload]
    mkIfaceAnnCache :: [IfaceAnnotation] -> OccName -> [AnnPayload]
    mkIfaceAnnCache [IfaceAnnotation]
    anns
      = \OccName
    n -> OccEnv [AnnPayload] -> OccName -> Maybe [AnnPayload]
    forall a. OccEnv a -> OccName -> Maybe a
    lookupOccEnv OccEnv [AnnPayload]
    env OccName
    n Maybe [AnnPayload] -> [AnnPayload] -> [AnnPayload]
    forall a. Maybe a -> a -> a
    `orElse` []
      where
        pair :: IfaceAnnotation -> (OccName, [AnnPayload])
    pair (IfaceAnnotation IfaceAnnTarget
    target AnnPayload
    value) =
          (case IfaceAnnTarget
    target of
              NamedTarget OccName
    occn -> OccName
    occn
              ModuleTarget Module
    _   -> FastString -> OccName
    mkVarOccFS (String -> FastString
    fsLit String
    "module")
          , [AnnPayload
    value])
        -- flipping (++), so the first argument is always short
        env :: OccEnv [AnnPayload]
    env = ([AnnPayload] -> [AnnPayload] -> [AnnPayload])
    -> [(OccName, [AnnPayload])] -> OccEnv [AnnPayload]
    forall a. (a -> a -> a) -> [(OccName, a)] -> OccEnv a
    mkOccEnv_C (([AnnPayload] -> [AnnPayload] -> [AnnPayload])
    -> [AnnPayload] -> [AnnPayload] -> [AnnPayload]
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip [AnnPayload] -> [AnnPayload] -> [AnnPayload]
    forall a. [a] -> [a] -> [a]
    (++)) ((IfaceAnnotation -> (OccName, [AnnPayload]))
    -> [IfaceAnnotation] -> [(OccName, [AnnPayload])]
    forall a b. (a -> b) -> [a] -> [b]
    map IfaceAnnotation -> (OccName, [AnnPayload])
    pair [IfaceAnnotation]
    anns)