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

    -}

    {-# LANGUAGE NondecreasingIndentation #-}
    {-# LANGUAGE TypeFamilies #-}
    {-# LANGUAGE LambdaCase #-}

    {-# OPTIONS_GHC -fno-warn-orphans #-}
    {-# LANGUAGE ViewPatterns #-}

    -- | Loading interface files
    module GHC.Iface.Load (
            -- Importing one thing
            tcLookupImported_maybe, importDecl,
            checkWiredInTyCon, ifCheckWiredInThing,

            -- RnM/TcM functions
            loadModuleInterface, loadModuleInterfaces,
            loadSrcInterface, loadSrcInterface_maybe,
            loadInterfaceForName, loadInterfaceForModule,

            -- IfM functions
            loadInterface,
            loadSysInterface, loadUserInterface, loadPluginInterface,
            findAndReadIface, readIface, writeIface,
            moduleFreeHolesPrecise,
            needWiredInHomeIface, loadWiredInHomeIface,

            WhereFrom(..),

            pprModIfaceSimple,
            ifaceStats, pprModIface, showIface,

            module Iface_Errors -- avoids boot files in Ppr modules
       ) where

    import GHC.Prelude

    import GHC.Platform.Profile

    import {-# SOURCE #-} GHC.IfaceToCore
       ( tcIfaceDecls, tcIfaceRules, tcIfaceInst, tcIfaceFamInst
       , tcIfaceAnnotations, tcIfaceCompleteMatches )

    import GHC.Driver.Config.Finder
    import GHC.Driver.Env
    import GHC.Driver.Errors.Types
    import GHC.Driver.DynFlags
    import GHC.Driver.Hooks
    import GHC.Driver.Plugins

    import GHC.Iface.Syntax
    import GHC.Iface.Ext.Fields
    import GHC.Iface.Binary
    import GHC.Iface.Rename
    import GHC.Iface.Env
    import GHC.Iface.Errors as Iface_Errors

    import GHC.Tc.Errors.Types
    import GHC.Tc.Utils.Monad

    import GHC.Utils.Binary   ( BinData(..) )
    import GHC.Utils.Error
    import GHC.Utils.Outputable as Outputable
    import GHC.Utils.Panic
    import GHC.Utils.Constants (debugIsOn)
    import GHC.Utils.Logger

    import GHC.Settings.Constants

    import GHC.Builtin.Names
    import GHC.Builtin.Utils
    import GHC.Builtin.PrimOps    ( allThePrimOps, primOpFixity, primOpOcc )

    import GHC.Core.Rules
    import GHC.Core.TyCon
    import GHC.Core.InstEnv
    import GHC.Core.FamInstEnv

    import GHC.Types.Id.Make      ( seqId )
    import GHC.Types.Annotations
    import GHC.Types.Name
    import GHC.Types.Name.Cache
    import GHC.Types.Name.Env
    import GHC.Types.Avail
    import GHC.Types.Fixity
    import GHC.Types.Fixity.Env
    import GHC.Types.SourceError
    import GHC.Types.SourceText
    import GHC.Types.SourceFile
    import GHC.Types.SafeHaskell
    import GHC.Types.TypeEnv
    import GHC.Types.Unique.DSet
    import GHC.Types.SrcLoc
    import GHC.Types.TyThing
    import GHC.Types.PkgQual

    import GHC.Unit.External
    import GHC.Unit.Module
    import GHC.Unit.Module.ModIface
    import GHC.Unit.Module.Deps
    import GHC.Unit.State
    import GHC.Unit.Home
    import GHC.Unit.Home.ModInfo
    import GHC.Unit.Finder
    import GHC.Unit.Env

    import GHC.Data.Maybe

    import Control.Monad
    import Data.Map ( toList )
    import System.FilePath
    import System.Directory
    import GHC.Driver.Env.KnotVars
    import GHC.Iface.Errors.Types

    {-
    ************************************************************************
    *                                                                      *
    *      tcImportDecl is the key function for "faulting in"              *
    *      imported things
    *                                                                      *
    ************************************************************************

    The main idea is this.  We are chugging along type-checking source code, and
    find a reference to GHC.Base.map.  We call tcLookupGlobal, which doesn't find
    it in the EPS type envt.  So it
            1 loads GHC.Base.hi
            2 gets the decl for GHC.Base.map
            3 typechecks it via tcIfaceDecl
            4 and adds it to the type env in the EPS

    Note that DURING STEP 4, we may find that map's type mentions a type
    constructor that also

    Notice that for imported things we read the current version from the EPS
    mutable variable.  This is important in situations like
            ...$(e1)...$(e2)...
    where the code that e1 expands to might import some defns that
    also turn out to be needed by the code that e2 expands to.
    -}

    tcLookupImported_maybe :: Name -> TcM (MaybeErr IfaceMessage TyThing)
    -- Returns (Failed err) if we can't find the interface file for the thing
    tcLookupImported_maybe :: Name -> TcM (MaybeErr IfaceMessage TyThing)
    tcLookupImported_maybe Name
    name
      = do  { hsc_env <- TcRnIf TcGblEnv TcLclEnv HscEnv
    forall gbl lcl. TcRnIf gbl lcl HscEnv
    getTopEnv
            ; mb_thing <- liftIO (lookupType hsc_env name)
            ; case mb_thing of
                Just TyThing
    thing -> MaybeErr IfaceMessage TyThing
    -> TcM (MaybeErr IfaceMessage TyThing)
    forall a. a -> IOEnv (Env TcGblEnv TcLclEnv) a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (TyThing -> MaybeErr IfaceMessage TyThing
    forall err val. val -> MaybeErr err val
    Succeeded TyThing
    thing)
                Maybe TyThing
    Nothing    -> Name -> TcM (MaybeErr IfaceMessage TyThing)
    tcImportDecl_maybe Name
    name }

    tcImportDecl_maybe :: Name -> TcM (MaybeErr IfaceMessage TyThing)
    -- Entry point for *source-code* uses of importDecl
    tcImportDecl_maybe :: Name -> TcM (MaybeErr IfaceMessage TyThing)
    tcImportDecl_maybe Name
    name
      | Just TyThing
    thing <- Name -> Maybe TyThing
    wiredInNameTyThing_maybe Name
    name
      = do  { Bool
    -> IOEnv (Env TcGblEnv TcLclEnv) ()
    -> IOEnv (Env TcGblEnv TcLclEnv) ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    when (TyThing -> Bool
    needWiredInHomeIface TyThing
    thing)
                   (IfG () -> IOEnv (Env TcGblEnv TcLclEnv) ()
    forall a. IfG a -> TcRn a
    initIfaceTcRn (Name -> IfG ()
    forall lcl. Name -> IfM lcl ()
    loadWiredInHomeIface Name
    name))
                    -- See Note [Loading instances for wired-in things]
            ; MaybeErr IfaceMessage TyThing
    -> TcM (MaybeErr IfaceMessage TyThing)
    forall a. a -> IOEnv (Env TcGblEnv TcLclEnv) a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (TyThing -> MaybeErr IfaceMessage TyThing
    forall err val. val -> MaybeErr err val
    Succeeded TyThing
    thing) }
      | Bool
    otherwise
      = IfG (MaybeErr IfaceMessage TyThing)
    -> TcM (MaybeErr IfaceMessage TyThing)
    forall a. IfG a -> TcRn a
    initIfaceTcRn (Name -> IfG (MaybeErr IfaceMessage TyThing)
    forall lcl. Name -> IfM lcl (MaybeErr IfaceMessage TyThing)
    importDecl Name
    name)

    importDecl :: Name -> IfM lcl (MaybeErr IfaceMessage TyThing)
    -- Get the TyThing for this Name from an interface file
    -- It's not a wired-in thing -- the caller caught that
    importDecl :: forall lcl. Name -> IfM lcl (MaybeErr IfaceMessage TyThing)
    importDecl Name
    name
      = Bool
    -> IfM lcl (MaybeErr IfaceMessage TyThing)
    -> IfM lcl (MaybeErr IfaceMessage TyThing)
    forall a. HasCallStack => Bool -> a -> a
    assert (Bool -> Bool
    not (Name -> Bool
    isWiredInName Name
    name)) (IfM lcl (MaybeErr IfaceMessage TyThing)
     -> IfM lcl (MaybeErr IfaceMessage TyThing))
    -> IfM lcl (MaybeErr IfaceMessage TyThing)
    -> IfM lcl (MaybeErr IfaceMessage TyThing)
    forall a b. (a -> b) -> a -> b
    $
        do  { logger <- IOEnv (Env IfGblEnv lcl) Logger
    forall (m :: * -> *). HasLogger m => m Logger
    getLogger
            ; liftIO $ trace_if logger nd_doc

            -- Load the interface, which should populate the PTE
            ; mb_iface <- assertPpr (isExternalName name) (ppr name) $
                          loadInterface nd_doc (nameModule name) ImportBySystem
            ; case mb_iface of
              { Failed MissingInterfaceError
    err_msg -> MaybeErr IfaceMessage TyThing
    -> IfM lcl (MaybeErr IfaceMessage TyThing)
    forall a. a -> IOEnv (Env IfGblEnv lcl) a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (MaybeErr IfaceMessage TyThing
     -> IfM lcl (MaybeErr IfaceMessage TyThing))
    -> MaybeErr IfaceMessage TyThing
    -> IfM lcl (MaybeErr IfaceMessage TyThing)
    forall a b. (a -> b) -> a -> b
    $ IfaceMessage -> MaybeErr IfaceMessage TyThing
    forall err val. err -> MaybeErr err val
    Failed (IfaceMessage -> MaybeErr IfaceMessage TyThing)
    -> IfaceMessage -> MaybeErr IfaceMessage TyThing
    forall a b. (a -> b) -> a -> b
    $
                                  MissingInterfaceError -> InterfaceLookingFor -> IfaceMessage
    Can'tFindInterface MissingInterfaceError
    err_msg (Name -> InterfaceLookingFor
    LookingForName Name
    name)
              ; Succeeded ModIface
    _ -> do

            -- Now look it up again; this time we should find it
            { eps <- TcRnIf IfGblEnv lcl ExternalPackageState
    forall gbl lcl. TcRnIf gbl lcl ExternalPackageState
    getEps
            ; case lookupTypeEnv (eps_PTE eps) name of
                Just TyThing
    thing -> MaybeErr IfaceMessage TyThing
    -> IfM lcl (MaybeErr IfaceMessage TyThing)
    forall a. a -> IOEnv (Env IfGblEnv lcl) a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (MaybeErr IfaceMessage TyThing
     -> IfM lcl (MaybeErr IfaceMessage TyThing))
    -> MaybeErr IfaceMessage TyThing
    -> IfM lcl (MaybeErr IfaceMessage TyThing)
    forall a b. (a -> b) -> a -> b
    $ TyThing -> MaybeErr IfaceMessage TyThing
    forall err val. val -> MaybeErr err val
    Succeeded TyThing
    thing
                Maybe TyThing
    Nothing    -> MaybeErr IfaceMessage TyThing
    -> IfM lcl (MaybeErr IfaceMessage TyThing)
    forall a. a -> IOEnv (Env IfGblEnv lcl) a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (MaybeErr IfaceMessage TyThing
     -> IfM lcl (MaybeErr IfaceMessage TyThing))
    -> MaybeErr IfaceMessage TyThing
    -> IfM lcl (MaybeErr IfaceMessage TyThing)
    forall a b. (a -> b) -> a -> b
    $ IfaceMessage -> MaybeErr IfaceMessage TyThing
    forall err val. err -> MaybeErr err val
    Failed (IfaceMessage -> MaybeErr IfaceMessage TyThing)
    -> IfaceMessage -> MaybeErr IfaceMessage TyThing
    forall a b. (a -> b) -> a -> b
    $
                  Name -> [TyThing] -> IfaceMessage
    Can'tFindNameInInterface Name
    name
                  ((TyThing -> Bool) -> [TyThing] -> [TyThing]
    forall a. (a -> Bool) -> [a] -> [a]
    filter TyThing -> Bool
    is_interesting ([TyThing] -> [TyThing]) -> [TyThing] -> [TyThing]
    forall a b. (a -> b) -> a -> b
    $ TypeEnv -> [TyThing]
    forall a. NameEnv a -> [a]
    nonDetNameEnvElts (TypeEnv -> [TyThing]) -> TypeEnv -> [TyThing]
    forall a b. (a -> b) -> a -> b
    $ ExternalPackageState -> TypeEnv
    eps_PTE ExternalPackageState
    eps)
        }}}
      where
        nd_doc :: SDoc
    nd_doc = String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "Need decl for" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Name -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Name
    name
        is_interesting :: TyThing -> Bool
    is_interesting TyThing
    thing = HasDebugCallStack => Name -> Module
    Name -> Module
    nameModule Name
    name Module -> Module -> Bool
    forall a. Eq a => a -> a -> Bool
    == HasDebugCallStack => Name -> Module
    Name -> Module
    nameModule (TyThing -> Name
    forall a. NamedThing a => a -> Name
    getName TyThing
    thing)

    {-
    ************************************************************************
    *                                                                      *
               Checks for wired-in things
    *                                                                      *
    ************************************************************************

    Note [Loading instances for wired-in things]
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    We need to make sure that we have at least *read* the interface files
    for any module with an instance decl or RULE that we might want.

    * If the instance decl is an orphan, we have a whole separate mechanism
      (loadOrphanModules)

    * If the instance decl is not an orphan, then the act of looking at the
      TyCon or Class will force in the defining module for the
      TyCon/Class, and hence the instance decl

    * BUT, if the TyCon is a wired-in TyCon, we don't really need its interface;
      but we must make sure we read its interface in case it has instances or
      rules.  That is what GHC.Iface.Load.loadWiredInHomeIface does.  It's called
      from GHC.IfaceToCore.{tcImportDecl, checkWiredInTyCon, ifCheckWiredInThing}

    * HOWEVER, only do this for TyCons.  There are no wired-in Classes.  There
      are some wired-in Ids, but we don't want to load their interfaces. For
      example, Control.Exception.Base.recSelError is wired in, but that module
      is compiled late in the base library, and we don't want to force it to
      load before it's been compiled!

    All of this is done by the type checker. The renamer plays no role.
    (It used to, but no longer.)
    -}

    checkWiredInTyCon :: TyCon -> TcM ()
    -- Ensure that the home module of the TyCon (and hence its instances)
    -- are loaded. See Note [Loading instances for wired-in things]
    -- It might not be a wired-in tycon (see the calls in GHC.Tc.Utils.Unify),
    -- in which case this is a no-op.
    checkWiredInTyCon :: TyCon -> IOEnv (Env TcGblEnv TcLclEnv) ()
    checkWiredInTyCon TyCon
    tc
      | Bool -> Bool
    not (Name -> Bool
    isWiredInName Name
    tc_name)
      = () -> IOEnv (Env TcGblEnv TcLclEnv) ()
    forall a. a -> IOEnv (Env TcGblEnv TcLclEnv) a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
      | Bool
    otherwise
      = do  { mod <- IOEnv (Env TcGblEnv TcLclEnv) Module
    forall (m :: * -> *). HasModule m => m Module
    getModule
            ; logger <- getLogger
            ; liftIO $ trace_if logger (text "checkWiredInTyCon" <+> ppr tc_name $$ ppr mod)
            ; assert (isExternalName tc_name )
              when (mod /= nameModule tc_name)
                   (initIfaceTcRn (loadWiredInHomeIface tc_name))
                    -- Don't look for (non-existent) Float.hi when
                    -- compiling Float.hs, which mentions Float of course
                    -- A bit yukky to call initIfaceTcRn here
            }
      where
        tc_name :: Name
    tc_name = TyCon -> Name
    tyConName TyCon
    tc

    ifCheckWiredInThing :: TyThing -> IfL ()
    -- Even though we are in an interface file, we want to make
    -- sure the instances of a wired-in thing are loaded (imagine f :: Double -> Double)
    -- Ditto want to ensure that RULES are loaded too
    -- See Note [Loading instances for wired-in things]
    ifCheckWiredInThing :: TyThing -> IfL ()
    ifCheckWiredInThing TyThing
    thing
      = do  { mod <- IfL Module
    getIfModule
                    -- Check whether we are typechecking the interface for this
                    -- very module.  E.g when compiling the base library in --make mode
                    -- we may typecheck GHC.Base.hi. At that point, GHC.Base is not in
                    -- the HPT, so without the test we'll demand-load it into the PIT!
                    -- C.f. the same test in checkWiredInTyCon above
            ; let name = TyThing -> Name
    forall a. NamedThing a => a -> Name
    getName TyThing
    thing
            ; assertPpr (isExternalName name) (ppr name) $
              when (needWiredInHomeIface thing && mod /= nameModule name)
                   (loadWiredInHomeIface name) }

    needWiredInHomeIface :: TyThing -> Bool
    -- Only for TyCons; see Note [Loading instances for wired-in things]
    needWiredInHomeIface :: TyThing -> Bool
    needWiredInHomeIface (ATyCon {}) = Bool
    True
    needWiredInHomeIface TyThing
    _           = Bool
    False

    {-
    ************************************************************************
    *                                                                      *
            loadSrcInterface, loadOrphanModules, loadInterfaceForName

                    These three are called from TcM-land
    *                                                                      *
    ************************************************************************
    -}

    -- | Load the interface corresponding to an @import@ directive in
    -- source code.  On a failure, fail in the monad with an error message.
    loadSrcInterface :: SDoc
                     -> ModuleName
                     -> IsBootInterface     -- {-# SOURCE #-} ?
                     -> PkgQual             -- "package", if any
                     -> RnM ModIface

    loadSrcInterface :: SDoc -> ModuleName -> IsBootInterface -> PkgQual -> RnM ModIface
    loadSrcInterface SDoc
    doc ModuleName
    mod IsBootInterface
    want_boot PkgQual
    maybe_pkg
      = do { res <- SDoc
    -> ModuleName
    -> IsBootInterface
    -> PkgQual
    -> RnM (MaybeErr MissingInterfaceError ModIface)
    loadSrcInterface_maybe SDoc
    doc ModuleName
    mod IsBootInterface
    want_boot PkgQual
    maybe_pkg
           ; case res of
               Failed    MissingInterfaceError
    err ->
                 TcRnMessage -> RnM ModIface
    forall a. TcRnMessage -> TcM a
    failWithTc (TcRnMessage -> RnM ModIface) -> TcRnMessage -> RnM ModIface
    forall a b. (a -> b) -> a -> b
    $
                   IfaceMessage -> TcRnMessage
    TcRnInterfaceError (IfaceMessage -> TcRnMessage) -> IfaceMessage -> TcRnMessage
    forall a b. (a -> b) -> a -> b
    $
                     MissingInterfaceError -> InterfaceLookingFor -> IfaceMessage
    Can'tFindInterface MissingInterfaceError
    err (InterfaceLookingFor -> IfaceMessage)
    -> InterfaceLookingFor -> IfaceMessage
    forall a b. (a -> b) -> a -> b
    $
                     ModuleName -> IsBootInterface -> InterfaceLookingFor
    LookingForModule ModuleName
    mod IsBootInterface
    want_boot
               Succeeded ModIface
    iface ->
                 ModIface -> RnM ModIface
    forall a. a -> IOEnv (Env TcGblEnv TcLclEnv) a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ModIface
    iface
           }

    -- | Like 'loadSrcInterface', but returns a 'MaybeErr'.
    loadSrcInterface_maybe :: SDoc
                           -> ModuleName
                           -> IsBootInterface     -- {-# SOURCE #-} ?
                           -> PkgQual             -- "package", if any
                           -> RnM (MaybeErr MissingInterfaceError ModIface)

    loadSrcInterface_maybe :: SDoc
    -> ModuleName
    -> IsBootInterface
    -> PkgQual
    -> RnM (MaybeErr MissingInterfaceError ModIface)
    loadSrcInterface_maybe SDoc
    doc ModuleName
    mod IsBootInterface
    want_boot PkgQual
    maybe_pkg
      -- We must first find which Module this import refers to.  This involves
      -- calling the Finder, which as a side effect will search the filesystem
      -- and create a ModLocation.  If successful, loadIface will read the
      -- interface; it will call the Finder again, but the ModLocation will be
      -- cached from the first search.
      = do hsc_env <- TcRnIf TcGblEnv TcLclEnv HscEnv
    forall gbl lcl. TcRnIf gbl lcl HscEnv
    getTopEnv
           res <- liftIO $ findImportedModule hsc_env mod maybe_pkg
           case res of
               Found ModLocation
    _ Module
    mod -> IfG (MaybeErr MissingInterfaceError ModIface)
    -> RnM (MaybeErr MissingInterfaceError ModIface)
    forall a. IfG a -> TcRn a
    initIfaceTcRn (IfG (MaybeErr MissingInterfaceError ModIface)
     -> RnM (MaybeErr MissingInterfaceError ModIface))
    -> IfG (MaybeErr MissingInterfaceError ModIface)
    -> RnM (MaybeErr MissingInterfaceError ModIface)
    forall a b. (a -> b) -> a -> b
    $ SDoc
    -> Module
    -> WhereFrom
    -> IfG (MaybeErr MissingInterfaceError ModIface)
    forall lcl.
    SDoc
    -> Module
    -> WhereFrom
    -> IfM lcl (MaybeErr MissingInterfaceError ModIface)
    loadInterface SDoc
    doc Module
    mod (IsBootInterface -> WhereFrom
    ImportByUser IsBootInterface
    want_boot)
               -- TODO: Make sure this error message is good
               FindResult
    err         -> MaybeErr MissingInterfaceError ModIface
    -> RnM (MaybeErr MissingInterfaceError ModIface)
    forall a. a -> IOEnv (Env TcGblEnv TcLclEnv) a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (MissingInterfaceError -> MaybeErr MissingInterfaceError ModIface
    forall err val. err -> MaybeErr err val
    Failed (HscEnv -> ModuleName -> FindResult -> MissingInterfaceError
    cannotFindModule HscEnv
    hsc_env ModuleName
    mod FindResult
    err))

    -- | Load interface directly for a fully qualified 'Module'.  (This is a fairly
    -- rare operation, but in particular it is used to load orphan modules
    -- in order to pull their instances into the global package table and to
    -- handle some operations in GHCi).
    loadModuleInterface :: SDoc -> Module -> TcM ModIface
    loadModuleInterface :: SDoc -> Module -> RnM ModIface
    loadModuleInterface SDoc
    doc Module
    mod = IfG ModIface -> RnM ModIface
    forall a. IfG a -> TcRn a
    initIfaceTcRn (SDoc -> Module -> IfG ModIface
    forall lcl. SDoc -> Module -> IfM lcl ModIface
    loadSysInterface SDoc
    doc Module
    mod)

    -- | Load interfaces for a collection of modules.
    loadModuleInterfaces :: SDoc -> [Module] -> TcM ()
    loadModuleInterfaces :: SDoc -> [Module] -> IOEnv (Env TcGblEnv TcLclEnv) ()
    loadModuleInterfaces SDoc
    doc [Module]
    mods
      | [Module] -> Bool
    forall a. [a] -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    null [Module]
    mods = () -> IOEnv (Env TcGblEnv TcLclEnv) ()
    forall a. a -> IOEnv (Env TcGblEnv TcLclEnv) a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
      | Bool
    otherwise = IfG () -> IOEnv (Env TcGblEnv TcLclEnv) ()
    forall a. IfG a -> TcRn a
    initIfaceTcRn ((Module -> IfG ModIface) -> [Module] -> IfG ()
    forall (t :: * -> *) (m :: * -> *) a b.
    (Foldable t, Monad m) =>
    (a -> m b) -> t a -> m ()
    mapM_ Module -> IfG ModIface
    load [Module]
    mods)
      where
        load :: Module -> IfG ModIface
    load Module
    mod = SDoc -> Module -> IfG ModIface
    forall lcl. SDoc -> Module -> IfM lcl ModIface
    loadSysInterface (SDoc
    doc SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc
    parens (Module -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Module
    mod)) Module
    mod

    -- | Loads the interface for a given Name.
    -- Should only be called for an imported name;
    -- otherwise loadSysInterface may not find the interface
    loadInterfaceForName :: SDoc -> Name -> TcRn ModIface
    loadInterfaceForName :: SDoc -> Name -> RnM ModIface
    loadInterfaceForName SDoc
    doc Name
    name
      = do { Bool
    -> IOEnv (Env TcGblEnv TcLclEnv) ()
    -> IOEnv (Env TcGblEnv TcLclEnv) ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    when Bool
    debugIsOn (IOEnv (Env TcGblEnv TcLclEnv) ()
     -> IOEnv (Env TcGblEnv TcLclEnv) ())
    -> IOEnv (Env TcGblEnv TcLclEnv) ()
    -> IOEnv (Env TcGblEnv TcLclEnv) ()
    forall a b. (a -> b) -> a -> b
    $  -- Check pre-condition
             do { this_mod <- IOEnv (Env TcGblEnv TcLclEnv) Module
    forall (m :: * -> *). HasModule m => m Module
    getModule
                ; massertPpr (not (nameIsLocalOrFrom this_mod name)) (ppr name <+> parens doc) }
          ; Bool -> SDoc -> RnM ModIface -> RnM ModIface
    forall a. HasCallStack => Bool -> SDoc -> a -> a
    assertPpr (Name -> Bool
    isExternalName Name
    name) (Name -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Name
    name) (RnM ModIface -> RnM ModIface) -> RnM ModIface -> RnM ModIface
    forall a b. (a -> b) -> a -> b
    $
            IfG ModIface -> RnM ModIface
    forall a. IfG a -> TcRn a
    initIfaceTcRn (IfG ModIface -> RnM ModIface) -> IfG ModIface -> RnM ModIface
    forall a b. (a -> b) -> a -> b
    $ SDoc -> Module -> IfG ModIface
    forall lcl. SDoc -> Module -> IfM lcl ModIface
    loadSysInterface SDoc
    doc (HasDebugCallStack => Name -> Module
    Name -> Module
    nameModule Name
    name) }

    -- | Loads the interface for a given Module.
    loadInterfaceForModule :: SDoc -> Module -> TcRn ModIface
    loadInterfaceForModule :: SDoc -> Module -> RnM ModIface
    loadInterfaceForModule SDoc
    doc Module
    m
      = do
        -- Should not be called with this module
        Bool
    -> IOEnv (Env TcGblEnv TcLclEnv) ()
    -> IOEnv (Env TcGblEnv TcLclEnv) ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    when Bool
    debugIsOn (IOEnv (Env TcGblEnv TcLclEnv) ()
     -> IOEnv (Env TcGblEnv TcLclEnv) ())
    -> IOEnv (Env TcGblEnv TcLclEnv) ()
    -> IOEnv (Env TcGblEnv TcLclEnv) ()
    forall a b. (a -> b) -> a -> b
    $ do
          this_mod <- IOEnv (Env TcGblEnv TcLclEnv) Module
    forall (m :: * -> *). HasModule m => m Module
    getModule
          massertPpr (this_mod /= m) (ppr m <+> parens doc)
        IfG ModIface -> RnM ModIface
    forall a. IfG a -> TcRn a
    initIfaceTcRn (IfG ModIface -> RnM ModIface) -> IfG ModIface -> RnM ModIface
    forall a b. (a -> b) -> a -> b
    $ SDoc -> Module -> IfG ModIface
    forall lcl. SDoc -> Module -> IfM lcl ModIface
    loadSysInterface SDoc
    doc Module
    m

    {-
    *********************************************************
    *                                                      *
                    loadInterface

            The main function to load an interface
            for an imported module, and put it in
            the External Package State
    *                                                      *
    *********************************************************
    -}

    -- | An 'IfM' function to load the home interface for a wired-in thing,
    -- so that we're sure that we see its instance declarations and rules
    -- See Note [Loading instances for wired-in things]
    loadWiredInHomeIface :: Name -> IfM lcl ()
    loadWiredInHomeIface :: forall lcl. Name -> IfM lcl ()
    loadWiredInHomeIface Name
    name
      = Bool -> IfM lcl () -> IfM lcl ()
    forall a. HasCallStack => Bool -> a -> a
    assert (Name -> Bool
    isWiredInName Name
    name) (IfM lcl () -> IfM lcl ()) -> IfM lcl () -> IfM lcl ()
    forall a b. (a -> b) -> a -> b
    $
        do _ <- SDoc -> Module -> IfM lcl ModIface
    forall lcl. SDoc -> Module -> IfM lcl ModIface
    loadSysInterface SDoc
    doc (HasDebugCallStack => Name -> Module
    Name -> Module
    nameModule Name
    name); return ()
      where
        doc :: SDoc
    doc = String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "Need home interface for wired-in thing" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Name -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Name
    name

    ------------------
    -- | Loads a system interface and throws an exception if it fails
    loadSysInterface :: SDoc -> Module -> IfM lcl ModIface
    loadSysInterface :: forall lcl. SDoc -> Module -> IfM lcl ModIface
    loadSysInterface SDoc
    doc Module
    mod_name = SDoc -> Module -> WhereFrom -> IfM lcl ModIface
    forall lcl. SDoc -> Module -> WhereFrom -> IfM lcl ModIface
    loadInterfaceWithException SDoc
    doc Module
    mod_name WhereFrom
    ImportBySystem

    ------------------
    -- | Loads a user interface and throws an exception if it fails. The first parameter indicates
    -- whether we should import the boot variant of the module
    loadUserInterface :: IsBootInterface -> SDoc -> Module -> IfM lcl ModIface
    loadUserInterface :: forall lcl. IsBootInterface -> SDoc -> Module -> IfM lcl ModIface
    loadUserInterface IsBootInterface
    is_boot SDoc
    doc Module
    mod_name
      = SDoc -> Module -> WhereFrom -> IfM lcl ModIface
    forall lcl. SDoc -> Module -> WhereFrom -> IfM lcl ModIface
    loadInterfaceWithException SDoc
    doc Module
    mod_name (IsBootInterface -> WhereFrom
    ImportByUser IsBootInterface
    is_boot)

    loadPluginInterface :: SDoc -> Module -> IfM lcl ModIface
    loadPluginInterface :: forall lcl. SDoc -> Module -> IfM lcl ModIface
    loadPluginInterface SDoc
    doc Module
    mod_name
      = SDoc -> Module -> WhereFrom -> IfM lcl ModIface
    forall lcl. SDoc -> Module -> WhereFrom -> IfM lcl ModIface
    loadInterfaceWithException SDoc
    doc Module
    mod_name WhereFrom
    ImportByPlugin

    ------------------
    -- | A wrapper for 'loadInterface' that throws an exception if it fails
    loadInterfaceWithException :: SDoc -> Module -> WhereFrom -> IfM lcl ModIface
    loadInterfaceWithException :: forall lcl. SDoc -> Module -> WhereFrom -> IfM lcl ModIface
    loadInterfaceWithException SDoc
    doc Module
    mod_name WhereFrom
    where_from
      = do
        dflags <- IOEnv (Env IfGblEnv lcl) DynFlags
    forall (m :: * -> *). HasDynFlags m => m DynFlags
    getDynFlags
        let ctx = DynFlags -> PprStyle -> SDocContext
    initSDocContext DynFlags
    dflags PprStyle
    defaultUserStyle
        withIfaceErr ctx (loadInterface doc mod_name where_from)

    ------------------
    loadInterface :: SDoc -> Module -> WhereFrom
                  -> IfM lcl (MaybeErr MissingInterfaceError ModIface)

    -- loadInterface looks in both the HPT and PIT for the required interface
    -- If not found, it loads it, and puts it in the PIT (always).

    -- If it can't find a suitable interface file, we
    --      a) modify the PackageIfaceTable to have an empty entry
    --              (to avoid repeated complaints)
    --      b) return (Left message)
    --
    -- It's not necessarily an error for there not to be an interface
    -- file -- perhaps the module has changed, and that interface
    -- is no longer used

    loadInterface :: forall lcl.
    SDoc
    -> Module
    -> WhereFrom
    -> IfM lcl (MaybeErr MissingInterfaceError ModIface)
    loadInterface SDoc
    doc_str Module
    mod WhereFrom
    from
      | Module -> Bool
    forall u. GenModule (GenUnit u) -> Bool
    isHoleModule Module
    mod
      -- Hole modules get special treatment
      = do hsc_env <- TcRnIf IfGblEnv lcl HscEnv
    forall gbl lcl. TcRnIf gbl lcl HscEnv
    getTopEnv
           let home_unit = HscEnv -> HomeUnit
    hsc_home_unit HscEnv
    hsc_env
           -- Redo search for our local hole module
           loadInterface doc_str (mkHomeModule home_unit (moduleName mod)) from
      | Bool
    otherwise
      = do
        logger <- IOEnv (Env IfGblEnv lcl) Logger
    forall (m :: * -> *). HasLogger m => m Logger
    getLogger
        withTimingSilent logger (text "loading interface") (pure ()) $ do
            {       -- Read the state
              (eps,hug) <- getEpsAndHug
            ; gbl_env <- getGblEnv

            ; liftIO $ trace_if logger (text "Considering whether to load" <+> ppr mod <+> ppr from)

                    -- Check whether we have the interface already
            ; hsc_env <- getTopEnv
            ; let mhome_unit = UnitEnv -> Maybe HomeUnit
    ue_homeUnit (HscEnv -> UnitEnv
    hsc_unit_env HscEnv
    hsc_env)
            ; case lookupIfaceByModule hug (eps_PIT eps) mod of {
                Just ModIface
    iface
                    -> MaybeErr MissingInterfaceError ModIface
    -> IfM lcl (MaybeErr MissingInterfaceError ModIface)
    forall a. a -> IOEnv (Env IfGblEnv lcl) a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (ModIface -> MaybeErr MissingInterfaceError ModIface
    forall err val. val -> MaybeErr err val
    Succeeded ModIface
    iface) ;   -- Already loaded
                Maybe ModIface
    _ -> do {

            -- READ THE MODULE IN
            ; read_result <- case Maybe HomeUnit
    -> ExternalPackageState
    -> Module
    -> WhereFrom
    -> MaybeErr MissingInterfaceError IsBootInterface
    wantHiBootFile Maybe HomeUnit
    mhome_unit ExternalPackageState
    eps Module
    mod WhereFrom
    from of
                               Failed MissingInterfaceError
    err             -> MaybeErr MissingInterfaceError (ModIface, String)
    -> IOEnv
         (Env IfGblEnv lcl)
         (MaybeErr MissingInterfaceError (ModIface, String))
    forall a. a -> IOEnv (Env IfGblEnv lcl) a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (MissingInterfaceError
    -> MaybeErr MissingInterfaceError (ModIface, String)
    forall err val. err -> MaybeErr err val
    Failed MissingInterfaceError
    err)
                               Succeeded IsBootInterface
    hi_boot_file -> do
                                 hsc_env <- TcRnIf IfGblEnv lcl HscEnv
    forall gbl lcl. TcRnIf gbl lcl HscEnv
    getTopEnv
                                 liftIO $ computeInterface hsc_env doc_str hi_boot_file mod
            ; case read_result of {
                Failed MissingInterfaceError
    err -> do
                    { let fake_iface :: ModIface
    fake_iface = Module -> ModIface
    emptyFullModIface Module
    mod

                    ; (ExternalPackageState -> ExternalPackageState)
    -> IOEnv (Env IfGblEnv lcl) ()
    forall gbl lcl.
    (ExternalPackageState -> ExternalPackageState) -> TcRnIf gbl lcl ()
    updateEps_ ((ExternalPackageState -> ExternalPackageState)
     -> IOEnv (Env IfGblEnv lcl) ())
    -> (ExternalPackageState -> ExternalPackageState)
    -> IOEnv (Env IfGblEnv lcl) ()
    forall a b. (a -> b) -> a -> b
    $ \ExternalPackageState
    eps ->
                            ExternalPackageState
    eps { eps_PIT = extendModuleEnv (eps_PIT eps) (mi_module fake_iface) fake_iface }
                            -- Not found, so add an empty iface to
                            -- the EPS map so that we don't look again

                    ; MaybeErr MissingInterfaceError ModIface
    -> IfM lcl (MaybeErr MissingInterfaceError ModIface)
    forall a. a -> IOEnv (Env IfGblEnv lcl) a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (MissingInterfaceError -> MaybeErr MissingInterfaceError ModIface
    forall err val. err -> MaybeErr err val
    Failed MissingInterfaceError
    err) } ;

            -- Found and parsed!
            -- We used to have a sanity check here that looked for:
            --  * System importing ..
            --  * a home package module ..
            --  * that we know nothing about (mb_dep == Nothing)!
            --
            -- But this is no longer valid because thNameToGhcName allows users to
            -- cause the system to load arbitrary interfaces (by supplying an appropriate
            -- Template Haskell original-name).
                Succeeded (ModIface
    iface, String
    loc) ->
            let
                loc_doc :: SDoc
    loc_doc = String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    loc
            in
            Module
    -> SDoc
    -> IsBootInterface
    -> IfL (MaybeErr MissingInterfaceError ModIface)
    -> IfM lcl (MaybeErr MissingInterfaceError ModIface)
    forall a lcl.
    Module -> SDoc -> IsBootInterface -> IfL a -> IfM lcl a
    initIfaceLcl (ModIface -> Module
    forall (phase :: ModIfacePhase). ModIface_ phase -> Module
    mi_semantic_module ModIface
    iface) SDoc
    loc_doc (ModIface -> IsBootInterface
    mi_boot ModIface
    iface) (IfL (MaybeErr MissingInterfaceError ModIface)
     -> IfM lcl (MaybeErr MissingInterfaceError ModIface))
    -> IfL (MaybeErr MissingInterfaceError ModIface)
    -> IfM lcl (MaybeErr MissingInterfaceError ModIface)
    forall a b. (a -> b) -> a -> b
    $

            IfL (MaybeErr MissingInterfaceError ModIface)
    -> IfL (MaybeErr MissingInterfaceError ModIface)
    forall a. IfL a -> IfL a
    dontLeakTheHUG (IfL (MaybeErr MissingInterfaceError ModIface)
     -> IfL (MaybeErr MissingInterfaceError ModIface))
    -> IfL (MaybeErr MissingInterfaceError ModIface)
    -> IfL (MaybeErr MissingInterfaceError ModIface)
    forall a b. (a -> b) -> a -> b
    $ do

            --      Load the new ModIface into the External Package State
            -- Even home-package interfaces loaded by loadInterface
            --      (which only happens in OneShot mode; in Batch/Interactive
            --      mode, home-package modules are loaded one by one into the HPT)
            -- are put in the EPS.
            --
            -- The main thing is to add the ModIface to the PIT, but
            -- we also take the
            --      IfaceDecls, IfaceClsInst, IfaceFamInst, IfaceRules,
            -- out of the ModIface and put them into the big EPS pools

            -- NB: *first* we do tcIfaceDecls, so that the provenance of all the locally-defined
            ---    names is done correctly (notably, whether this is an .hi file or .hi-boot file).
            --     If we do loadExport first the wrong info gets into the cache (unless we
            --      explicitly tag each export which seems a bit of a bore)

            -- Crucial assertion that checks if you are trying to load a HPT module into the EPS.
            -- If you start loading HPT modules into the EPS then you get strange errors about
            -- overlapping instances.
            ; Bool -> SDoc -> IfL ()
    forall (m :: * -> *).
    (HasCallStack, Applicative m) =>
    Bool -> SDoc -> m ()
    massertPpr
                  ((GhcMode -> Bool
    isOneShot (DynFlags -> GhcMode
    ghcMode (HscEnv -> DynFlags
    hsc_dflags HscEnv
    hsc_env)))
                    Bool -> Bool -> Bool
    || Module -> UnitId
    moduleUnitId Module
    mod UnitId -> Set UnitId -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `notElem` HscEnv -> Set UnitId
    hsc_all_home_unit_ids HscEnv
    hsc_env
                    Bool -> Bool -> Bool
    || Module
    mod Module -> Module -> Bool
    forall a. Eq a => a -> a -> Bool
    == Module
    gHC_PRIM)
                    (String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "Attempting to load home package interface into the EPS" SDoc -> SDoc -> SDoc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$ HomeUnitGraph -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr HomeUnitGraph
    hug SDoc -> SDoc -> SDoc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$ SDoc
    doc_str SDoc -> SDoc -> SDoc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$ Module -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Module
    mod SDoc -> SDoc -> SDoc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$ UnitId -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr (Module -> UnitId
    moduleUnitId Module
    mod))
            ; ignore_prags      <- GeneralFlag -> TcRnIf IfGblEnv IfLclEnv Bool
    forall gbl lcl. GeneralFlag -> TcRnIf gbl lcl Bool
    goptM GeneralFlag
    Opt_IgnoreInterfacePragmas
            ; new_eps_decls     <- tcIfaceDecls ignore_prags (mi_decls iface)
            ; new_eps_insts     <- mapM tcIfaceInst (mi_insts iface)
            ; new_eps_fam_insts <- mapM tcIfaceFamInst (mi_fam_insts iface)
            ; new_eps_rules     <- tcIfaceRules ignore_prags (mi_rules iface)
            ; new_eps_anns      <- tcIfaceAnnotations (mi_anns iface)
            ; new_eps_complete_matches <- tcIfaceCompleteMatches (mi_complete_matches iface)

            ; let { final_iface = ModIface
    iface {
                                    mi_decls     = panic "No mi_decls in PIT",
                                    mi_insts     = panic "No mi_insts in PIT",
                                    mi_fam_insts = panic "No mi_fam_insts in PIT",
                                    mi_rules     = panic "No mi_rules in PIT",
                                    mi_anns      = panic "No mi_anns in PIT"
                                  }
                   }

            ; let bad_boot = ModIface -> IsBootInterface
    mi_boot ModIface
    iface IsBootInterface -> IsBootInterface -> Bool
    forall a. Eq a => a -> a -> Bool
    == IsBootInterface
    IsBoot
                              Bool -> Bool -> Bool
    && Maybe (IfG TypeEnv) -> Bool
    forall a. Maybe a -> Bool
    isJust (KnotVars (IfG TypeEnv) -> Module -> Maybe (IfG TypeEnv)
    forall a. KnotVars a -> Module -> Maybe a
    lookupKnotVars (IfGblEnv -> KnotVars (IfG TypeEnv)
    if_rec_types IfGblEnv
    gbl_env) Module
    mod)
                                -- Warn against an EPS-updating import
                                -- of one's own boot file! (one-shot only)
                                -- See Note [Loading your own hi-boot file]

            ; warnPprTrace bad_boot "loadInterface" (ppr mod) $
              updateEps_  $ \ ExternalPackageState
    eps ->
               if Module -> PackageIfaceTable -> Bool
    forall a. Module -> ModuleEnv a -> Bool
    elemModuleEnv Module
    mod (ExternalPackageState -> PackageIfaceTable
    eps_PIT ExternalPackageState
    eps) Bool -> Bool -> Bool
    || Maybe HomeUnit -> ModIface -> Bool
    is_external_sig Maybe HomeUnit
    mhome_unit ModIface
    iface
                    then ExternalPackageState
    eps
               else if Bool
    bad_boot
                    -- See Note [Loading your own hi-boot file]
                    then ExternalPackageState
    eps { eps_PTE = addDeclsToPTE (eps_PTE eps) new_eps_decls }
               else
                    ExternalPackageState
    eps {
                      eps_PIT          = extendModuleEnv (eps_PIT eps) mod final_iface,
                      eps_PTE          = addDeclsToPTE   (eps_PTE eps) new_eps_decls,
                      eps_rule_base    = extendRuleBaseList (eps_rule_base eps)
                                                            new_eps_rules,
                      eps_complete_matches
                                       = eps_complete_matches eps ++ new_eps_complete_matches,
                      eps_inst_env     = extendInstEnvList (eps_inst_env eps)
                                                           new_eps_insts,
                      eps_fam_inst_env = extendFamInstEnvList (eps_fam_inst_env eps)
                                                              new_eps_fam_insts,
                      eps_ann_env      = extendAnnEnvList (eps_ann_env eps)
                                                          new_eps_anns,
                      eps_mod_fam_inst_env
                                       = let
                                           fam_inst_env =
                                             FamInstEnv -> [FamInst] -> FamInstEnv
    extendFamInstEnvList FamInstEnv
    emptyFamInstEnv
                                                                  [FamInst]
    new_eps_fam_insts
                                         in
                                         extendModuleEnv (eps_mod_fam_inst_env eps)
                                                         mod
                                                         fam_inst_env,
                      eps_stats        = addEpsInStats (eps_stats eps)
                                                       (length new_eps_decls)
                                                       (length new_eps_insts)
                                                       (length new_eps_rules) }

            ; -- invoke plugins with *full* interface, not final_iface, to ensure
              -- that plugins have access to declarations, etc.
              res <- withPlugins (hsc_plugins hsc_env) (\Plugin
    p -> Plugin -> forall lcl. [String] -> ModIface -> IfM lcl ModIface
    interfaceLoadAction Plugin
    p) iface
            ; return (Succeeded res)
        }}}}

    {- Note [Loading your own hi-boot file]
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Generally speaking, when compiling module M, we should not
    load M.hi boot into the EPS.  After all, we are very shortly
    going to have full information about M.  Moreover, see
    Note [Do not update EPS with your own hi-boot] in GHC.Iface.Recomp.

    But there is a HORRIBLE HACK here.

    * At the end of tcRnImports, we call checkFamInstConsistency to
      check consistency of imported type-family instances
      See Note [The type family instance consistency story] in GHC.Tc.Instance.Family

    * Alas, those instances may refer to data types defined in M,
      if there is a M.hs-boot.

    * And that means we end up loading M.hi-boot, because those
      data types are not yet in the type environment.

    But in this weird case, /all/ we need is the types. We don't need
    instances, rules etc.  And if we put the instances in the EPS
    we get "duplicate instance" warnings when we compile the "real"
    instance in M itself.  Hence the strange business of just updateing
    the eps_PTE.

    This really happens in practice.  The module "GHC.Hs.Expr" gets
    "duplicate instance" errors if this hack is not present.

    This is a mess.

    Note [Home Unit Graph space leak]
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    Ticket: #15111

    In IfL, we defer some work until it is demanded using forkM, such
    as building TyThings from IfaceDecls. These thunks are stored in
    the ExternalPackageState, and they might never be poked.  If we're
    not careful, these thunks will capture the state of the loaded
    program when we read an interface file, and retain all that data
    for ever.

    Therefore, when loading a package interface file , we use a "clean"
    version of the HscEnv with all the data about the currently loaded
    program stripped out. Most of the fields can be panics because
    we'll never read them, but hsc_HUG needs to be empty because this
    interface will cause other interfaces to be loaded recursively, and
    when looking up those interfaces we use the HUG in loadInterface.
    We know that none of the interfaces below here can refer to
    home-package modules however, so it's safe for the HUG to be empty.
    -}

    -- Note [GHC Heap Invariants]
    -- Note [Home Unit Graph space leak]
    dontLeakTheHUG :: IfL a -> IfL a
    dontLeakTheHUG :: forall a. IfL a -> IfL a
    dontLeakTheHUG IfL a
    thing_inside = do
      env <- TcRnIf IfGblEnv IfLclEnv HscEnv
    forall gbl lcl. TcRnIf gbl lcl HscEnv
    getTopEnv
      let
        inOneShot =
          GhcMode -> Bool
    isOneShot (DynFlags -> GhcMode
    ghcMode (HscEnv -> DynFlags
    hsc_dflags HscEnv
    env))
        cleanGblEnv IfGblEnv
    gbl_env
          | Bool
    inOneShot = IfGblEnv
    gbl_env
          | Bool
    otherwise = IfGblEnv
    gbl_env { if_rec_types = emptyKnotVars }
        cleanTopEnv HscEnv
    hsc_env =

           let
             !maybe_type_vars :: Maybe (KnotVars (IORef TypeEnv))
    maybe_type_vars | Bool
    inOneShot = KnotVars (IORef TypeEnv) -> Maybe (KnotVars (IORef TypeEnv))
    forall a. a -> Maybe a
    Just (HscEnv -> KnotVars (IORef TypeEnv)
    hsc_type_env_vars HscEnv
    env)
                              | Bool
    otherwise = Maybe (KnotVars (IORef TypeEnv))
    forall a. Maybe a
    Nothing
             -- wrinkle: when we're typechecking in --backpack mode, the
             -- instantiation of a signature might reside in the HPT, so
             -- this case breaks the assumption that EPS interfaces only
             -- refer to other EPS interfaces.
             -- As a temporary (MP Oct 2021 #20509) we only keep the HPT if it
             -- contains any hole modules.
             -- Quite a few tests in testsuite/tests/backpack break without this
             -- tweak.
             old_unit_env :: UnitEnv
    old_unit_env = HscEnv -> UnitEnv
    hsc_unit_env HscEnv
    hsc_env
             keepFor20509 :: HomeModInfo -> Bool
    keepFor20509 HomeModInfo
    hmi
              | Module -> Bool
    forall u. GenModule (GenUnit u) -> Bool
    isHoleModule (ModIface -> Module
    forall (phase :: ModIfacePhase). ModIface_ phase -> Module
    mi_semantic_module (HomeModInfo -> ModIface
    hm_iface HomeModInfo
    hmi)) = Bool
    True
              | Bool
    otherwise = Bool
    False
             pruneHomeUnitEnv :: HomeUnitEnv -> HomeUnitEnv
    pruneHomeUnitEnv HomeUnitEnv
    hme = HomeUnitEnv
    hme { homeUnitEnv_hpt = emptyHomePackageTable }
             !unit_env :: UnitEnv
    unit_env
              = UnitEnv
    old_unit_env
                 { ue_home_unit_graph = if anyHpt keepFor20509 (ue_hpt old_unit_env) then ue_home_unit_graph old_unit_env
                                                                                     else unitEnv_map pruneHomeUnitEnv (ue_home_unit_graph old_unit_env)
                 }
           in
           HscEnv
    hsc_env {  hsc_targets      = panic "cleanTopEnv: hsc_targets"
                   ,  hsc_mod_graph    = panic "cleanTopEnv: hsc_mod_graph"
                   ,  hsc_IC           = panic "cleanTopEnv: hsc_IC"
                   ,  hsc_type_env_vars = case maybe_type_vars of
                                              Just KnotVars (IORef TypeEnv)
    vars -> KnotVars (IORef TypeEnv)
    vars
                                              Maybe (KnotVars (IORef TypeEnv))
    Nothing -> String -> KnotVars (IORef TypeEnv)
    forall a. HasCallStack => String -> a
    panic String
    "cleanTopEnv: hsc_type_env_vars"
                   ,  hsc_unit_env     = unit_env
                   }

      updTopEnv cleanTopEnv $ updGblEnv cleanGblEnv $ do
      !_ <- getTopEnv        -- force the updTopEnv
      !_ <- getGblEnv
      thing_inside

    -- | Returns @True@ if a 'ModIface' comes from an external package.
    -- In this case, we should NOT load it into the EPS; the entities
    -- should instead come from the local merged signature interface.
    is_external_sig :: Maybe HomeUnit -> ModIface -> Bool
    is_external_sig :: Maybe HomeUnit -> ModIface -> Bool
    is_external_sig Maybe HomeUnit
    mhome_unit ModIface
    iface =
        -- It's a signature iface...
        ModIface -> Module
    forall (phase :: ModIfacePhase). ModIface_ phase -> Module
    mi_semantic_module ModIface
    iface Module -> Module -> Bool
    forall a. Eq a => a -> a -> Bool
    /= ModIface -> Module
    forall (phase :: ModIfacePhase). ModIface_ phase -> Module
    mi_module ModIface
    iface Bool -> Bool -> Bool
    &&
        -- and it's not from the local package
        Maybe HomeUnit -> Module -> Bool
    notHomeModuleMaybe Maybe HomeUnit
    mhome_unit (ModIface -> Module
    forall (phase :: ModIfacePhase). ModIface_ phase -> Module
    mi_module ModIface
    iface)

    -- | This is an improved version of 'findAndReadIface' which can also
    -- handle the case when a user requests @p[A=<B>]:M@ but we only
    -- have an interface for @p[A=<A>]:M@ (the indefinite interface.
    -- If we are not trying to build code, we load the interface we have,
    -- *instantiating it* according to how the holes are specified.
    -- (Of course, if we're actually building code, this is a hard error.)
    --
    -- In the presence of holes, 'computeInterface' has an important invariant:
    -- to load module M, its set of transitively reachable requirements must
    -- have an up-to-date local hi file for that requirement.  Note that if
    -- we are loading the interface of a requirement, this does not
    -- apply to the requirement itself; e.g., @p[A=<A>]:A@ does not require
    -- A.hi to be up-to-date (and indeed, we MUST NOT attempt to read A.hi, unless
    -- we are actually typechecking p.)
    computeInterface
      :: HscEnv
      -> SDoc
      -> IsBootInterface
      -> Module
      -> IO (MaybeErr MissingInterfaceError (ModIface, FilePath))
    computeInterface :: HscEnv
    -> SDoc
    -> IsBootInterface
    -> Module
    -> IO (MaybeErr MissingInterfaceError (ModIface, String))
    computeInterface HscEnv
    hsc_env SDoc
    doc_str IsBootInterface
    hi_boot_file Module
    mod0 = do
      Bool -> IO ()
    forall (m :: * -> *). (HasCallStack, Applicative m) => Bool -> m ()
    massert (Bool -> Bool
    not (Module -> Bool
    forall u. GenModule (GenUnit u) -> Bool
    isHoleModule Module
    mod0))
      let mhome_unit :: Maybe HomeUnit
    mhome_unit  = HscEnv -> Maybe HomeUnit
    hsc_home_unit_maybe HscEnv
    hsc_env
      let find_iface :: GenModule UnitId
    -> IO (MaybeErr MissingInterfaceError (ModIface, String))
    find_iface GenModule UnitId
    m = HscEnv
    -> SDoc
    -> GenModule UnitId
    -> Module
    -> IsBootInterface
    -> IO (MaybeErr MissingInterfaceError (ModIface, String))
    findAndReadIface HscEnv
    hsc_env SDoc
    doc_str
                                          GenModule UnitId
    m Module
    mod0 IsBootInterface
    hi_boot_file
      case Module -> (GenModule UnitId, Maybe InstantiatedModule)
    getModuleInstantiation Module
    mod0 of
          (GenModule UnitId
    imod, Just InstantiatedModule
    indef)
            | Just HomeUnit
    home_unit <- Maybe HomeUnit
    mhome_unit
            , HomeUnit -> Bool
    forall u. GenHomeUnit u -> Bool
    isHomeUnitIndefinite HomeUnit
    home_unit ->
              GenModule UnitId
    -> IO (MaybeErr MissingInterfaceError (ModIface, String))
    find_iface GenModule UnitId
    imod IO (MaybeErr MissingInterfaceError (ModIface, String))
    -> (MaybeErr MissingInterfaceError (ModIface, String)
        -> IO (MaybeErr MissingInterfaceError (ModIface, String)))
    -> IO (MaybeErr MissingInterfaceError (ModIface, String))
    forall a b. IO a -> (a -> IO b) -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= \case
                Succeeded (ModIface
    iface0, String
    path) ->
                  HscEnv
    -> [(ModuleName, Module)]
    -> Maybe NameShape
    -> ModIface
    -> IO (Either (Messages TcRnMessage) ModIface)
    rnModIface HscEnv
    hsc_env (GenInstantiatedUnit UnitId -> [(ModuleName, Module)]
    forall unit. GenInstantiatedUnit unit -> GenInstantiations unit
    instUnitInsts (InstantiatedModule -> GenInstantiatedUnit UnitId
    forall unit. GenModule unit -> unit
    moduleUnit InstantiatedModule
    indef)) Maybe NameShape
    forall a. Maybe a
    Nothing ModIface
    iface0 IO (Either (Messages TcRnMessage) ModIface)
    -> (Either (Messages TcRnMessage) ModIface
        -> IO (MaybeErr MissingInterfaceError (ModIface, String)))
    -> IO (MaybeErr MissingInterfaceError (ModIface, String))
    forall a b. IO a -> (a -> IO b) -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= \case
                    Right ModIface
    x   -> MaybeErr MissingInterfaceError (ModIface, String)
    -> IO (MaybeErr MissingInterfaceError (ModIface, String))
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ((ModIface, String)
    -> MaybeErr MissingInterfaceError (ModIface, String)
    forall err val. val -> MaybeErr err val
    Succeeded (ModIface
    x, String
    path))
                    Left Messages TcRnMessage
    errs -> Messages GhcMessage
    -> IO (MaybeErr MissingInterfaceError (ModIface, String))
    forall (io :: * -> *) a. MonadIO io => Messages GhcMessage -> io a
    throwErrors (TcRnMessage -> GhcMessage
    GhcTcRnMessage (TcRnMessage -> GhcMessage)
    -> Messages TcRnMessage -> Messages GhcMessage
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Messages TcRnMessage
    errs)
                Failed MissingInterfaceError
    err -> MaybeErr MissingInterfaceError (ModIface, String)
    -> IO (MaybeErr MissingInterfaceError (ModIface, String))
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (MissingInterfaceError
    -> MaybeErr MissingInterfaceError (ModIface, String)
    forall err val. err -> MaybeErr err val
    Failed MissingInterfaceError
    err)
          (GenModule UnitId
    mod, Maybe InstantiatedModule
    _) -> GenModule UnitId
    -> IO (MaybeErr MissingInterfaceError (ModIface, String))
    find_iface GenModule UnitId
    mod

    -- | Compute the signatures which must be compiled in order to
    -- load the interface for a 'Module'.  The output of this function
    -- is always a subset of 'moduleFreeHoles'; it is more precise
    -- because in signature @p[A=\<A>,B=\<B>]:B@, although the free holes
    -- are A and B, B might not depend on A at all!
    --
    -- If this is invoked on a signature, this does NOT include the
    -- signature itself; e.g. precise free module holes of
    -- @p[A=\<A>,B=\<B>]:B@ never includes B.
    moduleFreeHolesPrecise
        :: SDoc -> Module
        -> TcRnIf gbl lcl (MaybeErr MissingInterfaceError (UniqDSet ModuleName))
    moduleFreeHolesPrecise :: forall gbl lcl.
    SDoc
    -> Module
    -> TcRnIf
         gbl lcl (MaybeErr MissingInterfaceError (UniqDSet ModuleName))
    moduleFreeHolesPrecise SDoc
    doc_str Module
    mod
     | Module -> Bool
    moduleIsDefinite Module
    mod = MaybeErr MissingInterfaceError (UniqDSet ModuleName)
    -> IOEnv
         (Env gbl lcl)
         (MaybeErr MissingInterfaceError (UniqDSet ModuleName))
    forall a. a -> IOEnv (Env gbl lcl) a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (UniqDSet ModuleName
    -> MaybeErr MissingInterfaceError (UniqDSet ModuleName)
    forall err val. val -> MaybeErr err val
    Succeeded UniqDSet ModuleName
    forall a. UniqDSet a
    emptyUniqDSet)
     | Bool
    otherwise =
       case Module -> (GenModule UnitId, Maybe InstantiatedModule)
    getModuleInstantiation Module
    mod of
        (GenModule UnitId
    imod, Just InstantiatedModule
    indef) -> do
            logger <- IOEnv (Env gbl lcl) Logger
    forall (m :: * -> *). HasLogger m => m Logger
    getLogger
            let insts = GenInstantiatedUnit UnitId -> [(ModuleName, Module)]
    forall unit. GenInstantiatedUnit unit -> GenInstantiations unit
    instUnitInsts (InstantiatedModule -> GenInstantiatedUnit UnitId
    forall unit. GenModule unit -> unit
    moduleUnit InstantiatedModule
    indef)
            liftIO $ trace_if logger (text "Considering whether to load" <+> ppr mod <+>
                     text "to compute precise free module holes")
            (eps, hpt) <- getEpsAndHug
            case tryEpsAndHpt eps hpt `firstJust` tryDepsCache eps imod insts of
                Just UniqDSet ModuleName
    r -> MaybeErr MissingInterfaceError (UniqDSet ModuleName)
    -> IOEnv
         (Env gbl lcl)
         (MaybeErr MissingInterfaceError (UniqDSet ModuleName))
    forall a. a -> IOEnv (Env gbl lcl) a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (UniqDSet ModuleName
    -> MaybeErr MissingInterfaceError (UniqDSet ModuleName)
    forall err val. val -> MaybeErr err val
    Succeeded UniqDSet ModuleName
    r)
                Maybe (UniqDSet ModuleName)
    Nothing -> GenModule UnitId
    -> [(ModuleName, Module)]
    -> IOEnv
         (Env gbl lcl)
         (MaybeErr MissingInterfaceError (UniqDSet ModuleName))
    readAndCache GenModule UnitId
    imod [(ModuleName, Module)]
    insts
        (GenModule UnitId
    _, Maybe InstantiatedModule
    Nothing) -> MaybeErr MissingInterfaceError (UniqDSet ModuleName)
    -> IOEnv
         (Env gbl lcl)
         (MaybeErr MissingInterfaceError (UniqDSet ModuleName))
    forall a. a -> IOEnv (Env gbl lcl) a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (UniqDSet ModuleName
    -> MaybeErr MissingInterfaceError (UniqDSet ModuleName)
    forall err val. val -> MaybeErr err val
    Succeeded UniqDSet ModuleName
    forall a. UniqDSet a
    emptyUniqDSet)
      where
        tryEpsAndHpt :: ExternalPackageState
    -> HomeUnitGraph -> Maybe (UniqDSet ModuleName)
    tryEpsAndHpt ExternalPackageState
    eps HomeUnitGraph
    hpt =
            (ModIface -> UniqDSet ModuleName)
    -> Maybe ModIface -> Maybe (UniqDSet ModuleName)
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap ModIface -> UniqDSet ModuleName
    mi_free_holes (HomeUnitGraph -> PackageIfaceTable -> Module -> Maybe ModIface
    lookupIfaceByModule HomeUnitGraph
    hpt (ExternalPackageState -> PackageIfaceTable
    eps_PIT ExternalPackageState
    eps) Module
    mod)
        tryDepsCache :: ExternalPackageState
    -> GenModule UnitId
    -> [(ModuleName, Module)]
    -> Maybe (UniqDSet ModuleName)
    tryDepsCache ExternalPackageState
    eps GenModule UnitId
    imod [(ModuleName, Module)]
    insts =
            case InstalledModuleEnv (UniqDSet ModuleName)
    -> GenModule UnitId -> Maybe (UniqDSet ModuleName)
    forall a. InstalledModuleEnv a -> GenModule UnitId -> Maybe a
    lookupInstalledModuleEnv (ExternalPackageState -> InstalledModuleEnv (UniqDSet ModuleName)
    eps_free_holes ExternalPackageState
    eps) GenModule UnitId
    imod of
                Just UniqDSet ModuleName
    ifhs  -> UniqDSet ModuleName -> Maybe (UniqDSet ModuleName)
    forall a. a -> Maybe a
    Just (UniqDSet ModuleName
    -> [(ModuleName, Module)] -> UniqDSet ModuleName
    renameFreeHoles UniqDSet ModuleName
    ifhs [(ModuleName, Module)]
    insts)
                Maybe (UniqDSet ModuleName)
    _otherwise -> Maybe (UniqDSet ModuleName)
    forall a. Maybe a
    Nothing
        readAndCache :: GenModule UnitId
    -> [(ModuleName, Module)]
    -> IOEnv
         (Env gbl lcl)
         (MaybeErr MissingInterfaceError (UniqDSet ModuleName))
    readAndCache GenModule UnitId
    imod [(ModuleName, Module)]
    insts = do
            hsc_env <- TcRnIf gbl lcl HscEnv
    forall gbl lcl. TcRnIf gbl lcl HscEnv
    getTopEnv
            mb_iface <- liftIO $ findAndReadIface hsc_env
                                                  (text "moduleFreeHolesPrecise" <+> doc_str)
                                                  imod mod NotBoot
            case mb_iface of
                Succeeded (ModIface
    iface, String
    _) -> do
                    let ifhs :: UniqDSet ModuleName
    ifhs = ModIface -> UniqDSet ModuleName
    mi_free_holes ModIface
    iface
                    -- Cache it
                    (ExternalPackageState -> ExternalPackageState)
    -> IOEnv (Env gbl lcl) ()
    forall gbl lcl.
    (ExternalPackageState -> ExternalPackageState) -> TcRnIf gbl lcl ()
    updateEps_ (\ExternalPackageState
    eps ->
                        ExternalPackageState
    eps { eps_free_holes = extendInstalledModuleEnv (eps_free_holes eps) imod ifhs })
                    MaybeErr MissingInterfaceError (UniqDSet ModuleName)
    -> IOEnv
         (Env gbl lcl)
         (MaybeErr MissingInterfaceError (UniqDSet ModuleName))
    forall a. a -> IOEnv (Env gbl lcl) a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (UniqDSet ModuleName
    -> MaybeErr MissingInterfaceError (UniqDSet ModuleName)
    forall err val. val -> MaybeErr err val
    Succeeded (UniqDSet ModuleName
    -> [(ModuleName, Module)] -> UniqDSet ModuleName
    renameFreeHoles UniqDSet ModuleName
    ifhs [(ModuleName, Module)]
    insts))
                Failed MissingInterfaceError
    err -> MaybeErr MissingInterfaceError (UniqDSet ModuleName)
    -> IOEnv
         (Env gbl lcl)
         (MaybeErr MissingInterfaceError (UniqDSet ModuleName))
    forall a. a -> IOEnv (Env gbl lcl) a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (MissingInterfaceError
    -> MaybeErr MissingInterfaceError (UniqDSet ModuleName)
    forall err val. err -> MaybeErr err val
    Failed MissingInterfaceError
    err)

    wantHiBootFile :: Maybe HomeUnit -> ExternalPackageState -> Module -> WhereFrom
                   -> MaybeErr MissingInterfaceError IsBootInterface
    -- Figure out whether we want Foo.hi or Foo.hi-boot
    wantHiBootFile :: Maybe HomeUnit
    -> ExternalPackageState
    -> Module
    -> WhereFrom
    -> MaybeErr MissingInterfaceError IsBootInterface
    wantHiBootFile Maybe HomeUnit
    mhome_unit ExternalPackageState
    eps Module
    mod WhereFrom
    from
      = case WhereFrom
    from of
           ImportByUser IsBootInterface
    usr_boot
              | IsBootInterface
    usr_boot IsBootInterface -> IsBootInterface -> Bool
    forall a. Eq a => a -> a -> Bool
    == IsBootInterface
    IsBoot Bool -> Bool -> Bool
    && Maybe HomeUnit -> Module -> Bool
    notHomeModuleMaybe Maybe HomeUnit
    mhome_unit Module
    mod
              -> MissingInterfaceError
    -> MaybeErr MissingInterfaceError IsBootInterface
    forall err val. err -> MaybeErr err val
    Failed (Module -> MissingInterfaceError
    BadSourceImport Module
    mod)
              | Bool
    otherwise -> IsBootInterface -> MaybeErr MissingInterfaceError IsBootInterface
    forall err val. val -> MaybeErr err val
    Succeeded IsBootInterface
    usr_boot

           WhereFrom
    ImportByPlugin
              -> IsBootInterface -> MaybeErr MissingInterfaceError IsBootInterface
    forall err val. val -> MaybeErr err val
    Succeeded IsBootInterface
    NotBoot

           WhereFrom
    ImportBySystem
              | Maybe HomeUnit -> Module -> Bool
    notHomeModuleMaybe Maybe HomeUnit
    mhome_unit Module
    mod
              -> IsBootInterface -> MaybeErr MissingInterfaceError IsBootInterface
    forall err val. val -> MaybeErr err val
    Succeeded IsBootInterface
    NotBoot
                 -- If the module to be imported is not from this package
                 -- don't look it up in eps_is_boot, because that is keyed
                 -- on the ModuleName of *home-package* modules only.
                 -- We never import boot modules from other packages!

              | Bool
    otherwise
              -> case InstalledModuleEnv ModuleNameWithIsBoot
    -> GenModule UnitId -> Maybe ModuleNameWithIsBoot
    forall a. InstalledModuleEnv a -> GenModule UnitId -> Maybe a
    lookupInstalledModuleEnv (ExternalPackageState -> InstalledModuleEnv ModuleNameWithIsBoot
    eps_is_boot ExternalPackageState
    eps) (GenUnit UnitId -> UnitId
    toUnitId (GenUnit UnitId -> UnitId) -> Module -> GenModule UnitId
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Module
    mod) of
                    Just (GWIB { gwib_isBoot :: forall mod. GenWithIsBoot mod -> IsBootInterface
    gwib_isBoot = IsBootInterface
    is_boot }) ->
                      IsBootInterface -> MaybeErr MissingInterfaceError IsBootInterface
    forall err val. val -> MaybeErr err val
    Succeeded IsBootInterface
    is_boot
                    Maybe ModuleNameWithIsBoot
    Nothing ->
                      IsBootInterface -> MaybeErr MissingInterfaceError IsBootInterface
    forall err val. val -> MaybeErr err val
    Succeeded IsBootInterface
    NotBoot
                         -- The boot-ness of the requested interface,
                         -- based on the dependencies in directly-imported modules

    -----------------------------------------------------
    --      Loading type/class/value decls
    -- We pass the full Module name here, replete with
    -- its package info, so that we can build a Name for
    -- each binder with the right package info in it
    -- All subsequent lookups, including crucially lookups during typechecking
    -- the declaration itself, will find the fully-glorious Name
    --
    -- We handle ATs specially.  They are not main declarations, but also not
    -- implicit things (in particular, adding them to `implicitTyThings' would mess
    -- things up in the renaming/type checking of source programs).
    -----------------------------------------------------

    addDeclsToPTE :: PackageTypeEnv -> [(Name,TyThing)] -> PackageTypeEnv
    addDeclsToPTE :: TypeEnv -> [(Name, TyThing)] -> TypeEnv
    addDeclsToPTE TypeEnv
    pte [(Name, TyThing)]
    things = TypeEnv -> [(Name, TyThing)] -> TypeEnv
    forall a. NameEnv a -> [(Name, a)] -> NameEnv a
    extendNameEnvList TypeEnv
    pte [(Name, TyThing)]
    things

    {-
    *********************************************************
    *                                                      *
    \subsection{Reading an interface file}
    *                                                      *
    *********************************************************

    Note [Home module load error]
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    If the sought-for interface is in the current package (as determined
    by -package-name flag) then it jolly well should already be in the HPT
    because we process home-package modules in dependency order.  (Except
    in one-shot mode; see notes with hsc_HPT decl in GHC.Driver.Env).

    It is possible (though hard) to get this error through user behaviour.
      * Suppose package P (modules P1, P2) depends on package Q (modules Q1,
        Q2, with Q2 importing Q1)
      * We compile both packages.
      * Now we edit package Q so that it somehow depends on P
      * Now recompile Q with --make (without recompiling P).
      * Then Q1 imports, say, P1, which in turn depends on Q2. So Q2
        is a home-package module which is not yet in the HPT!  Disaster.

    This actually happened with P=base, Q=ghc-prim, via the AMP warnings.
    See #8320.
    -}

    findAndReadIface
      :: HscEnv
      -> SDoc            -- ^ Reason for loading the iface (used for tracing)
      -> InstalledModule -- ^ The unique identifier of the on-disk module we're looking for
      -> Module          -- ^ The *actual* module we're looking for.  We use
                         -- this to check the consistency of the requirements of the
                         -- module we read out.
      -> IsBootInterface -- ^ Looking for .hi-boot or .hi file
      -> IO (MaybeErr MissingInterfaceError (ModIface, FilePath))
    findAndReadIface :: HscEnv
    -> SDoc
    -> GenModule UnitId
    -> Module
    -> IsBootInterface
    -> IO (MaybeErr MissingInterfaceError (ModIface, String))
    findAndReadIface HscEnv
    hsc_env SDoc
    doc_str GenModule UnitId
    mod Module
    wanted_mod IsBootInterface
    hi_boot_file = do

      let profile :: Profile
    profile = DynFlags -> Profile
    targetProfile DynFlags
    dflags
          unit_state :: UnitState
    unit_state = HasDebugCallStack => HscEnv -> UnitState
    HscEnv -> UnitState
    hsc_units HscEnv
    hsc_env
          fc :: FinderCache
    fc         = HscEnv -> FinderCache
    hsc_FC HscEnv
    hsc_env
          name_cache :: NameCache
    name_cache = HscEnv -> NameCache
    hsc_NC HscEnv
    hsc_env
          mhome_unit :: Maybe HomeUnit
    mhome_unit  = HscEnv -> Maybe HomeUnit
    hsc_home_unit_maybe HscEnv
    hsc_env
          dflags :: DynFlags
    dflags     = HscEnv -> DynFlags
    hsc_dflags HscEnv
    hsc_env
          logger :: Logger
    logger     = HscEnv -> Logger
    hsc_logger HscEnv
    hsc_env
          hooks :: Hooks
    hooks      = HscEnv -> Hooks
    hsc_hooks HscEnv
    hsc_env
          other_fopts :: UnitEnvGraph FinderOpts
    other_fopts = DynFlags -> FinderOpts
    initFinderOpts (DynFlags -> FinderOpts)
    -> (HomeUnitEnv -> DynFlags) -> HomeUnitEnv -> FinderOpts
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . HomeUnitEnv -> DynFlags
    homeUnitEnv_dflags (HomeUnitEnv -> FinderOpts)
    -> HomeUnitGraph -> UnitEnvGraph FinderOpts
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> (HscEnv -> HomeUnitGraph
    hsc_HUG HscEnv
    hsc_env)

      Logger -> SDoc -> IO ()
    trace_if Logger
    logger ([SDoc] -> SDoc
    forall doc. IsLine doc => [doc] -> doc
    sep [[SDoc] -> SDoc
    forall doc. IsLine doc => [doc] -> doc
    hsep [String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "Reading",
                               if IsBootInterface
    hi_boot_file IsBootInterface -> IsBootInterface -> Bool
    forall a. Eq a => a -> a -> Bool
    == IsBootInterface
    IsBoot
                                 then String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "[boot]"
                                 else SDoc
    forall doc. IsOutput doc => doc
    Outputable.empty,
                               String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "interface for",
                               GenModule UnitId -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr GenModule UnitId
    mod SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <> SDoc
    forall doc. IsLine doc => doc
    semi],
                         Int -> SDoc -> SDoc
    nest Int
    4 (String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "reason:" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> SDoc
    doc_str)])

      -- Check for GHC.Prim, and return its static interface
      -- See Note [GHC.Prim] in primops.txt.pp.
      -- TODO: make this check a function
      if GenModule UnitId
    mod GenModule UnitId -> Module -> Bool
    `installedModuleEq` Module
    gHC_PRIM
          then do
              let iface :: ModIface
    iface = case Hooks -> Maybe ModIface
    ghcPrimIfaceHook Hooks
    hooks of
                           Maybe ModIface
    Nothing -> ModIface
    ghcPrimIface
                           Just ModIface
    h  -> ModIface
    h
              MaybeErr MissingInterfaceError (ModIface, String)
    -> IO (MaybeErr MissingInterfaceError (ModIface, String))
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ((ModIface, String)
    -> MaybeErr MissingInterfaceError (ModIface, String)
    forall err val. val -> MaybeErr err val
    Succeeded (ModIface
    iface, String
    "<built in interface for GHC.Prim>"))
          else do
              let fopts :: FinderOpts
    fopts = DynFlags -> FinderOpts
    initFinderOpts DynFlags
    dflags
              -- Look for the file
              mb_found <- IO InstalledFindResult -> IO InstalledFindResult
    forall a. IO a -> IO a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (FinderCache
    -> FinderOpts
    -> UnitEnvGraph FinderOpts
    -> UnitState
    -> Maybe HomeUnit
    -> GenModule UnitId
    -> IO InstalledFindResult
    findExactModule FinderCache
    fc FinderOpts
    fopts UnitEnvGraph FinderOpts
    other_fopts UnitState
    unit_state Maybe HomeUnit
    mhome_unit GenModule UnitId
    mod)
              case mb_found of
                  InstalledFound (IsBootInterface -> ModLocation -> ModLocation
    addBootSuffixLocn_maybe IsBootInterface
    hi_boot_file -> ModLocation
    loc) GenModule UnitId
    mod -> do
                      -- See Note [Home module load error]
                      case Maybe HomeUnit
    mhome_unit of
                        Just HomeUnit
    home_unit
                          | HomeUnit -> GenModule UnitId -> Bool
    forall u. GenHomeUnit u -> GenModule UnitId -> Bool
    isHomeInstalledModule HomeUnit
    home_unit GenModule UnitId
    mod
                          , Bool -> Bool
    not (GhcMode -> Bool
    isOneShot (DynFlags -> GhcMode
    ghcMode DynFlags
    dflags))
                          -> MaybeErr MissingInterfaceError (ModIface, String)
    -> IO (MaybeErr MissingInterfaceError (ModIface, String))
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (MissingInterfaceError
    -> MaybeErr MissingInterfaceError (ModIface, String)
    forall err val. err -> MaybeErr err val
    Failed (GenModule UnitId -> ModLocation -> MissingInterfaceError
    HomeModError GenModule UnitId
    mod ModLocation
    loc))
                        Maybe HomeUnit
    _ -> do
                            r <- Logger
    -> NameCache
    -> UnitState
    -> DynFlags
    -> Module
    -> String
    -> IO (MaybeErr ReadInterfaceError (ModIface, String))
    read_file Logger
    logger NameCache
    name_cache UnitState
    unit_state DynFlags
    dflags Module
    wanted_mod (ModLocation -> String
    ml_hi_file ModLocation
    loc)
                            case r of
                              Failed ReadInterfaceError
    err
                                -> MaybeErr MissingInterfaceError (ModIface, String)
    -> IO (MaybeErr MissingInterfaceError (ModIface, String))
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (MissingInterfaceError
    -> MaybeErr MissingInterfaceError (ModIface, String)
    forall err val. err -> MaybeErr err val
    Failed (MissingInterfaceError
     -> MaybeErr MissingInterfaceError (ModIface, String))
    -> MissingInterfaceError
    -> MaybeErr MissingInterfaceError (ModIface, String)
    forall a b. (a -> b) -> a -> b
    $ ReadInterfaceError -> MissingInterfaceError
    BadIfaceFile ReadInterfaceError
    err)
                              Succeeded (ModIface
    iface,String
    _fp)
                                -> do
                                    r2 <- Logger
    -> NameCache
    -> UnitState
    -> DynFlags
    -> Module
    -> ModIface
    -> ModLocation
    -> IO (MaybeErr MissingInterfaceError ())
    load_dynamic_too_maybe Logger
    logger NameCache
    name_cache UnitState
    unit_state
                                                             (DynFlags -> DynFlags
    setDynamicNow DynFlags
    dflags) Module
    wanted_mod
                                                             ModIface
    iface ModLocation
    loc
                                    case r2 of
                                      Failed MissingInterfaceError
    sdoc -> MaybeErr MissingInterfaceError (ModIface, String)
    -> IO (MaybeErr MissingInterfaceError (ModIface, String))
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (MissingInterfaceError
    -> MaybeErr MissingInterfaceError (ModIface, String)
    forall err val. err -> MaybeErr err val
    Failed MissingInterfaceError
    sdoc)
                                      Succeeded {} -> MaybeErr MissingInterfaceError (ModIface, String)
    -> IO (MaybeErr MissingInterfaceError (ModIface, String))
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (MaybeErr MissingInterfaceError (ModIface, String)
     -> IO (MaybeErr MissingInterfaceError (ModIface, String)))
    -> MaybeErr MissingInterfaceError (ModIface, String)
    -> IO (MaybeErr MissingInterfaceError (ModIface, String))
    forall a b. (a -> b) -> a -> b
    $ (ModIface, String)
    -> MaybeErr MissingInterfaceError (ModIface, String)
    forall err val. val -> MaybeErr err val
    Succeeded (ModIface
    iface,String
    _fp)
                  InstalledFindResult
    err -> do
                      Logger -> SDoc -> IO ()
    trace_if Logger
    logger (String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "...not found")
                      MaybeErr MissingInterfaceError (ModIface, String)
    -> IO (MaybeErr MissingInterfaceError (ModIface, String))
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (MaybeErr MissingInterfaceError (ModIface, String)
     -> IO (MaybeErr MissingInterfaceError (ModIface, String)))
    -> MaybeErr MissingInterfaceError (ModIface, String)
    -> IO (MaybeErr MissingInterfaceError (ModIface, String))
    forall a b. (a -> b) -> a -> b
    $ MissingInterfaceError
    -> MaybeErr MissingInterfaceError (ModIface, String)
    forall err val. err -> MaybeErr err val
    Failed (MissingInterfaceError
     -> MaybeErr MissingInterfaceError (ModIface, String))
    -> MissingInterfaceError
    -> MaybeErr MissingInterfaceError (ModIface, String)
    forall a b. (a -> b) -> a -> b
    $ UnitState
    -> Maybe HomeUnit
    -> Profile
    -> ModuleName
    -> InstalledFindResult
    -> MissingInterfaceError
    cannotFindInterface
                                          UnitState
    unit_state
                                          Maybe HomeUnit
    mhome_unit
                                          Profile
    profile
                                          (GenModule UnitId -> ModuleName
    forall unit. GenModule unit -> ModuleName
    moduleName GenModule UnitId
    mod)
                                          InstalledFindResult
    err

    -- | Check if we need to try the dynamic interface for -dynamic-too
    load_dynamic_too_maybe :: Logger -> NameCache -> UnitState -> DynFlags
                           -> Module -> ModIface -> ModLocation
                           -> IO (MaybeErr MissingInterfaceError ())
    load_dynamic_too_maybe :: Logger
    -> NameCache
    -> UnitState
    -> DynFlags
    -> Module
    -> ModIface
    -> ModLocation
    -> IO (MaybeErr MissingInterfaceError ())
    load_dynamic_too_maybe Logger
    logger NameCache
    name_cache UnitState
    unit_state DynFlags
    dflags Module
    wanted_mod ModIface
    iface ModLocation
    loc
      -- Indefinite interfaces are ALWAYS non-dynamic.
      | Bool -> Bool
    not (Module -> Bool
    moduleIsDefinite (ModIface -> Module
    forall (phase :: ModIfacePhase). ModIface_ phase -> Module
    mi_module ModIface
    iface)) = MaybeErr MissingInterfaceError ()
    -> IO (MaybeErr MissingInterfaceError ())
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (() -> MaybeErr MissingInterfaceError ()
    forall err val. val -> MaybeErr err val
    Succeeded ())
      | GeneralFlag -> DynFlags -> Bool
    gopt GeneralFlag
    Opt_BuildDynamicToo DynFlags
    dflags = Logger
    -> NameCache
    -> UnitState
    -> DynFlags
    -> Module
    -> ModIface
    -> ModLocation
    -> IO (MaybeErr MissingInterfaceError ())
    load_dynamic_too Logger
    logger NameCache
    name_cache UnitState
    unit_state DynFlags
    dflags Module
    wanted_mod ModIface
    iface ModLocation
    loc
      | Bool
    otherwise = MaybeErr MissingInterfaceError ()
    -> IO (MaybeErr MissingInterfaceError ())
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (() -> MaybeErr MissingInterfaceError ()
    forall err val. val -> MaybeErr err val
    Succeeded ())

    load_dynamic_too :: Logger -> NameCache -> UnitState -> DynFlags
                     -> Module -> ModIface -> ModLocation
                     -> IO (MaybeErr MissingInterfaceError ())
    load_dynamic_too :: Logger
    -> NameCache
    -> UnitState
    -> DynFlags
    -> Module
    -> ModIface
    -> ModLocation
    -> IO (MaybeErr MissingInterfaceError ())
    load_dynamic_too Logger
    logger NameCache
    name_cache UnitState
    unit_state DynFlags
    dflags Module
    wanted_mod ModIface
    iface ModLocation
    loc = do
      Logger
    -> NameCache
    -> UnitState
    -> DynFlags
    -> Module
    -> String
    -> IO (MaybeErr ReadInterfaceError (ModIface, String))
    read_file Logger
    logger NameCache
    name_cache UnitState
    unit_state DynFlags
    dflags Module
    wanted_mod (ModLocation -> String
    ml_dyn_hi_file ModLocation
    loc) IO (MaybeErr ReadInterfaceError (ModIface, String))
    -> (MaybeErr ReadInterfaceError (ModIface, String)
        -> IO (MaybeErr MissingInterfaceError ()))
    -> IO (MaybeErr MissingInterfaceError ())
    forall a b. IO a -> (a -> IO b) -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= \case
        Succeeded (ModIface
    dynIface, String
    _)
         | ModIfaceBackend -> Fingerprint
    mi_mod_hash (ModIface -> IfaceBackendExts 'ModIfaceFinal
    forall (phase :: ModIfacePhase).
    ModIface_ phase -> IfaceBackendExts phase
    mi_final_exts ModIface
    iface) Fingerprint -> Fingerprint -> Bool
    forall a. Eq a => a -> a -> Bool
    == ModIfaceBackend -> Fingerprint
    mi_mod_hash (ModIface -> IfaceBackendExts 'ModIfaceFinal
    forall (phase :: ModIfacePhase).
    ModIface_ phase -> IfaceBackendExts phase
    mi_final_exts ModIface
    dynIface)
         -> MaybeErr MissingInterfaceError ()
    -> IO (MaybeErr MissingInterfaceError ())
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (() -> MaybeErr MissingInterfaceError ()
    forall err val. val -> MaybeErr err val
    Succeeded ())
         | Bool
    otherwise ->
            do MaybeErr MissingInterfaceError ()
    -> IO (MaybeErr MissingInterfaceError ())
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (MaybeErr MissingInterfaceError ()
     -> IO (MaybeErr MissingInterfaceError ()))
    -> MaybeErr MissingInterfaceError ()
    -> IO (MaybeErr MissingInterfaceError ())
    forall a b. (a -> b) -> a -> b
    $ (MissingInterfaceError -> MaybeErr MissingInterfaceError ()
    forall err val. err -> MaybeErr err val
    Failed (MissingInterfaceError -> MaybeErr MissingInterfaceError ())
    -> MissingInterfaceError -> MaybeErr MissingInterfaceError ()
    forall a b. (a -> b) -> a -> b
    $ Module -> ModLocation -> MissingInterfaceError
    DynamicHashMismatchError Module
    wanted_mod ModLocation
    loc)
        Failed ReadInterfaceError
    err ->
            do MaybeErr MissingInterfaceError ()
    -> IO (MaybeErr MissingInterfaceError ())
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (MaybeErr MissingInterfaceError ()
     -> IO (MaybeErr MissingInterfaceError ()))
    -> MaybeErr MissingInterfaceError ()
    -> IO (MaybeErr MissingInterfaceError ())
    forall a b. (a -> b) -> a -> b
    $ (MissingInterfaceError -> MaybeErr MissingInterfaceError ()
    forall err val. err -> MaybeErr err val
    Failed (MissingInterfaceError -> MaybeErr MissingInterfaceError ())
    -> MissingInterfaceError -> MaybeErr MissingInterfaceError ()
    forall a b. (a -> b) -> a -> b
    $ Module -> ReadInterfaceError -> MissingInterfaceError
    FailedToLoadDynamicInterface Module
    wanted_mod ReadInterfaceError
    err)

              --((text "Failed to load dynamic interface file for" <+> ppr wanted_mod <> colon) $$ err))

    read_file :: Logger -> NameCache -> UnitState -> DynFlags
              -> Module -> FilePath
              -> IO (MaybeErr ReadInterfaceError (ModIface, FilePath))
    read_file :: Logger
    -> NameCache
    -> UnitState
    -> DynFlags
    -> Module
    -> String
    -> IO (MaybeErr ReadInterfaceError (ModIface, String))
    read_file Logger
    logger NameCache
    name_cache UnitState
    unit_state DynFlags
    dflags Module
    wanted_mod String
    file_path = do
      Logger -> SDoc -> IO ()
    trace_if Logger
    logger (String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "readIFace" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    file_path)

      -- Figure out what is recorded in mi_module.  If this is
      -- a fully definite interface, it'll match exactly, but
      -- if it's indefinite, the inside will be uninstantiated!
      let wanted_mod' :: Module
    wanted_mod' =
            case Module -> (GenModule UnitId, Maybe InstantiatedModule)
    getModuleInstantiation Module
    wanted_mod of
                (GenModule UnitId
    _, Maybe InstantiatedModule
    Nothing) -> Module
    wanted_mod
                (GenModule UnitId
    _, Just InstantiatedModule
    indef_mod) ->
                  UnitState -> InstantiatedModule -> Module
    instModuleToModule UnitState
    unit_state
                    (InstantiatedModule -> InstantiatedModule
    uninstantiateInstantiatedModule InstantiatedModule
    indef_mod)
      read_result <- DynFlags
    -> NameCache
    -> Module
    -> String
    -> IO (MaybeErr ReadInterfaceError ModIface)
    readIface DynFlags
    dflags NameCache
    name_cache Module
    wanted_mod' String
    file_path
      case read_result of
        Failed ReadInterfaceError
    err      -> MaybeErr ReadInterfaceError (ModIface, String)
    -> IO (MaybeErr ReadInterfaceError (ModIface, String))
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (ReadInterfaceError
    -> MaybeErr ReadInterfaceError (ModIface, String)
    forall err val. err -> MaybeErr err val
    Failed ReadInterfaceError
    err)
        Succeeded ModIface
    iface -> MaybeErr ReadInterfaceError (ModIface, String)
    -> IO (MaybeErr ReadInterfaceError (ModIface, String))
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ((ModIface, String)
    -> MaybeErr ReadInterfaceError (ModIface, String)
    forall err val. val -> MaybeErr err val
    Succeeded (ModIface
    iface, String
    file_path))
                    -- Don't forget to fill in the package name...

    -- | Write interface file
    writeIface :: Logger -> Profile -> FilePath -> ModIface -> IO ()
    writeIface :: Logger -> Profile -> String -> ModIface -> IO ()
    writeIface Logger
    logger Profile
    profile String
    hi_file_path ModIface
    new_iface
        = do Bool -> String -> IO ()
    createDirectoryIfMissing Bool
    True (String -> String
    takeDirectory String
    hi_file_path)
             let printer :: TraceBinIFace
    printer = (SDoc -> IO ()) -> TraceBinIFace
    TraceBinIFace (Logger -> Int -> SDoc -> IO ()
    debugTraceMsg Logger
    logger Int
    3)
             Profile -> TraceBinIFace -> String -> ModIface -> IO ()
    writeBinIface Profile
    profile TraceBinIFace
    printer String
    hi_file_path ModIface
    new_iface

    -- | @readIface@ tries just the one file.
    --
    -- Failed err    <=> file not found, or unreadable, or illegible
    -- Succeeded iface <=> successfully found and parsed
    readIface
      :: DynFlags
      -> NameCache
      -> Module
      -> FilePath
      -> IO (MaybeErr ReadInterfaceError ModIface)
    readIface :: DynFlags
    -> NameCache
    -> Module
    -> String
    -> IO (MaybeErr ReadInterfaceError ModIface)
    readIface DynFlags
    dflags NameCache
    name_cache Module
    wanted_mod String
    file_path = do
      let profile :: Profile
    profile = DynFlags -> Profile
    targetProfile DynFlags
    dflags
      res <- IO ModIface -> IO (Either SomeException ModIface)
    forall a. IO a -> IO (Either SomeException a)
    tryMost (IO ModIface -> IO (Either SomeException ModIface))
    -> IO ModIface -> IO (Either SomeException ModIface)
    forall a b. (a -> b) -> a -> b
    $ Profile
    -> NameCache
    -> CheckHiWay
    -> TraceBinIFace
    -> String
    -> IO ModIface
    readBinIface Profile
    profile NameCache
    name_cache CheckHiWay
    CheckHiWay TraceBinIFace
    QuietBinIFace String
    file_path
      case res of
        Right ModIface
    iface
            -- NB: This check is NOT just a sanity check, it is
            -- critical for correctness of recompilation checking
            -- (it lets us tell when -this-unit-id has changed.)
            | Module
    wanted_mod Module -> Module -> Bool
    forall a. Eq a => a -> a -> Bool
    == Module
    actual_mod
                            -> MaybeErr ReadInterfaceError ModIface
    -> IO (MaybeErr ReadInterfaceError ModIface)
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (ModIface -> MaybeErr ReadInterfaceError ModIface
    forall err val. val -> MaybeErr err val
    Succeeded ModIface
    iface)
            | Bool
    otherwise     -> MaybeErr ReadInterfaceError ModIface
    -> IO (MaybeErr ReadInterfaceError ModIface)
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (ReadInterfaceError -> MaybeErr ReadInterfaceError ModIface
    forall err val. err -> MaybeErr err val
    Failed ReadInterfaceError
    err)
            where
              actual_mod :: Module
    actual_mod = ModIface -> Module
    forall (phase :: ModIfacePhase). ModIface_ phase -> Module
    mi_module ModIface
    iface
              err :: ReadInterfaceError
    err = String -> Module -> Module -> ReadInterfaceError
    HiModuleNameMismatchWarn String
    file_path Module
    wanted_mod Module
    actual_mod

        Left SomeException
    exn    -> MaybeErr ReadInterfaceError ModIface
    -> IO (MaybeErr ReadInterfaceError ModIface)
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (ReadInterfaceError -> MaybeErr ReadInterfaceError ModIface
    forall err val. err -> MaybeErr err val
    Failed (String -> SomeException -> ReadInterfaceError
    ExceptionOccurred String
    file_path SomeException
    exn))

    {-
    *********************************************************
    *                                                       *
            Wired-in interface for GHC.Prim
    *                                                       *
    *********************************************************
    -}

    -- See Note [GHC.Prim] in primops.txt.pp.
    ghcPrimIface :: ModIface
    ghcPrimIface :: ModIface
    ghcPrimIface
      = ModIface
    empty_iface {
            mi_exports  = ghcPrimExports,
            mi_decls    = [],
            mi_fixities = fixities,
            mi_final_exts = (mi_final_exts empty_iface){ mi_fix_fn = mkIfaceFixCache fixities },
            mi_docs = Just ghcPrimDeclDocs -- See Note [GHC.Prim Docs]
            }
      where
        empty_iface :: ModIface
    empty_iface = Module -> ModIface
    emptyFullModIface Module
    gHC_PRIM

        -- The fixity listed here for @`seq`@ should match
        -- those in primops.txt.pp (from which Haddock docs are generated).
        fixities :: [(OccName, Fixity)]
    fixities = (Id -> OccName
    forall a. NamedThing a => a -> OccName
    getOccName Id
    seqId, SourceText -> Int -> FixityDirection -> Fixity
    Fixity SourceText
    NoSourceText Int
    0 FixityDirection
    InfixR)
                 (OccName, Fixity) -> [(OccName, Fixity)] -> [(OccName, Fixity)]
    forall a. a -> [a] -> [a]
    : (PrimOp -> Maybe (OccName, Fixity))
    -> [PrimOp] -> [(OccName, Fixity)]
    forall a b. (a -> Maybe b) -> [a] -> [b]
    mapMaybe PrimOp -> Maybe (OccName, Fixity)
    mkFixity [PrimOp]
    allThePrimOps
        mkFixity :: PrimOp -> Maybe (OccName, Fixity)
    mkFixity PrimOp
    op = (,) (PrimOp -> OccName
    primOpOcc PrimOp
    op) (Fixity -> (OccName, Fixity))
    -> Maybe Fixity -> Maybe (OccName, Fixity)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> PrimOp -> Maybe Fixity
    primOpFixity PrimOp
    op

    {-
    *********************************************************
    *                                                      *
    \subsection{Statistics}
    *                                                      *
    *********************************************************
    -}

    ifaceStats :: ExternalPackageState -> SDoc
    ifaceStats :: ExternalPackageState -> SDoc
    ifaceStats ExternalPackageState
    eps
      = [SDoc] -> SDoc
    forall doc. IsLine doc => [doc] -> doc
    hcat [String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "Renamer stats: ", SDoc
    msg]
      where
        stats :: EpsStats
    stats = ExternalPackageState -> EpsStats
    eps_stats ExternalPackageState
    eps
        msg :: SDoc
    msg = [SDoc] -> SDoc
    forall doc. IsDoc doc => [doc] -> doc
    vcat
            [Int -> SDoc
    forall doc. IsLine doc => Int -> doc
    int (EpsStats -> Int
    n_ifaces_in EpsStats
    stats) SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "interfaces read",
             [SDoc] -> SDoc
    forall doc. IsLine doc => [doc] -> doc
    hsep [ Int -> SDoc
    forall doc. IsLine doc => Int -> doc
    int (EpsStats -> Int
    n_decls_out EpsStats
    stats), String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "type/class/variable imported, out of",
                    Int -> SDoc
    forall doc. IsLine doc => Int -> doc
    int (EpsStats -> Int
    n_decls_in EpsStats
    stats), String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "read"],
             [SDoc] -> SDoc
    forall doc. IsLine doc => [doc] -> doc
    hsep [ Int -> SDoc
    forall doc. IsLine doc => Int -> doc
    int (EpsStats -> Int
    n_insts_out EpsStats
    stats), String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "instance decls imported, out of",
                    Int -> SDoc
    forall doc. IsLine doc => Int -> doc
    int (EpsStats -> Int
    n_insts_in EpsStats
    stats), String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "read"],
             [SDoc] -> SDoc
    forall doc. IsLine doc => [doc] -> doc
    hsep [ Int -> SDoc
    forall doc. IsLine doc => Int -> doc
    int (EpsStats -> Int
    n_rules_out EpsStats
    stats), String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "rule decls imported, out of",
                    Int -> SDoc
    forall doc. IsLine doc => Int -> doc
    int (EpsStats -> Int
    n_rules_in EpsStats
    stats), String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "read"]
            ]

    {-
    ************************************************************************
    *                                                                      *
                    Printing interfaces
    *                                                                      *
    ************************************************************************

    Note [Name qualification with --show-iface]
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    In order to disambiguate between identifiers from different modules, we qualify
    all names that don't originate in the current module. In order to keep visual
    noise as low as possible, we keep local names unqualified.

    For some background on this choice see #15269.
    -}

    -- | Read binary interface, and print it out
    showIface :: Logger -> DynFlags -> UnitState -> NameCache -> FilePath -> IO ()
    showIface :: Logger -> DynFlags -> UnitState -> NameCache -> String -> IO ()
    showIface Logger
    logger DynFlags
    dflags UnitState
    unit_state NameCache
    name_cache String
    filename = do
       let profile :: Profile
    profile = DynFlags -> Profile
    targetProfile DynFlags
    dflags
           printer :: SDoc -> IO ()
    printer = Logger -> MessageClass -> SrcSpan -> SDoc -> IO ()
    logMsg Logger
    logger MessageClass
    MCOutput SrcSpan
    noSrcSpan (SDoc -> IO ()) -> (SDoc -> SDoc) -> SDoc -> IO ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . PprStyle -> SDoc -> SDoc
    withPprStyle PprStyle
    defaultDumpStyle

       -- skip the hi way check; we don't want to worry about profiled vs.
       -- non-profiled interfaces, for example.
       iface <- Profile
    -> NameCache
    -> CheckHiWay
    -> TraceBinIFace
    -> String
    -> IO ModIface
    readBinIface Profile
    profile NameCache
    name_cache CheckHiWay
    IgnoreHiWay ((SDoc -> IO ()) -> TraceBinIFace
    TraceBinIFace SDoc -> IO ()
    printer) String
    filename

       let -- See Note [Name qualification with --show-iface]
           qualifyImportedNames Module
    mod OccName
    _
               | Module
    mod Module -> Module -> Bool
    forall a. Eq a => a -> a -> Bool
    == ModIface -> Module
    forall (phase :: ModIfacePhase). ModIface_ phase -> Module
    mi_module ModIface
    iface = QualifyName
    NameUnqual
               | Bool
    otherwise              = QualifyName
    NameNotInScope1
           name_ppr_ctx = (Module -> OccName -> QualifyName)
    -> (Module -> Bool)
    -> QueryQualifyPackage
    -> QueryPromotionTick
    -> NamePprCtx
    QueryQualify Module -> OccName -> QualifyName
    qualifyImportedNames
                                       Module -> Bool
    neverQualifyModules
                                       QueryQualifyPackage
    neverQualifyPackages
                                       QueryPromotionTick
    alwaysPrintPromTick
       logMsg logger MCDump noSrcSpan
          $ withPprStyle (mkDumpStyle name_ppr_ctx)
          $ pprModIface unit_state iface

    -- | Show a ModIface but don't display details; suitable for ModIfaces stored in
    -- the EPT.
    pprModIfaceSimple :: UnitState -> ModIface -> SDoc
    pprModIfaceSimple :: UnitState -> ModIface -> SDoc
    pprModIfaceSimple UnitState
    unit_state ModIface
    iface =
        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. IsDoc doc => doc -> doc -> doc
    $$ UnitState -> Dependencies -> SDoc
    pprDeps UnitState
    unit_state (ModIface -> Dependencies
    forall (phase :: ModIfacePhase). ModIface_ phase -> Dependencies
    mi_deps ModIface
    iface)
        SDoc -> SDoc -> SDoc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$ Int -> SDoc -> SDoc
    nest Int
    2 ([SDoc] -> SDoc
    forall doc. IsDoc doc => [doc] -> doc
    vcat ((IfaceExport -> SDoc) -> [IfaceExport] -> [SDoc]
    forall a b. (a -> b) -> [a] -> [b]
    map IfaceExport -> SDoc
    pprExport (ModIface -> [IfaceExport]
    forall (phase :: ModIfacePhase). ModIface_ phase -> [IfaceExport]
    mi_exports ModIface
    iface)))

    -- | Show a ModIface
    --
    -- The UnitState is used to pretty-print units
    pprModIface :: UnitState -> ModIface -> SDoc
    pprModIface :: UnitState -> ModIface -> SDoc
    pprModIface UnitState
    unit_state iface :: ModIface
    iface@ModIface{ mi_final_exts :: forall (phase :: ModIfacePhase).
    ModIface_ phase -> IfaceBackendExts phase
    mi_final_exts = IfaceBackendExts 'ModIfaceFinal
    exts }
     = [SDoc] -> SDoc
    forall doc. IsDoc doc => [doc] -> doc
    vcat [ String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "interface"
                    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
    <+> HscSource -> SDoc
    forall {doc}. IsLine doc => HscSource -> doc
    pp_hsc_src (ModIface -> HscSource
    forall (phase :: ModIfacePhase). ModIface_ phase -> HscSource
    mi_hsc_src ModIface
    iface)
                    SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> (if ModIfaceBackend -> Bool
    mi_orphan IfaceBackendExts 'ModIfaceFinal
    ModIfaceBackend
    exts then String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "[orphan module]" else SDoc
    forall doc. IsOutput doc => doc
    Outputable.empty)
                    SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> (if ModIfaceBackend -> Bool
    mi_finsts IfaceBackendExts 'ModIfaceFinal
    ModIfaceBackend
    exts then String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "[family instance module]" else SDoc
    forall doc. IsOutput doc => doc
    Outputable.empty)
                    SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> (if ModIface -> Bool
    forall (phase :: ModIfacePhase). ModIface_ phase -> Bool
    mi_hpc ModIface
    iface then String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "[hpc]" else SDoc
    forall doc. IsOutput doc => doc
    Outputable.empty)
                    SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Integer -> SDoc
    forall doc. IsLine doc => Integer -> doc
    integer Integer
    hiVersion
            , Int -> SDoc -> SDoc
    nest Int
    2 (String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "interface hash:" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Fingerprint -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr (ModIfaceBackend -> Fingerprint
    mi_iface_hash IfaceBackendExts 'ModIfaceFinal
    ModIfaceBackend
    exts))
            , Int -> SDoc -> SDoc
    nest Int
    2 (String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "ABI hash:" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Fingerprint -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr (ModIfaceBackend -> Fingerprint
    mi_mod_hash IfaceBackendExts 'ModIfaceFinal
    ModIfaceBackend
    exts))
            , Int -> SDoc -> SDoc
    nest Int
    2 (String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "export-list hash:" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Fingerprint -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr (ModIfaceBackend -> Fingerprint
    mi_exp_hash IfaceBackendExts 'ModIfaceFinal
    ModIfaceBackend
    exts))
            , Int -> SDoc -> SDoc
    nest Int
    2 (String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "orphan hash:" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Fingerprint -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr (ModIfaceBackend -> Fingerprint
    mi_orphan_hash IfaceBackendExts 'ModIfaceFinal
    ModIfaceBackend
    exts))
            , Int -> SDoc -> SDoc
    nest Int
    2 (String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "flag hash:" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Fingerprint -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr (ModIfaceBackend -> Fingerprint
    mi_flag_hash IfaceBackendExts 'ModIfaceFinal
    ModIfaceBackend
    exts))
            , Int -> SDoc -> SDoc
    nest Int
    2 (String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "opt_hash:" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Fingerprint -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr (ModIfaceBackend -> Fingerprint
    mi_opt_hash IfaceBackendExts 'ModIfaceFinal
    ModIfaceBackend
    exts))
            , Int -> SDoc -> SDoc
    nest Int
    2 (String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "hpc_hash:" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Fingerprint -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr (ModIfaceBackend -> Fingerprint
    mi_hpc_hash IfaceBackendExts 'ModIfaceFinal
    ModIfaceBackend
    exts))
            , Int -> SDoc -> SDoc
    nest Int
    2 (String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "plugin_hash:" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Fingerprint -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr (ModIfaceBackend -> Fingerprint
    mi_plugin_hash IfaceBackendExts 'ModIfaceFinal
    ModIfaceBackend
    exts))
            , Int -> SDoc -> SDoc
    nest Int
    2 (String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "src_hash:" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Fingerprint -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr (ModIface -> Fingerprint
    forall (phase :: ModIfacePhase). ModIface_ phase -> Fingerprint
    mi_src_hash ModIface
    iface))
            , Int -> SDoc -> SDoc
    nest Int
    2 (String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "sig of:" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Maybe Module -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr (ModIface -> Maybe Module
    forall (phase :: ModIfacePhase). ModIface_ phase -> Maybe Module
    mi_sig_of ModIface
    iface))
            , Int -> SDoc -> SDoc
    nest Int
    2 (String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "used TH splices:" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Bool -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr (ModIface -> Bool
    forall (phase :: ModIfacePhase). ModIface_ phase -> Bool
    mi_used_th ModIface
    iface))
            , Int -> SDoc -> SDoc
    nest Int
    2 (String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "where")
            , String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "exports:"
            , Int -> SDoc -> SDoc
    nest Int
    2 ([SDoc] -> SDoc
    forall doc. IsDoc doc => [doc] -> doc
    vcat ((IfaceExport -> SDoc) -> [IfaceExport] -> [SDoc]
    forall a b. (a -> b) -> [a] -> [b]
    map IfaceExport -> SDoc
    pprExport (ModIface -> [IfaceExport]
    forall (phase :: ModIfacePhase). ModIface_ phase -> [IfaceExport]
    mi_exports ModIface
    iface)))
            , UnitState -> Dependencies -> SDoc
    pprDeps UnitState
    unit_state (ModIface -> Dependencies
    forall (phase :: ModIfacePhase). ModIface_ phase -> Dependencies
    mi_deps ModIface
    iface)
            , [SDoc] -> SDoc
    forall doc. IsDoc doc => [doc] -> doc
    vcat ((Usage -> SDoc) -> [Usage] -> [SDoc]
    forall a b. (a -> b) -> [a] -> [b]
    map Usage -> SDoc
    pprUsage (ModIface -> [Usage]
    forall (phase :: ModIfacePhase). ModIface_ phase -> [Usage]
    mi_usages ModIface
    iface))
            , [SDoc] -> SDoc
    forall doc. IsDoc doc => [doc] -> doc
    vcat ((IfaceAnnotation -> SDoc) -> [IfaceAnnotation] -> [SDoc]
    forall a b. (a -> b) -> [a] -> [b]
    map IfaceAnnotation -> SDoc
    pprIfaceAnnotation (ModIface -> [IfaceAnnotation]
    forall (phase :: ModIfacePhase).
    ModIface_ phase -> [IfaceAnnotation]
    mi_anns ModIface
    iface))
            , [(OccName, Fixity)] -> SDoc
    pprFixities (ModIface -> [(OccName, Fixity)]
    forall (phase :: ModIfacePhase).
    ModIface_ phase -> [(OccName, Fixity)]
    mi_fixities ModIface
    iface)
            , [SDoc] -> SDoc
    forall doc. IsDoc doc => [doc] -> doc
    vcat [Fingerprint -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Fingerprint
    ver SDoc -> SDoc -> SDoc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$ Int -> SDoc -> SDoc
    nest Int
    2 (IfaceDecl -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr IfaceDecl
    decl) | (Fingerprint
    ver,IfaceDecl
    decl) <- ModIface -> [IfaceDeclExts 'ModIfaceFinal]
    forall (phase :: ModIfacePhase).
    ModIface_ phase -> [IfaceDeclExts phase]
    mi_decls ModIface
    iface]
            , case ModIface -> Maybe [IfaceBindingX IfaceMaybeRhs IfaceTopBndrInfo]
    forall (phase :: ModIfacePhase).
    ModIface_ phase
    -> Maybe [IfaceBindingX IfaceMaybeRhs IfaceTopBndrInfo]
    mi_extra_decls ModIface
    iface of
                Maybe [IfaceBindingX IfaceMaybeRhs IfaceTopBndrInfo]
    Nothing -> SDoc
    forall doc. IsOutput doc => doc
    empty
                Just [IfaceBindingX IfaceMaybeRhs IfaceTopBndrInfo]
    eds -> String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "extra decls:"
                              SDoc -> SDoc -> SDoc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$ Int -> SDoc -> SDoc
    nest Int
    2 ([SDoc] -> SDoc
    forall doc. IsDoc doc => [doc] -> doc
    vcat ([IfaceBindingX IfaceMaybeRhs IfaceTopBndrInfo -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr IfaceBindingX IfaceMaybeRhs IfaceTopBndrInfo
    bs | IfaceBindingX IfaceMaybeRhs IfaceTopBndrInfo
    bs <- [IfaceBindingX IfaceMaybeRhs IfaceTopBndrInfo]
    eds]))
            , [SDoc] -> SDoc
    forall doc. IsDoc doc => [doc] -> doc
    vcat ((IfaceClsInst -> SDoc) -> [IfaceClsInst] -> [SDoc]
    forall a b. (a -> b) -> [a] -> [b]
    map IfaceClsInst -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr (ModIface -> [IfaceClsInst]
    forall (phase :: ModIfacePhase). ModIface_ phase -> [IfaceClsInst]
    mi_insts ModIface
    iface))
            , [SDoc] -> SDoc
    forall doc. IsDoc doc => [doc] -> doc
    vcat ((IfaceFamInst -> SDoc) -> [IfaceFamInst] -> [SDoc]
    forall a b. (a -> b) -> [a] -> [b]
    map IfaceFamInst -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr (ModIface -> [IfaceFamInst]
    forall (phase :: ModIfacePhase). ModIface_ phase -> [IfaceFamInst]
    mi_fam_insts ModIface
    iface))
            , [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 (ModIface -> [IfaceRule]
    forall (phase :: ModIfacePhase). ModIface_ phase -> [IfaceRule]
    mi_rules ModIface
    iface))
            , IfaceWarnings -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr (ModIface -> IfaceWarnings
    forall (phase :: ModIfacePhase). ModIface_ phase -> IfaceWarnings
    mi_warns ModIface
    iface)
            , IfaceTrustInfo -> SDoc
    pprTrustInfo (ModIface -> IfaceTrustInfo
    forall (phase :: ModIfacePhase). ModIface_ phase -> IfaceTrustInfo
    mi_trust ModIface
    iface)
            , Bool -> SDoc
    pprTrustPkg (ModIface -> Bool
    forall (phase :: ModIfacePhase). ModIface_ phase -> Bool
    mi_trust_pkg ModIface
    iface)
            , [SDoc] -> SDoc
    forall doc. IsDoc doc => [doc] -> doc
    vcat ((IfaceCompleteMatch -> SDoc) -> [IfaceCompleteMatch] -> [SDoc]
    forall a b. (a -> b) -> [a] -> [b]
    map IfaceCompleteMatch -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr (ModIface -> [IfaceCompleteMatch]
    forall (phase :: ModIfacePhase).
    ModIface_ phase -> [IfaceCompleteMatch]
    mi_complete_matches ModIface
    iface))
            , String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "docs:" SDoc -> SDoc -> SDoc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$ Int -> SDoc -> SDoc
    nest Int
    2 (Maybe Docs -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr (ModIface -> Maybe Docs
    forall (phase :: ModIfacePhase). ModIface_ phase -> Maybe Docs
    mi_docs ModIface
    iface))
            , String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "extensible fields:" SDoc -> SDoc -> SDoc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$ Int -> SDoc -> SDoc
    nest Int
    2 (ExtensibleFields -> SDoc
    pprExtensibleFields (ModIface -> ExtensibleFields
    forall (phase :: ModIfacePhase).
    ModIface_ phase -> ExtensibleFields
    mi_ext_fields ModIface
    iface))
            ]
      where
        pp_hsc_src :: HscSource -> doc
    pp_hsc_src HscSource
    HsBootFile = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "[boot]"
        pp_hsc_src HscSource
    HsigFile   = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "[hsig]"
        pp_hsc_src HscSource
    HsSrcFile  = doc
    forall doc. IsOutput doc => doc
    Outputable.empty

    {-
    When printing export lists, we print like this:
            Avail   f               f
            AvailTC C [C, x, y]     C(x,y)
            AvailTC C [x, y]        C!(x,y)         -- Exporting x, y but not C
    -}

    pprExport :: IfaceExport -> SDoc
    pprExport :: IfaceExport -> SDoc
    pprExport (Avail Name
    n)      = Name -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Name
    n
    pprExport (AvailTC Name
    _ []) = SDoc
    forall doc. IsOutput doc => doc
    Outputable.empty
    pprExport avail :: IfaceExport
    avail@(AvailTC Name
    n [Name]
    _) =
        Name -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Name
    n SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <> SDoc
    mark SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <> [Name] -> SDoc
    forall {a}. Outputable a => [a] -> SDoc
    pp_export (IfaceExport -> [Name]
    availSubordinateNames IfaceExport
    avail)
      where
        mark :: SDoc
    mark | IfaceExport -> Bool
    availExportsDecl IfaceExport
    avail = SDoc
    forall doc. IsOutput doc => doc
    Outputable.empty
             | Bool
    otherwise              = SDoc
    forall doc. IsLine doc => doc
    vbar

        pp_export :: [a] -> SDoc
    pp_export []    = SDoc
    forall doc. IsOutput doc => doc
    Outputable.empty
        pp_export [a]
    names = SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc
    braces ([SDoc] -> SDoc
    forall doc. IsLine doc => [doc] -> doc
    hsep ((a -> SDoc) -> [a] -> [SDoc]
    forall a b. (a -> b) -> [a] -> [b]
    map a -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr [a]
    names))

    pprUsage :: Usage -> SDoc
    pprUsage :: Usage -> SDoc
    pprUsage usage :: Usage
    usage@UsagePackageModule{}
      = Usage -> (Usage -> Module) -> SDoc
    forall a. Outputable a => Usage -> (Usage -> a) -> SDoc
    pprUsageImport Usage
    usage Usage -> Module
    usg_mod
    pprUsage usage :: Usage
    usage@UsageHomeModule{}
      = Usage -> (Usage -> GenModule UnitId) -> SDoc
    forall a. Outputable a => Usage -> (Usage -> a) -> SDoc
    pprUsageImport Usage
    usage (\Usage
    u -> UnitId -> ModuleName -> GenModule UnitId
    forall u. u -> ModuleName -> GenModule u
    mkModule (Usage -> UnitId
    usg_unit_id Usage
    u) (Usage -> ModuleName
    usg_mod_name Usage
    u)) SDoc -> SDoc -> SDoc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$
        Int -> SDoc -> SDoc
    nest Int
    2 (
            SDoc -> (Fingerprint -> SDoc) -> Maybe Fingerprint -> SDoc
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe SDoc
    forall doc. IsOutput doc => doc
    Outputable.empty (\Fingerprint
    v -> String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "exports: " SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Fingerprint -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Fingerprint
    v) (Usage -> Maybe Fingerprint
    usg_exports Usage
    usage) SDoc -> SDoc -> SDoc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$
            [SDoc] -> SDoc
    forall doc. IsDoc doc => [doc] -> doc
    vcat [ OccName -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr OccName
    n SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Fingerprint -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Fingerprint
    v | (OccName
    n,Fingerprint
    v) <- Usage -> [(OccName, Fingerprint)]
    usg_entities Usage
    usage ]
            )
    pprUsage usage :: Usage
    usage@UsageFile{}
      = [SDoc] -> SDoc
    forall doc. IsLine doc => [doc] -> doc
    hsep [String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "addDependentFile",
              SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc
    doubleQuotes (FastString -> SDoc
    forall doc. IsLine doc => FastString -> doc
    ftext (Usage -> FastString
    usg_file_path Usage
    usage)),
              Fingerprint -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr (Usage -> Fingerprint
    usg_file_hash Usage
    usage)]
    pprUsage usage :: Usage
    usage@UsageMergedRequirement{}
      = [SDoc] -> SDoc
    forall doc. IsLine doc => [doc] -> doc
    hsep [String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "merged", Module -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr (Usage -> Module
    usg_mod Usage
    usage), Fingerprint -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr (Usage -> Fingerprint
    usg_mod_hash Usage
    usage)]
    pprUsage usage :: Usage
    usage@UsageHomeModuleInterface{}
      = [SDoc] -> SDoc
    forall doc. IsLine doc => [doc] -> doc
    hsep [String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "implementation", ModuleName -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr (Usage -> ModuleName
    usg_mod_name Usage
    usage)
                                   , UnitId -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr (Usage -> UnitId
    usg_unit_id Usage
    usage)
                                   , Fingerprint -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr (Usage -> Fingerprint
    usg_iface_hash Usage
    usage)]

    pprUsageImport :: Outputable a => Usage -> (Usage -> a) -> SDoc
    pprUsageImport :: forall a. Outputable a => Usage -> (Usage -> a) -> SDoc
    pprUsageImport Usage
    usage Usage -> a
    usg_mod'
      = [SDoc] -> SDoc
    forall doc. IsLine doc => [doc] -> doc
    hsep [String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "import", SDoc
    safe, a -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr (Usage -> a
    usg_mod' Usage
    usage),
                           Fingerprint -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr (Usage -> Fingerprint
    usg_mod_hash Usage
    usage)]
        where
            safe :: SDoc
    safe | Usage -> Bool
    usg_safe Usage
    usage = String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "safe"
                 | Bool
    otherwise      = String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    " -/ "

    pprFixities :: [(OccName, Fixity)] -> SDoc
    pprFixities :: [(OccName, Fixity)] -> SDoc
    pprFixities []    = SDoc
    forall doc. IsOutput doc => doc
    Outputable.empty
    pprFixities [(OccName, Fixity)]
    fixes = String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "fixities" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> ((OccName, Fixity) -> SDoc) -> [(OccName, Fixity)] -> SDoc
    forall a. (a -> SDoc) -> [a] -> SDoc
    pprWithCommas (OccName, Fixity) -> SDoc
    forall {a} {a}. (Outputable a, Outputable a) => (a, a) -> SDoc
    pprFix [(OccName, Fixity)]
    fixes
                      where
                        pprFix :: (a, a) -> SDoc
    pprFix (a
    occ,a
    fix) = a -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr a
    fix SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> a -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr a
    occ

    pprTrustInfo :: IfaceTrustInfo -> SDoc
    pprTrustInfo :: IfaceTrustInfo -> SDoc
    pprTrustInfo IfaceTrustInfo
    trust = String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "trusted:" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> IfaceTrustInfo -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr IfaceTrustInfo
    trust

    pprTrustPkg :: Bool -> SDoc
    pprTrustPkg :: Bool -> SDoc
    pprTrustPkg Bool
    tpkg = String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "require own pkg trusted:" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Bool -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Bool
    tpkg

    pprIfaceAnnotation :: IfaceAnnotation -> SDoc
    pprIfaceAnnotation :: IfaceAnnotation -> SDoc
    pprIfaceAnnotation (IfaceAnnotation { ifAnnotatedTarget :: IfaceAnnotation -> IfaceAnnTarget
    ifAnnotatedTarget = IfaceAnnTarget
    target, ifAnnotatedValue :: IfaceAnnotation -> AnnPayload
    ifAnnotatedValue = AnnPayload
    serialized })
      = IfaceAnnTarget -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr IfaceAnnTarget
    target SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "annotated by" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> AnnPayload -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr AnnPayload
    serialized

    pprExtensibleFields :: ExtensibleFields -> SDoc
    pprExtensibleFields :: ExtensibleFields -> SDoc
    pprExtensibleFields (ExtensibleFields Map String BinData
    fs) = [SDoc] -> SDoc
    forall doc. IsDoc doc => [doc] -> doc
    vcat ([SDoc] -> SDoc)
    -> ([(String, BinData)] -> [SDoc]) -> [(String, BinData)] -> SDoc
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ((String, BinData) -> SDoc) -> [(String, BinData)] -> [SDoc]
    forall a b. (a -> b) -> [a] -> [b]
    map (String, BinData) -> SDoc
    pprField ([(String, BinData)] -> SDoc) -> [(String, BinData)] -> SDoc
    forall a b. (a -> b) -> a -> b
    $ Map String BinData -> [(String, BinData)]
    forall k a. Map k a -> [(k, a)]
    toList Map String BinData
    fs
      where
        pprField :: (String, BinData) -> SDoc
    pprField (String
    name, (BinData Int
    size BinArray
    _data)) = String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    name SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "-" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Int -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Int
    size SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "bytes"

    -- | Reason for loading an interface file
    --
    -- Used to figure out whether we want to consider loading hi-boot files or not.
    data WhereFrom
      = ImportByUser IsBootInterface        -- Ordinary user import (perhaps {-# SOURCE #-})
      | ImportBySystem                      -- Non user import.
      | ImportByPlugin                      -- Importing a plugin.

    instance Outputable WhereFrom where
      ppr :: WhereFrom -> SDoc
    ppr (ImportByUser IsBootInterface
    IsBoot)                = String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "{- SOURCE -}"
      ppr (ImportByUser IsBootInterface
    NotBoot)               = SDoc
    forall doc. IsOutput doc => doc
    empty
      ppr WhereFrom
    ImportBySystem                       = String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "{- SYSTEM -}"
      ppr WhereFrom
    ImportByPlugin                       = String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "{- PLUGIN -}"