Hannes Siebenhandl pushed to branch wip/fendor/external-unit-db-cache at Glasgow Haskell Compiler / GHC

Commits:

21 changed files:

Changes:

  • compiler/GHC.hs
    ... ... @@ -671,7 +671,7 @@ setUnitDynFlagsNoCheck uid dflags1 = do
    671 671
       logger <- getLogger
    
    672 672
       hsc_env <- getSession
    
    673 673
     
    
    674
    -  (unit_state,home_unit,mconstants) <- liftIO $ initUnits logger dflags1 (hscEUDC hsc_env) (hsc_all_home_unit_ids hsc_env)
    
    674
    +  (unit_state,home_unit,mconstants) <- liftIO $ initUnits logger dflags1 (hsc_unit_index hsc_env) (hscEUDC hsc_env) (hsc_all_home_unit_ids hsc_env)
    
    675 675
       updated_dflags <- liftIO $ updatePlatformConstants dflags1 mconstants
    
    676 676
     
    
    677 677
       let upd hue =
    
    ... ... @@ -760,7 +760,7 @@ setProgramDynFlags_ invalidate_needed dflags = do
    760 760
                   old_hpt = homeUnitEnv_hpt homeUnitEnv
    
    761 761
                   home_units = HUG.allUnits (ue_home_unit_graph old_unit_env)
    
    762 762
     
    
    763
    -          (unit_state,home_unit,mconstants) <- liftIO $ initUnits logger dflags (ue_eud old_unit_env) home_units
    
    763
    +          (unit_state,home_unit,mconstants) <- liftIO $ initUnits logger dflags (ue_unit_index old_unit_env) (ue_eud old_unit_env) home_units
    
    764 764
     
    
    765 765
               updated_dflags <- liftIO $ updatePlatformConstants dflags0 mconstants
    
    766 766
               pure HomeUnitEnv
    
    ... ... @@ -779,6 +779,7 @@ setProgramDynFlags_ invalidate_needed dflags = do
    779 779
                   , ue_module_graph    = ue_module_graph old_unit_env
    
    780 780
                   , ue_eps             = ue_eps old_unit_env
    
    781 781
                   , ue_eud             = ue_eud old_unit_env
    
    782
    +              , ue_unit_index      = ue_unit_index old_unit_env
    
    782 783
                   }
    
    783 784
             modifySession $ \h -> hscSetFlags dflags1 h{ hsc_unit_env = unit_env }
    
    784 785
         else modifySession (hscSetFlags dflags0)
    
    ... ... @@ -837,6 +838,7 @@ setProgramHUG_ invalidate_needed new_hug0 = do
    837 838
                 , ue_eps             = ue_eps unit_env0
    
    838 839
                 , ue_module_graph    = ue_module_graph unit_env0
    
    839 840
                 , ue_eud             = ue_eud unit_env0
    
    841
    +            , ue_unit_index      = ue_unit_index unit_env0
    
    840 842
                 }
    
    841 843
           modifySession $ \h ->
    
    842 844
             -- hscSetFlags takes care of updating the logger as well.
    
    ... ... @@ -884,7 +886,7 @@ setProgramHUG_ invalidate_needed new_hug0 = do
    884 886
               old_hpt = homeUnitEnv_hpt homeUnitEnv
    
    885 887
               home_units = HUG.allUnits (ue_home_unit_graph unit_env)
    
    886 888
     
    
    887
    -      (unit_state,home_unit,mconstants) <- liftIO $ initUnits logger dflags (ue_eud unit_env) home_units
    
    889
    +      (unit_state,home_unit,mconstants) <- liftIO $ initUnits logger dflags (ue_unit_index unit_env) (ue_eud unit_env) home_units
    
    888 890
     
    
    889 891
           updated_dflags <- liftIO $ updatePlatformConstants dflags mconstants
    
    890 892
           pure HomeUnitEnv
    

  • compiler/GHC/Driver/Backpack.hs
    ... ... @@ -175,6 +175,8 @@ withBkpSession :: UnitId
    175 175
                    -> BkpM a
    
    176 176
     withBkpSession cid insts deps session_type do_this = do
    
    177 177
         dflags <- getDynFlags
    
    178
    +    env <- getSession
    
    179
    +    unitIndex <- liftIO $ hscUnitIndex env
    
    178 180
         let cid_fs = unitFS cid
    
    179 181
             is_primary = False
    
    180 182
             uid_str = unpackFS (mkInstantiatedUnitHash cid insts)
    
    ... ... @@ -194,8 +196,8 @@ withBkpSession cid insts deps session_type do_this = do
    194 196
                      | otherwise = sub_comp (key_base p)
    
    195 197
     
    
    196 198
             mk_temp_env hsc_env =
    
    197
    -          hscUpdateFlags (\dflags -> mk_temp_dflags (hsc_units hsc_env) dflags) hsc_env
    
    198
    -        mk_temp_dflags unit_state dflags = dflags
    
    199
    +          hscUpdateFlags (\dflags -> mk_temp_dflags unitIndex (hsc_units hsc_env) dflags) hsc_env
    
    200
    +        mk_temp_dflags unit_index unit_state dflags = dflags
    
    199 201
                 { backend = case session_type of
    
    200 202
                                 TcSession -> noBackend
    
    201 203
                                 _         -> backend dflags
    
    ... ... @@ -242,7 +244,7 @@ withBkpSession cid insts deps session_type do_this = do
    242 244
                 , importPaths = []
    
    243 245
                 -- Synthesize the flags
    
    244 246
                 , packageFlags = packageFlags dflags ++ map (\(uid0, rn) ->
    
    245
    -              let uid = unwireUnit unit_state
    
    247
    +              let uid = unwireUnit unit_index
    
    246 248
                             $ renameHoleUnit unit_state (listToUFM insts) uid0
    
    247 249
                   in ExposePackage
    
    248 250
                     (showSDoc dflags
    
    ... ... @@ -349,9 +351,9 @@ buildUnit session cid insts lunit = do
    349 351
                   | otherwise
    
    350 352
                   = [Nothing]
    
    351 353
             linkables <- liftIO $ catMaybes <$> concatHpt takeLinkables (hsc_HPT hsc_env)
    
    354
    +        unit_index <- liftIO $ hscUnitIndex hsc_env
    
    352 355
             let
    
    353 356
                 obj_files = concatMap linkableFiles linkables
    
    354
    -            state     = hsc_units hsc_env
    
    355 357
     
    
    356 358
                 compat_fs = unitIdFS cid
    
    357 359
                 compat_pn = PackageName compat_fs
    
    ... ... @@ -377,7 +379,7 @@ buildUnit session cid insts lunit = do
    377 379
                             -- really used for anything, so we leave it
    
    378 380
                             -- blank for now.
    
    379 381
                             TcSession -> []
    
    380
    -                        _ -> map (toUnitId . unwireUnit state)
    
    382
    +                        _ -> map (toUnitId . unwireUnit unit_index)
    
    381 383
                                     $ deps ++ [ moduleUnit mod
    
    382 384
                                               | (_, mod) <- insts
    
    383 385
                                               , not (isHoleModule mod) ],
    
    ... ... @@ -449,7 +451,7 @@ addUnit u = do
    449 451
               { packageDBFlags = packageDBFlags dflags0 ++ [PackageDB (PkgDbPath (unitDatabasePath newdb))]
    
    450 452
               }
    
    451 453
     
    
    452
    -    (unit_state,home_unit,mconstants) <- liftIO $ initUnits logger dflags1 eud (hsc_all_home_unit_ids hsc_env)
    
    454
    +    (unit_state,home_unit,mconstants) <- liftIO $ initUnits logger dflags1 (ue_unit_index old_unit_env) eud (hsc_all_home_unit_ids hsc_env)
    
    453 455
     
    
    454 456
     
    
    455 457
         -- update platform constants
    
    ... ... @@ -467,6 +469,7 @@ addUnit u = do
    467 469
               , ue_eps       = ue_eps old_unit_env
    
    468 470
               , ue_module_graph = ue_module_graph old_unit_env
    
    469 471
               , ue_eud       = ue_eud old_unit_env
    
    472
    +          , ue_unit_index = ue_unit_index old_unit_env
    
    470 473
               }
    
    471 474
         setSession $ hscSetFlags dflags $ hsc_env { hsc_unit_env = unit_env }
    
    472 475
     
    

  • compiler/GHC/Driver/Env.hs
    ... ... @@ -13,6 +13,8 @@ module GHC.Driver.Env
    13 13
        , hsc_HUE
    
    14 14
        , hsc_HUG
    
    15 15
        , hsc_all_home_unit_ids
    
    16
    +   , hscUnitIndex
    
    17
    +   , hsc_unit_index
    
    16 18
        , hscUpdateLoggerFlags
    
    17 19
        , hscUpdateHUG
    
    18 20
        , hscInsertHPT
    
    ... ... @@ -230,6 +232,12 @@ hscEUD = readExternalUnitDatabases . hscEUDC
    230 232
     hscEUDC :: HscEnv -> ExternalUnitDatabaseCache UnitId
    
    231 233
     hscEUDC hsc_env = ue_eud (hsc_unit_env hsc_env)
    
    232 234
     
    
    235
    +hscUnitIndex :: HscEnv -> IO UnitIndex
    
    236
    +hscUnitIndex hsc_env = readIORef $ ue_unit_index (hsc_unit_env hsc_env)
    
    237
    +
    
    238
    +hsc_unit_index :: HscEnv -> IORef UnitIndex
    
    239
    +hsc_unit_index hsc_env = ue_unit_index (hsc_unit_env hsc_env)
    
    240
    +
    
    233 241
     --------------------------------------------------------------------------------
    
    234 242
     -- * Queries on Transitive Closure
    
    235 243
     --------------------------------------------------------------------------------
    

  • compiler/GHC/Driver/Session/Units.hs
    ... ... @@ -131,7 +131,7 @@ initMulti unitArgsFiles lintDynFlagsAndSrcs = do
    131 131
       home_unit_graph <- forM initial_home_graph $ \homeUnitEnv -> do
    
    132 132
         let hue_flags = homeUnitEnv_dflags homeUnitEnv
    
    133 133
             dflags = homeUnitEnv_dflags homeUnitEnv
    
    134
    -    (unit_state,home_unit,mconstants) <- liftIO $ State.initUnits logger hue_flags (hscEUDC hsc_env) home_units
    
    134
    +    (unit_state,home_unit,mconstants) <- liftIO $ State.initUnits logger hue_flags (hsc_unit_index hsc_env) (hscEUDC hsc_env) home_units
    
    135 135
     
    
    136 136
         updated_dflags <- liftIO $ updatePlatformConstants dflags mconstants
    
    137 137
         emptyHpt <- liftIO $ emptyHomePackageTable
    

  • compiler/GHC/Types/Unique.hs
    ... ... @@ -126,8 +126,8 @@ Prefer `env_ut :: Char` and
    126 126
     -- for fast ordering and equality tests. You should generate these with
    
    127 127
     -- the functions from the 'UniqSupply' module
    
    128 128
     --
    
    129
    --- These are sometimes also referred to as \"keys\" in comments in GHC.
    
    130 129
     newtype Unique = MkUnique Word64
    
    130
    +-- These are sometimes also referred to as \"keys\" in comments in GHC.
    
    131 131
     
    
    132 132
     data UniqueTag
    
    133 133
       = AlphaTyVarTag
    

  • compiler/GHC/Unit/Env.hs
    ... ... @@ -131,6 +131,7 @@ import GHC.Types.Annotations
    131 131
     import GHC.Types.CompleteMatch
    
    132 132
     import GHC.Core.InstEnv
    
    133 133
     import GHC.Core.FamInstEnv
    
    134
    +import Data.IORef
    
    134 135
     
    
    135 136
     --------------------------------------------------------------------------------
    
    136 137
     -- The hard queries
    
    ... ... @@ -177,6 +178,8 @@ data UnitEnv = UnitEnv
    177 178
     
    
    178 179
         , ue_eud :: {-# UNPACK #-} !(ExternalUnitDatabaseCache UnitId)
    
    179 180
             -- TODO: @fendor Docs
    
    181
    +    , ue_unit_index :: {-# UNPACK #-} !(IORef UnitIndex)
    
    182
    +        -- TODO: @fendor Docs
    
    180 183
         }
    
    181 184
     
    
    182 185
     ueEPS :: UnitEnv -> IO ExternalPackageState
    
    ... ... @@ -186,6 +189,7 @@ initUnitEnv :: UnitId -> HomeUnitGraph -> GhcNameVersion -> Platform -> IO UnitE
    186 189
     initUnitEnv cur_unit hug namever platform = do
    
    187 190
       eps <- initExternalUnitCache
    
    188 191
       eud <- initExternalUnitDatabaseCache
    
    192
    +  unit_index <- newIORef (initUnitIndex)
    
    189 193
       return $ UnitEnv
    
    190 194
         { ue_eps             = eps
    
    191 195
         , ue_home_unit_graph = hug
    
    ... ... @@ -194,6 +198,7 @@ initUnitEnv cur_unit hug namever platform = do
    194 198
         , ue_platform        = platform
    
    195 199
         , ue_namever         = namever
    
    196 200
         , ue_eud             = eud
    
    201
    +    , ue_unit_index      = unit_index
    
    197 202
         }
    
    198 203
     
    
    199 204
     updateHug :: (HomeUnitGraph -> HomeUnitGraph) -> UnitEnv -> UnitEnv
    

  • compiler/GHC/Unit/External/Database.hs
    ... ... @@ -14,18 +14,59 @@ module GHC.Unit.External.Database (
    14 14
       lookupExternalUnitDatabases,
    
    15 15
       -- *
    
    16 16
       UnitDatabase (..),
    
    17
    +  -- *
    
    18
    +  mergeDatabases,
    
    19
    +  validateDatabase,
    
    20
    +  UnitPrecedenceMap,
    
    21
    +  sortByPreference,
    
    22
    +  compareByPreference,
    
    23
    +  -- *
    
    24
    +  UnitDbConfig(..),
    
    25
    +  readOrGetUnitDatabase,
    
    26
    +  readUnitDatabases,
    
    27
    +  readUnitDatabase,
    
    28
    +  getUnitDbRefs,
    
    29
    +  resolveUnitDatabase,
    
    30
    +  -- *
    
    31
    +  matchingStr,
    
    32
    +  matchingId,
    
    33
    +  matching,
    
    17 34
     ) where
    
    18 35
     
    
    19 36
     import GHC.Prelude
    
    20 37
     
    
    21
    -import GHC.Data.OsPath
    
    22
    -import GHC.Unit.Info
    
    23
    -import GHC.Utils.Outputable
    
    38
    +import GHC.Driver.DynFlags
    
    24 39
     
    
    25
    -import Data.IORef (IORef)
    
    40
    +import Control.Monad
    
    41
    +import Data.Char
    
    42
    +import Data.Graph (SCC (..), stronglyConnComp)
    
    43
    +import Data.IORef
    
    26 44
     import Data.IORef qualified as IORef
    
    27
    -import Data.Map.Strict
    
    45
    +import Data.List (partition, sortBy)
    
    46
    +import Data.Map.Strict (Map)
    
    28 47
     import Data.Map.Strict qualified as Map
    
    48
    +import Data.Ord
    
    49
    +import Data.Set (Set)
    
    50
    +import Data.Set qualified as Set
    
    51
    +import GHC.Data.Maybe
    
    52
    +import GHC.Data.OsPath (OsPath)
    
    53
    +import GHC.Data.OsPath qualified as OsPath
    
    54
    +import GHC.Data.ShortText qualified as ST
    
    55
    +import GHC.Platform.ArchOS
    
    56
    +import GHC.Types.Unique.Map
    
    57
    +import GHC.Unit.Database
    
    58
    +import GHC.Unit.External.Validate
    
    59
    +import GHC.Unit.Info
    
    60
    +import GHC.Unit.Types
    
    61
    +import GHC.Utils.Error
    
    62
    +import GHC.Utils.Exception
    
    63
    +import GHC.Utils.Logger
    
    64
    +import GHC.Utils.Misc
    
    65
    +import GHC.Utils.Outputable as Outputable
    
    66
    +import GHC.Utils.Panic
    
    67
    +import System.Directory
    
    68
    +import System.Environment (getEnv)
    
    69
    +import System.FilePath as FilePath
    
    29 70
     
    
    30 71
     -- ----------------------------------------------------------------------------
    
    31 72
     -- ExternalUnitDatabaseCache
    
    ... ... @@ -102,3 +143,422 @@ data UnitDatabase unit = UnitDatabase
    102 143
     
    
    103 144
     instance (Outputable u) => Outputable (UnitDatabase u) where
    
    104 145
       ppr (UnitDatabase fp _u) = text "DB:" <+> ppr fp
    
    146
    +
    
    147
    +-- ----------------------------------------------------------------------------
    
    148
    +--
    
    149
    +-- Merging databases
    
    150
    +--
    
    151
    +
    
    152
    +-- | For each unit, a mapping from uid -> i indicates that this
    
    153
    +-- unit was brought into GHC by the ith @-package-db@ flag on
    
    154
    +-- the command line.  We use this mapping to make sure we prefer
    
    155
    +-- units that were defined later on the command line, if there
    
    156
    +-- is an ambiguity.
    
    157
    +type UnitPrecedenceMap = UniqMap UnitId Int
    
    158
    +
    
    159
    +-- | Given a list of databases, merge them together, where
    
    160
    +-- units with the same unit id in later databases override
    
    161
    +-- earlier ones.  This does NOT check if the resulting database
    
    162
    +-- makes sense (that's done by 'validateDatabase').
    
    163
    +mergeDatabases :: Logger -> [UnitDatabase UnitId]
    
    164
    +               -> IO (UnitInfoMap, UnitPrecedenceMap)
    
    165
    +mergeDatabases logger = foldM merge (emptyUniqMap, emptyUniqMap) . zip [1..]
    
    166
    +  where
    
    167
    +    merge (pkg_map, prec_map) (i, UnitDatabase db_path db) = do
    
    168
    +      debugTraceMsg logger 2 $
    
    169
    +          text "loading package database" <+> ppr db_path
    
    170
    +      when (logVerbAtLeast logger 2) $
    
    171
    +        forM_ (Set.toList override_set) $ \pkg ->
    
    172
    +            debugTraceMsg logger 2 $
    
    173
    +                text "package" <+> ppr pkg <+>
    
    174
    +                text "overrides a previously defined package"
    
    175
    +      return (pkg_map', prec_map')
    
    176
    +     where
    
    177
    +      db_map = mk_pkg_map db
    
    178
    +      mk_pkg_map = listToUniqMap . map (\p -> (unitId p, p))
    
    179
    +
    
    180
    +      -- The set of UnitIds which appear in both db and pkgs.  These are the
    
    181
    +      -- ones that get overridden.  Compute this just to give some
    
    182
    +      -- helpful debug messages at -v2
    
    183
    +      override_set :: Set UnitId
    
    184
    +      override_set = Set.intersection (nonDetUniqMapToKeySet db_map)
    
    185
    +                                      (nonDetUniqMapToKeySet pkg_map)
    
    186
    +
    
    187
    +      -- Now merge the sets together (NB: in case of duplicate,
    
    188
    +      -- first argument preferred)
    
    189
    +      pkg_map' :: UnitInfoMap
    
    190
    +      pkg_map' = pkg_map `plusUniqMap` db_map
    
    191
    +
    
    192
    +      prec_map' :: UnitPrecedenceMap
    
    193
    +      prec_map' = prec_map `plusUniqMap` (mapUniqMap (const i) db_map)
    
    194
    +
    
    195
    +-- | Validates a database, removing unusable units from it
    
    196
    +-- (this includes removing units that the user has explicitly
    
    197
    +-- ignored.)  Our general strategy:
    
    198
    +--
    
    199
    +-- 1. Remove all broken units (dangling dependencies)
    
    200
    +-- 2. Remove all units that are cyclic
    
    201
    +-- 3. Apply ignore flags
    
    202
    +-- 4. Remove all units which have deps with mismatching ABIs
    
    203
    +--
    
    204
    +validateDatabase :: [IgnorePackageFlag] -> UnitInfoMap
    
    205
    +                 -> (UnitInfoMap, UnusableUnits, [SCC UnitInfo])
    
    206
    +validateDatabase flagsIgnored pkg_map1 =
    
    207
    +    (pkg_map5, unusable, sccs)
    
    208
    +  where
    
    209
    +    ignore_flags = reverse flagsIgnored -- (unitConfigFlagsIgnored cfg)
    
    210
    +
    
    211
    +    -- Compute the reverse dependency index
    
    212
    +    index = reverseDeps pkg_map1
    
    213
    +
    
    214
    +    -- Helper function
    
    215
    +    mk_unusable mk_err dep_matcher m uids =
    
    216
    +      listToUniqMap [ (unitId pkg, (pkg, mk_err (dep_matcher m pkg)))
    
    217
    +                    | pkg <- uids
    
    218
    +                    ]
    
    219
    +
    
    220
    +    -- Find broken units
    
    221
    +    directly_broken = filter (not . null . depsNotAvailable pkg_map1)
    
    222
    +                             (nonDetEltsUniqMap pkg_map1)
    
    223
    +    (pkg_map2, broken) = removeUnits (map unitId directly_broken) index pkg_map1
    
    224
    +    unusable_broken = mk_unusable BrokenDependencies depsNotAvailable pkg_map2 broken
    
    225
    +
    
    226
    +    -- Find recursive units
    
    227
    +    sccs = stronglyConnComp [ (pkg, unitId pkg, unitDepends pkg)
    
    228
    +                            | pkg <- nonDetEltsUniqMap pkg_map2 ]
    
    229
    +    getCyclicSCC (CyclicSCC vs) = map unitId vs
    
    230
    +    getCyclicSCC (AcyclicSCC _) = []
    
    231
    +    (pkg_map3, cyclic) = removeUnits (concatMap getCyclicSCC sccs) index pkg_map2
    
    232
    +    unusable_cyclic = mk_unusable CyclicDependencies depsNotAvailable pkg_map3 cyclic
    
    233
    +
    
    234
    +    -- Apply ignore flags
    
    235
    +    directly_ignored = ignoreUnits ignore_flags (nonDetEltsUniqMap pkg_map3)
    
    236
    +    (pkg_map4, ignored) = removeUnits (nonDetKeysUniqMap directly_ignored) index pkg_map3
    
    237
    +    unusable_ignored = mk_unusable IgnoredDependencies depsNotAvailable pkg_map4 ignored
    
    238
    +
    
    239
    +    -- Knock out units whose dependencies don't agree with ABI
    
    240
    +    -- (i.e., got invalidated due to shadowing)
    
    241
    +    directly_shadowed = filter (not . null . depsAbiMismatch pkg_map4)
    
    242
    +                               (nonDetEltsUniqMap pkg_map4)
    
    243
    +    (pkg_map5, shadowed) = removeUnits (map unitId directly_shadowed) index pkg_map4
    
    244
    +    unusable_shadowed = mk_unusable ShadowedDependencies depsAbiMismatch pkg_map5 shadowed
    
    245
    +
    
    246
    +    -- combine all unusables. The order is important for shadowing.
    
    247
    +    -- plusUniqMapList folds using plusUFM which is right biased (opposite of
    
    248
    +    -- Data.Map.union) so the head of the list should be the least preferred
    
    249
    +    unusable = plusUniqMapList [ unusable_shadowed
    
    250
    +                               , unusable_cyclic
    
    251
    +                               , unusable_broken
    
    252
    +                               , unusable_ignored
    
    253
    +                               , directly_ignored
    
    254
    +                               ]
    
    255
    +
    
    256
    +
    
    257
    +-- | This sorts a list of packages, putting "preferred" packages first.
    
    258
    +-- See 'compareByPreference' for the semantics of "preference".
    
    259
    +sortByPreference :: UnitPrecedenceMap -> [UnitInfo] -> [UnitInfo]
    
    260
    +sortByPreference prec_map = sortBy (flip (compareByPreference prec_map))
    
    261
    +
    
    262
    +-- | Returns 'GT' if @pkg@ should be preferred over @pkg'@ when picking
    
    263
    +-- which should be "active".  Here is the order of preference:
    
    264
    +--
    
    265
    +--      1. First, prefer the latest version
    
    266
    +--      2. If the versions are the same, prefer the package that
    
    267
    +--      came in the latest package database.
    
    268
    +--
    
    269
    +-- Pursuant to #12518, we could change this policy to, for example, remove
    
    270
    +-- the version preference, meaning that we would always prefer the units
    
    271
    +-- in later unit database.
    
    272
    +compareByPreference
    
    273
    +    :: UnitPrecedenceMap
    
    274
    +    -> UnitInfo
    
    275
    +    -> UnitInfo
    
    276
    +    -> Ordering
    
    277
    +compareByPreference prec_map pkg pkg'
    
    278
    +  = case comparing unitPackageVersion pkg pkg' of
    
    279
    +        GT -> GT
    
    280
    +        EQ | Just prec  <- lookupUniqMap prec_map (unitId pkg)
    
    281
    +           , Just prec' <- lookupUniqMap prec_map (unitId pkg')
    
    282
    +           -- Prefer the unit from the later DB flag (i.e., higher
    
    283
    +           -- precedence)
    
    284
    +           -> compare prec prec'
    
    285
    +           | otherwise
    
    286
    +           -> EQ
    
    287
    +        LT -> LT
    
    288
    +
    
    289
    +-- -----------------------------------------------------------------------------
    
    290
    +-- Reading the unit database(s)
    
    291
    +
    
    292
    +data UnitDbConfig = UnitDbConfig
    
    293
    +  { unitDbConfigFlagsDB :: [PackageDBFlag]
    
    294
    +  , unitDbConfigProgramName :: String
    
    295
    +  , unitDbConfigDBName :: FilePath
    
    296
    +  , unitDbConfigPlatformArchOS :: ArchOS
    
    297
    +  , unitDbConfigGlobalDB :: FilePath
    
    298
    +  , unitDbConfigGHCDir :: FilePath
    
    299
    +  , unitDbConfigDBCache :: ExternalUnitDatabaseCache UnitId
    
    300
    +  }
    
    301
    +
    
    302
    +readUnitDatabases :: Logger -> UnitDbConfig -> IO [UnitDatabase UnitId]
    
    303
    +readUnitDatabases logger cfg = do
    
    304
    +  conf_refs <- getUnitDbRefs cfg
    
    305
    +  confs     <- liftM catMaybes $ mapM (resolveUnitDatabase cfg) conf_refs
    
    306
    +  mapM (readOrGetUnitDatabase logger cfg) confs
    
    307
    +
    
    308
    +
    
    309
    +getUnitDbRefs :: UnitDbConfig -> IO [PkgDbRef]
    
    310
    +getUnitDbRefs cfg = do
    
    311
    +  let system_conf_refs = [UserPkgDb, GlobalPkgDb]
    
    312
    +
    
    313
    +  e_pkg_path <- tryIO (getEnv $ map toUpper (unitDbConfigProgramName cfg) ++ "_PACKAGE_PATH")
    
    314
    +  let base_conf_refs = case e_pkg_path of
    
    315
    +        Left _ -> system_conf_refs
    
    316
    +        Right path
    
    317
    +         | Just (xs, x) <- snocView path, isSearchPathSeparator x
    
    318
    +         -> map PkgDbPath (OsPath.splitSearchPath (OsPath.unsafeEncodeUtf xs)) ++ system_conf_refs
    
    319
    +         | otherwise
    
    320
    +         -> map PkgDbPath (OsPath.splitSearchPath (OsPath.unsafeEncodeUtf path))
    
    321
    +
    
    322
    +  -- Apply the package DB-related flags from the command line to get the
    
    323
    +  -- final list of package DBs.
    
    324
    +  --
    
    325
    +  -- Notes on ordering:
    
    326
    +  --  * The list of flags is reversed (later ones first)
    
    327
    +  --  * We work with the package DB list in "left shadows right" order
    
    328
    +  --  * and finally reverse it at the end, to get "right shadows left"
    
    329
    +  --
    
    330
    +  return $ reverse (foldr doFlag base_conf_refs (unitDbConfigFlagsDB cfg))
    
    331
    + where
    
    332
    +  doFlag (PackageDB p) dbs = p : dbs
    
    333
    +  doFlag NoUserPackageDB dbs = filter isNotUser dbs
    
    334
    +  doFlag NoGlobalPackageDB dbs = filter isNotGlobal dbs
    
    335
    +  doFlag ClearPackageDBs _ = []
    
    336
    +
    
    337
    +  isNotUser UserPkgDb = False
    
    338
    +  isNotUser _ = True
    
    339
    +
    
    340
    +  isNotGlobal GlobalPkgDb = False
    
    341
    +  isNotGlobal _ = True
    
    342
    +
    
    343
    +-- | Return the path of a package database from a 'PkgDbRef'. Return 'Nothing'
    
    344
    +-- when the user database filepath is expected but the latter doesn't exist.
    
    345
    +--
    
    346
    +-- NB: This logic is reimplemented in Cabal, so if you change it,
    
    347
    +-- make sure you update Cabal. (Or, better yet, dump it in the
    
    348
    +-- compiler info so Cabal can use the info.)
    
    349
    +resolveUnitDatabase :: UnitDbConfig -> PkgDbRef -> IO (Maybe OsPath)
    
    350
    +resolveUnitDatabase cfg GlobalPkgDb = return $ Just $ OsPath.unsafeEncodeUtf $ unitDbConfigGlobalDB cfg
    
    351
    +resolveUnitDatabase cfg UserPkgDb = runMaybeT $ do
    
    352
    +  dir <- versionedAppDir (unitDbConfigProgramName cfg) (unitDbConfigPlatformArchOS cfg)
    
    353
    +  let pkgconf = dir </> unitDbConfigDBName cfg
    
    354
    +  exist <- tryMaybeT $ doesDirectoryExist pkgconf
    
    355
    +  if exist then return (OsPath.unsafeEncodeUtf pkgconf) else mzero
    
    356
    +resolveUnitDatabase _ (PkgDbPath name) = return $ Just name
    
    357
    +
    
    358
    +-- | Get the cached 'UnitDatabase' or read the 'UnitDatabase' at the given location.
    
    359
    +readOrGetUnitDatabase :: Logger -> UnitDbConfig -> OsPath -> IO (UnitDatabase UnitId)
    
    360
    +readOrGetUnitDatabase logger cfg conf_file =
    
    361
    +  readExternalUnitDatabase (unitDbConfigDBCache cfg) conf_file >>= \ case
    
    362
    +    Nothing -> do
    
    363
    +      new_db <- readUnitDatabase logger cfg conf_file
    
    364
    +      cacheExternalUnitDatabase (unitDbConfigDBCache cfg) new_db
    
    365
    +      pure new_db
    
    366
    +    Just db ->
    
    367
    +      pure db
    
    368
    +
    
    369
    +-- | Read the 'UnitDatabase' at the given location.
    
    370
    +readUnitDatabase :: Logger -> UnitDbConfig -> OsPath -> IO (UnitDatabase UnitId)
    
    371
    +readUnitDatabase logger cfg conf_file = do
    
    372
    +  isdir <- OsPath.doesDirectoryExist conf_file
    
    373
    +
    
    374
    +  proto_pkg_configs <-
    
    375
    +    if isdir
    
    376
    +       then readDirStyleUnitInfo conf_file
    
    377
    +       else do
    
    378
    +            isfile <- OsPath.doesFileExist conf_file
    
    379
    +            if isfile
    
    380
    +               then do
    
    381
    +                 mpkgs <- tryReadOldFileStyleUnitInfo
    
    382
    +                 case mpkgs of
    
    383
    +                   Just pkgs -> return pkgs
    
    384
    +                   Nothing   -> throwGhcExceptionIO $ InstallationError $
    
    385
    +                      "ghc no longer supports single-file style package " ++
    
    386
    +                      "databases (" ++ show conf_file ++
    
    387
    +                      ") use 'ghc-pkg init' to create the database with " ++
    
    388
    +                      "the correct format."
    
    389
    +               else throwGhcExceptionIO $ InstallationError $
    
    390
    +                      "can't find a package database at " ++ show conf_file
    
    391
    +
    
    392
    +  let
    
    393
    +      -- Fix #16360: remove trailing slash from conf_file before calculating pkgroot
    
    394
    +      conf_file' = OsPath.dropTrailingPathSeparator conf_file
    
    395
    +      top_dir = OsPath.unsafeEncodeUtf (unitDbConfigGHCDir cfg)
    
    396
    +      pkgroot = OsPath.takeDirectory conf_file'
    
    397
    +      pkg_configs1 = map (mungeUnitInfo top_dir pkgroot . mapUnitInfo (\(UnitKey x) -> UnitId x) . mkUnitKeyInfo)
    
    398
    +                         proto_pkg_configs
    
    399
    +  --
    
    400
    +  pkg_configs2 <- traverse evaluateUnitInfo pkg_configs1
    
    401
    +  return $ pkg_configs2 `seqList` UnitDatabase conf_file' pkg_configs2
    
    402
    +  where
    
    403
    +    readDirStyleUnitInfo :: OsPath -> IO [DbUnitInfo]
    
    404
    +    readDirStyleUnitInfo conf_dir = do
    
    405
    +      let filename = conf_dir OsPath.</> (OsPath.unsafeEncodeUtf "package.cache")
    
    406
    +      cache_exists <- OsPath.doesFileExist filename
    
    407
    +      if cache_exists
    
    408
    +        then do
    
    409
    +          debugTraceMsg logger 2 $ text "Using binary package database:" <+> ppr filename
    
    410
    +          readPackageDbForGhc filename
    
    411
    +        else do
    
    412
    +          -- If there is no package.cache file, we check if the database is not
    
    413
    +          -- empty by inspecting if the directory contains any .conf file. If it
    
    414
    +          -- does, something is wrong and we fail. Otherwise we assume that the
    
    415
    +          -- database is empty.
    
    416
    +          debugTraceMsg logger 2 $ text "There is no package.cache in"
    
    417
    +                      <+> ppr conf_dir
    
    418
    +                       <> text ", checking if the database is empty"
    
    419
    +          db_empty <- all (not . OsPath.isSuffixOf (OsPath.unsafeEncodeUtf ".conf"))
    
    420
    +                   <$> OsPath.getDirectoryContents conf_dir
    
    421
    +          if db_empty
    
    422
    +            then do
    
    423
    +              debugTraceMsg logger 3 $ text "There are no .conf files in"
    
    424
    +                          <+> ppr conf_dir <> text ", treating"
    
    425
    +                          <+> text "package database as empty"
    
    426
    +              return []
    
    427
    +            else
    
    428
    +              throwGhcExceptionIO $ InstallationError $
    
    429
    +                "there is no package.cache in " ++ show conf_dir ++
    
    430
    +                " even though package database is not empty"
    
    431
    +
    
    432
    +
    
    433
    +    -- Single-file style package dbs have been deprecated for some time, but
    
    434
    +    -- it turns out that Cabal was using them in one place. So this is a
    
    435
    +    -- workaround to allow older Cabal versions to use this newer ghc.
    
    436
    +    -- We check if the file db contains just "[]" and if so, we look for a new
    
    437
    +    -- dir-style db in conf_file.d/, ie in a dir next to the given file.
    
    438
    +    -- We cannot just replace the file with a new dir style since Cabal still
    
    439
    +    -- assumes it's a file and tries to overwrite with 'writeFile'.
    
    440
    +    -- ghc-pkg also cooperates with this workaround.
    
    441
    +    tryReadOldFileStyleUnitInfo = do
    
    442
    +      content <- readFile (OsPath.unsafeDecodeUtf conf_file) `catchIO` \_ -> return ""
    
    443
    +      if take 2 content == "[]"
    
    444
    +        then do
    
    445
    +          let conf_dir = conf_file OsPath.<.> OsPath.unsafeEncodeUtf "d"
    
    446
    +          direxists <- OsPath.doesDirectoryExist conf_dir
    
    447
    +          if direxists
    
    448
    +             then do debugTraceMsg logger 2 (text "Ignoring old file-style db and trying:" <+> ppr conf_dir)
    
    449
    +                     liftM Just (readDirStyleUnitInfo conf_dir)
    
    450
    +             else return (Just []) -- ghc-pkg will create it when it's updated
    
    451
    +        else return Nothing
    
    452
    +
    
    453
    +mungeUnitInfo :: OsPath -> OsPath
    
    454
    +                   -> UnitInfo -> UnitInfo
    
    455
    +mungeUnitInfo top_dir pkgroot =
    
    456
    +    mungeBytecodeLibFields
    
    457
    +  . mungeLibDirFields
    
    458
    +  . mungeUnitInfoPaths (ST.pack (OsPath.unsafeDecodeUtf top_dir)) (ST.pack (OsPath.unsafeDecodeUtf pkgroot))
    
    459
    +
    
    460
    +mungeLibDirFields :: UnitInfo -> UnitInfo
    
    461
    +mungeLibDirFields pkg =
    
    462
    +    pkg {
    
    463
    +      unitLibraryDynDirs = case unitLibraryDynDirs pkg of
    
    464
    +         [] -> unitLibraryDirs pkg
    
    465
    +         ds -> ds
    
    466
    +      , unitLibraryDirsStatic = case unitLibraryDirsStatic pkg of
    
    467
    +         [] -> unitLibraryDirs pkg
    
    468
    +         ds -> ds
    
    469
    +    }
    
    470
    +
    
    471
    +-- | Default to using library-dirs if bytecode library dirs is not explicitly set.
    
    472
    +mungeBytecodeLibFields :: UnitInfo -> UnitInfo
    
    473
    +mungeBytecodeLibFields pkg =
    
    474
    +    pkg {
    
    475
    +      unitLibraryBytecodeDirs = case unitLibraryBytecodeDirs pkg of
    
    476
    +         [] -> unitLibraryDirs pkg
    
    477
    +         ds -> ds
    
    478
    +    }
    
    479
    +
    
    480
    +-- ----------------------------------------------------------------------------
    
    481
    +--
    
    482
    +-- Utilities on the database
    
    483
    +--
    
    484
    +
    
    485
    +-- | A reverse dependency index, mapping an 'UnitId' to
    
    486
    +-- the 'UnitId's which have a dependency on it.
    
    487
    +type RevIndex = UniqMap UnitId [UnitId]
    
    488
    +
    
    489
    +-- | Compute the reverse dependency index of a unit database.
    
    490
    +reverseDeps :: UnitInfoMap -> RevIndex
    
    491
    +reverseDeps db = nonDetFoldUniqMap go emptyUniqMap db
    
    492
    +  where
    
    493
    +    go :: (UnitId, UnitInfo) -> RevIndex -> RevIndex
    
    494
    +    go (_uid, pkg) r = foldl' (go' (unitId pkg)) r (unitDepends pkg)
    
    495
    +    go' from r to = addToUniqMap_C (++) r to [from]
    
    496
    +
    
    497
    +-- | Given a list of 'UnitId's to remove, a database,
    
    498
    +-- and a reverse dependency index (as computed by 'reverseDeps'),
    
    499
    +-- remove those units, plus any units which depend on them.
    
    500
    +-- Returns the pruned database, as well as a list of 'UnitInfo's
    
    501
    +-- that was removed.
    
    502
    +removeUnits :: [UnitId] -> RevIndex
    
    503
    +               -> UnitInfoMap
    
    504
    +               -> (UnitInfoMap, [UnitInfo])
    
    505
    +removeUnits uids index m = go uids (m,[])
    
    506
    +  where
    
    507
    +    go [] (m,pkgs) = (m,pkgs)
    
    508
    +    go (uid:uids) (m,pkgs)
    
    509
    +        | Just pkg <- lookupUniqMap m uid
    
    510
    +        = case lookupUniqMap index uid of
    
    511
    +            Nothing    -> go uids (delFromUniqMap m uid, pkg:pkgs)
    
    512
    +            Just rdeps -> go (rdeps ++ uids) (delFromUniqMap m uid, pkg:pkgs)
    
    513
    +        | otherwise
    
    514
    +        = go uids (m,pkgs)
    
    515
    +
    
    516
    +-- | Given a 'UnitInfo' from some 'UnitInfoMap', return all entries in 'depends'
    
    517
    +-- which correspond to units that do not exist in the index.
    
    518
    +depsNotAvailable :: UnitInfoMap
    
    519
    +                 -> UnitInfo
    
    520
    +                 -> [UnitId]
    
    521
    +depsNotAvailable pkg_map pkg = filter (not . (`elemUniqMap` pkg_map)) (unitDepends pkg)
    
    522
    +
    
    523
    +-- | Given a 'UnitInfo' from some 'UnitInfoMap' return all entries in
    
    524
    +-- 'unitAbiDepends' which correspond to units that do not exist, OR have
    
    525
    +-- mismatching ABIs.
    
    526
    +depsAbiMismatch :: UnitInfoMap
    
    527
    +                -> UnitInfo
    
    528
    +                -> [UnitId]
    
    529
    +depsAbiMismatch pkg_map pkg = map fst . filter (not . abiMatch) $ unitAbiDepends pkg
    
    530
    +  where
    
    531
    +    abiMatch (dep_uid, abi)
    
    532
    +        | Just dep_pkg <- lookupUniqMap pkg_map dep_uid
    
    533
    +        = unitAbiHash dep_pkg == abi
    
    534
    +        | otherwise
    
    535
    +        = False
    
    536
    +
    
    537
    +-- -----------------------------------------------------------------------------
    
    538
    +-- Ignore units
    
    539
    +
    
    540
    +ignoreUnits :: [IgnorePackageFlag] -> [UnitInfo] -> UnusableUnits
    
    541
    +ignoreUnits flags pkgs = listToUniqMap (concatMap doit flags)
    
    542
    +  where
    
    543
    +  doit (IgnorePackage str) =
    
    544
    +     case partition (matchingStr str) pkgs of
    
    545
    +         (ps, _) -> [ (unitId p, (p, IgnoredWithFlag))
    
    546
    +                    | p <- ps ]
    
    547
    +        -- missing unit is not an error for -ignore-package,
    
    548
    +        -- because a common usage is to -ignore-package P as
    
    549
    +        -- a preventative measure just in case P exists.
    
    550
    +
    
    551
    +-- A package named on the command line can either include the
    
    552
    +-- version, or just the name if it is unambiguous.
    
    553
    +matchingStr :: String -> UnitInfo -> Bool
    
    554
    +matchingStr str p
    
    555
    +        =  str == unitPackageIdString p
    
    556
    +        || str == unitPackageNameString p
    
    557
    +
    
    558
    +matchingId :: UnitId -> UnitInfo -> Bool
    
    559
    +matchingId uid p = uid == unitId p
    
    560
    +
    
    561
    +matching :: PackageArg -> UnitInfo -> Bool
    
    562
    +matching (PackageArg str) = matchingStr str
    
    563
    +matching (UnitIdArg (RealUnit (Definite uid))) = matchingId uid
    
    564
    +matching (UnitIdArg _)  = \_ -> False -- TODO: warn in this case

  • compiler/GHC/Unit/External/Index.hs
    1
    +module GHC.Unit.External.Index (
    
    2
    +  -- *
    
    3
    +  UnitIndex,
    
    4
    +  initUnitIndex,
    
    5
    +  wiringMap,
    
    6
    +  unwiringMap,
    
    7
    +  globalUnits,
    
    8
    +  setWireMap,
    
    9
    +  isWireMapEmpty,
    
    10
    +  addUnitInfoMap,
    
    11
    +
    
    12
    +  -- *
    
    13
    +  GlobalUnitInfoMap,
    
    14
    +  lookupGlobalUnitInfoMap,
    
    15
    +  mkGlobalUnitKey,
    
    16
    +
    
    17
    +  -- *
    
    18
    +  GlobalUnitKey,
    
    19
    +  globalUnitKeyFromUnitInfo,
    
    20
    +
    
    21
    +  -- *
    
    22
    +  updateWiredInUnits,
    
    23
    +  updateWiredInUnitsInUnitInfo,
    
    24
    +  upd_wired_in_mod,
    
    25
    +) where
    
    26
    +
    
    27
    +import GHC.Prelude
    
    28
    +
    
    29
    +import GHC.Data.ShortText qualified as ST
    
    30
    +import GHC.Types.Unique.Map
    
    31
    +import GHC.Unit.Database
    
    32
    +import GHC.Unit.External.Wired
    
    33
    +import GHC.Unit.Info
    
    34
    +import GHC.Unit.Types
    
    35
    +
    
    36
    +import Data.Map.Strict (Map)
    
    37
    +import Data.Map.Strict qualified as Map
    
    38
    +import GHC.Utils.Misc
    
    39
    +
    
    40
    +-- ----------------------------------------------------------------------------
    
    41
    +-- UnitIndex
    
    42
    +-- ----------------------------------------------------------------------------
    
    43
    +
    
    44
    +data UnitIndex = UnitIndex
    
    45
    +  { ui_wireMap :: !WiringMap
    
    46
    +    -- ^ A mapping from database unit keys to wired in unit ids.
    
    47
    +  , ui_unwireMap :: !UnwiringMap
    
    48
    +    -- ^ A mapping from wired in unit ids to unit keys from the database.
    
    49
    +  , ui_unitInfoMap :: !GlobalUnitInfoMap
    
    50
    +    -- ^ TODO @fendor: document
    
    51
    +  }
    
    52
    +
    
    53
    +wiringMap :: UnitIndex -> UnwiringMap
    
    54
    +wiringMap = ui_unwireMap
    
    55
    +
    
    56
    +unwiringMap :: UnitIndex -> WiringMap
    
    57
    +unwiringMap = ui_wireMap
    
    58
    +
    
    59
    +globalUnits :: UnitIndex -> GlobalUnitInfoMap
    
    60
    +globalUnits = ui_unitInfoMap
    
    61
    +
    
    62
    +initUnitIndex :: UnitIndex
    
    63
    +initUnitIndex = UnitIndex
    
    64
    +  { ui_wireMap = emptyUniqMap
    
    65
    +  , ui_unwireMap = emptyUniqMap
    
    66
    +  , ui_unitInfoMap = emptyUniqMap
    
    67
    +  }
    
    68
    +
    
    69
    +setWireMap :: WiringMap -> UnitIndex -> UnitIndex
    
    70
    +setWireMap wired_map unit_index =
    
    71
    +  unit_index
    
    72
    +    { ui_wireMap = wired_map
    
    73
    +    , ui_unwireMap = listToUniqMap [ (v,k) | (k,v) <- nonDetUniqMapToList wired_map ]
    
    74
    +    }
    
    75
    +
    
    76
    +isWireMapEmpty :: UnitIndex -> Bool
    
    77
    +isWireMapEmpty unit_index =
    
    78
    +  isNullUniqMap (ui_wireMap unit_index)
    
    79
    +
    
    80
    +addUnitInfoMap :: UnitInfoMap -> UnitIndex -> UnitIndex
    
    81
    +addUnitInfoMap unit_info_map unit_index =
    
    82
    +  unit_index
    
    83
    +    { ui_unitInfoMap = plusUniqMap_C Map.union globalMap (ui_unitInfoMap unit_index)
    
    84
    +    }
    
    85
    +  where
    
    86
    +    globalMap :: GlobalUnitInfoMap
    
    87
    +    globalMap = mkGlobalUnitInfoMap $ nonDetUniqMapToList unit_info_map
    
    88
    +
    
    89
    +-- ----------------------------------------------------------------------------
    
    90
    +-- GlobalUnitInfoMap
    
    91
    +-- ----------------------------------------------------------------------------
    
    92
    +
    
    93
    +type GlobalUnitInfoMap = UniqMap UnitId (Map ST.ShortText UnitInfo)
    
    94
    +
    
    95
    +lookupGlobalUnitInfoMap :: GlobalUnitKey -> GlobalUnitInfoMap -> Maybe UnitInfo
    
    96
    +lookupGlobalUnitInfoMap (GlobalUnitKey uid abiHash) globalMap =
    
    97
    +  case lookupUniqMap globalMap uid of
    
    98
    +    Nothing -> Nothing
    
    99
    +    Just sameUnitId -> Map.lookup abiHash sameUnitId
    
    100
    +
    
    101
    +mkGlobalUnitInfoMap :: [(UnitId, UnitInfo)] -> GlobalUnitInfoMap
    
    102
    +mkGlobalUnitInfoMap unitInfos =
    
    103
    +  listToUniqMap_C Map.union . map (\(uid, v) -> (uid, Map.singleton (unitAbiHash v) v)) $ unitInfos
    
    104
    +
    
    105
    +-- ----------------------------------------------------------------------------
    
    106
    +-- GlobalUnitKey
    
    107
    +-- ----------------------------------------------------------------------------
    
    108
    +
    
    109
    +data GlobalUnitKey =
    
    110
    +  GlobalUnitKey
    
    111
    +    !UnitId -- ^ Unit Id of the 'UnitInfo'
    
    112
    +    !ST.ShortText
    
    113
    +
    
    114
    +globalUnitKeyFromUnitInfo :: UnitInfo -> GlobalUnitKey
    
    115
    +globalUnitKeyFromUnitInfo ui = mkGlobalUnitKey (unitId ui) (unitAbiHash ui)
    
    116
    +
    
    117
    +mkGlobalUnitKey :: UnitId -> ST.ShortText -> GlobalUnitKey
    
    118
    +mkGlobalUnitKey = GlobalUnitKey
    
    119
    +
    
    120
    +-- -----------------------------------------------------------------------------
    
    121
    +-- Wired-in units
    
    122
    +--
    
    123
    +-- See Note [Wired-in units] in GHC.Unit.Types
    
    124
    +
    
    125
    +updateWiredInUnits :: WiringMap -> GlobalUnitInfoMap -> [UnitInfo] -> [Either UnitInfo UnitInfo]
    
    126
    +updateWiredInUnits wiredInMap knownInfos pkgs =
    
    127
    +  map (updateWiredInUnitsInUnitInfo wiredInMap knownInfos) pkgs
    
    128
    +
    
    129
    +updateWiredInUnitsInUnitInfo :: WiringMap -> GlobalUnitInfoMap -> UnitInfo -> Either UnitInfo UnitInfo
    
    130
    +updateWiredInUnitsInUnitInfo wiredInMap knownInfos pkg =
    
    131
    +  let
    
    132
    +    upd_wired_in_pkg wiredInUnitId pkg =
    
    133
    +      pkg { unitId         = wiredInUnitId
    
    134
    +          , unitInstanceOf = wiredInUnitId
    
    135
    +              -- every non instantiated unit is an instance of
    
    136
    +              -- itself (required by Backpack...)
    
    137
    +              --
    
    138
    +              -- See Note [About units] in GHC.Unit
    
    139
    +          }
    
    140
    +
    
    141
    +    upd_deps pkg = pkg {
    
    142
    +          unitDepends = map (upd_wired_in wiredInMap) (unitDepends pkg),
    
    143
    +          unitExposedModules
    
    144
    +            = map (\(k,v) -> (k, fmap (upd_wired_in_mod wiredInMap) v))
    
    145
    +                  (unitExposedModules pkg)
    
    146
    +        }
    
    147
    +  in
    
    148
    +    case lookupUniqMap wiredInMap (unitId pkg) of
    
    149
    +      Just wiredIn ->
    
    150
    +        case lookupGlobalUnitInfoMap (mkGlobalUnitKey wiredIn (unitAbiHash pkg)) knownInfos of
    
    151
    +          Just ui ->
    
    152
    +            Right ui
    
    153
    +          Nothing ->
    
    154
    +            let
    
    155
    +              updated_pkg = upd_deps $ upd_wired_in_pkg wiredIn pkg
    
    156
    +            in
    
    157
    +              Left $ seqUnitInfo updated_pkg updated_pkg
    
    158
    +      Nothing -> case lookupGlobalUnitInfoMap (globalUnitKeyFromUnitInfo pkg) knownInfos of
    
    159
    +        Just ui ->
    
    160
    +          Right ui
    
    161
    +        Nothing ->
    
    162
    +          let
    
    163
    +            updated_pkg = upd_deps pkg
    
    164
    +          in
    
    165
    +            Left $ seqUnitInfo updated_pkg updated_pkg
    
    166
    +
    
    167
    +-- Helper functions for rewiring Module and Unit.  These
    
    168
    +-- rewrite Units of modules in wired-in packages to the form known to the
    
    169
    +-- compiler, as described in Note [Wired-in units] in GHC.Unit.Types.
    
    170
    +--
    
    171
    +-- For instance, base-4.9.0.0 will be rewritten to just base, to match
    
    172
    +-- what appears in GHC.Builtin.Names.
    
    173
    +
    
    174
    +upd_wired_in_mod :: WiringMap -> Module -> Module
    
    175
    +upd_wired_in_mod wiredInMap (Module uid m) = Module (upd_wired_in_uid wiredInMap uid) m
    
    176
    +
    
    177
    +upd_wired_in_uid :: WiringMap -> Unit -> Unit
    
    178
    +upd_wired_in_uid wiredInMap u = case u of
    
    179
    +   HoleUnit -> HoleUnit
    
    180
    +   RealUnit (Definite uid) -> RealUnit (Definite (upd_wired_in wiredInMap uid))
    
    181
    +   VirtUnit indef_uid ->
    
    182
    +      VirtUnit $ mkInstantiatedUnit
    
    183
    +        (instUnitInstanceOf indef_uid)
    
    184
    +        (map (\(x,y) -> (x,upd_wired_in_mod wiredInMap y)) (instUnitInsts indef_uid))
    
    185
    +
    
    186
    +upd_wired_in :: WiringMap -> UnitId -> UnitId
    
    187
    +upd_wired_in wiredInMap key
    
    188
    +    | Just key' <- lookupUniqMap wiredInMap key = key'
    
    189
    +    | otherwise = key

  • compiler/GHC/Unit/External/ModuleOrigin.hs
    1
    +module GHC.Unit.External.ModuleOrigin (
    
    2
    +  ModuleOrigin(..),
    
    3
    +  fromExposedModules,
    
    4
    +  fromReexportedModules,
    
    5
    +  fromFlag,
    
    6
    +  originVisible,
    
    7
    +  originEmpty,
    
    8
    +) where
    
    9
    +
    
    10
    +import GHC.Prelude
    
    11
    +import GHC.Unit.External.Validate
    
    12
    +import GHC.Unit.Info
    
    13
    +import GHC.Utils.Outputable
    
    14
    +import GHC.Utils.Panic
    
    15
    +import qualified Data.Semigroup as Semigroup
    
    16
    +
    
    17
    +-- | Given a module name, there may be multiple ways it came into scope,
    
    18
    +-- possibly simultaneously.  This data type tracks all the possible ways
    
    19
    +-- it could have come into scope.  Warning: don't use the record functions,
    
    20
    +-- they're partial!
    
    21
    +data ModuleOrigin =
    
    22
    +    -- | Module is hidden, and thus never will be available for import.
    
    23
    +    -- (But maybe the user didn't realize), so we'll still keep track
    
    24
    +    -- of these modules.)
    
    25
    +    ModHidden
    
    26
    +
    
    27
    +    -- | Module is unavailable because the unit is unusable.
    
    28
    +  | ModUnusable !UnusableUnit
    
    29
    +
    
    30
    +    -- | Module is public, and could have come from some places.
    
    31
    +  | ModOrigin {
    
    32
    +        -- | @Just False@ means that this module is in
    
    33
    +        -- someone's @exported-modules@ list, but that package is hidden;
    
    34
    +        -- @Just True@ means that it is available; @Nothing@ means neither
    
    35
    +        -- applies.
    
    36
    +        fromOrigUnit :: Maybe Bool
    
    37
    +        -- | Is the module available from a reexport of an exposed package?
    
    38
    +        -- There could be multiple.
    
    39
    +      , fromExposedReexport :: [UnitInfo]
    
    40
    +        -- | Is the module available from a reexport of a hidden package?
    
    41
    +      , fromHiddenReexport :: [UnitInfo]
    
    42
    +        -- | Did the module export come from a package flag? (ToDo: track
    
    43
    +        -- more information.
    
    44
    +      , fromPackageFlag :: Bool
    
    45
    +      }
    
    46
    +
    
    47
    +instance Outputable ModuleOrigin where
    
    48
    +    ppr ModHidden = text "hidden module"
    
    49
    +    ppr (ModUnusable _) = text "unusable module"
    
    50
    +    ppr (ModOrigin e res rhs f) = sep (punctuate comma (
    
    51
    +        (case e of
    
    52
    +            Nothing -> []
    
    53
    +            Just False -> [text "hidden package"]
    
    54
    +            Just True -> [text "exposed package"]) ++
    
    55
    +        (if null res
    
    56
    +            then []
    
    57
    +            else [text "reexport by" <+>
    
    58
    +                    sep (map (ppr . mkUnit) res)]) ++
    
    59
    +        (if null rhs
    
    60
    +            then []
    
    61
    +            else [text "hidden reexport by" <+>
    
    62
    +                    sep (map (ppr . mkUnit) rhs)]) ++
    
    63
    +        (if f then [text "package flag"] else [])
    
    64
    +        ))
    
    65
    +
    
    66
    +-- | Smart constructor for a module which is in @exposed-modules@.  Takes
    
    67
    +-- as an argument whether or not the defining package is exposed.
    
    68
    +fromExposedModules :: Bool -> ModuleOrigin
    
    69
    +fromExposedModules e = ModOrigin (Just e) [] [] False
    
    70
    +
    
    71
    +-- | Smart constructor for a module which is in @reexported-modules@.  Takes
    
    72
    +-- as an argument whether or not the reexporting package is exposed, and
    
    73
    +-- also its 'UnitInfo'.
    
    74
    +fromReexportedModules :: Bool -> UnitInfo -> ModuleOrigin
    
    75
    +fromReexportedModules True pkg = ModOrigin Nothing [pkg] [] False
    
    76
    +fromReexportedModules False pkg = ModOrigin Nothing [] [pkg] False
    
    77
    +
    
    78
    +-- | Smart constructor for a module which was bound by a package flag.
    
    79
    +fromFlag :: ModuleOrigin
    
    80
    +fromFlag = ModOrigin Nothing [] [] True
    
    81
    +
    
    82
    +instance Semigroup ModuleOrigin where
    
    83
    +    x@(ModOrigin e res rhs f) <> y@(ModOrigin e' res' rhs' f') =
    
    84
    +        ModOrigin (g e e') (res ++ res') (rhs ++ rhs') (f || f')
    
    85
    +      where g (Just b) (Just b')
    
    86
    +                | b == b'   = Just b
    
    87
    +                | otherwise = pprPanic "ModOrigin: package both exposed/hidden" $
    
    88
    +                    text "x: " <> ppr x $$ text "y: " <> ppr y
    
    89
    +            g Nothing x = x
    
    90
    +            g x Nothing = x
    
    91
    +
    
    92
    +    x <> y = pprPanic "ModOrigin: module origin mismatch" $
    
    93
    +                 text "x: " <> ppr x $$ text "y: " <> ppr y
    
    94
    +
    
    95
    +instance Monoid ModuleOrigin where
    
    96
    +    mempty = ModOrigin Nothing [] [] False
    
    97
    +    mappend = (Semigroup.<>)
    
    98
    +
    
    99
    +-- | Is the name from the import actually visible? (i.e. does it cause
    
    100
    +-- ambiguity, or is it only relevant when we're making suggestions?)
    
    101
    +originVisible :: ModuleOrigin -> Bool
    
    102
    +originVisible ModHidden = False
    
    103
    +originVisible (ModUnusable _) = False
    
    104
    +originVisible (ModOrigin b res _ f) = b == Just True || not (null res) || f
    
    105
    +
    
    106
    +-- | Are there actually no providers for this module?  This will never occur
    
    107
    +-- except when we're filtering based on package imports.
    
    108
    +originEmpty :: ModuleOrigin -> Bool
    
    109
    +originEmpty (ModOrigin Nothing [] [] False) = True
    
    110
    +originEmpty _ = False

  • compiler/GHC/Unit/External/Providers.hs
    1
    +module GHC.Unit.External.Providers (
    
    2
    +  ModuleNameProvidersMap,
    
    3
    +  pprModuleMap,
    
    4
    +) where
    
    5
    +
    
    6
    +import GHC.Prelude
    
    7
    +
    
    8
    +import GHC.Types.Unique.Map
    
    9
    +import GHC.Unit.Module
    
    10
    +import GHC.Unit.External.ModuleOrigin
    
    11
    +import GHC.Utils.Error
    
    12
    +import GHC.Utils.Outputable
    
    13
    +
    
    14
    +-- | Map from 'ModuleName' to a set of module providers (i.e. a 'Module' and
    
    15
    +-- its 'ModuleOrigin').
    
    16
    +--
    
    17
    +-- NB: the set is in fact a 'Map Module ModuleOrigin', probably to keep only one
    
    18
    +-- origin for a given 'Module'
    
    19
    +
    
    20
    +type ModuleNameProvidersMap =
    
    21
    +    UniqMap ModuleName (UniqMap Module ModuleOrigin)
    
    22
    +
    
    23
    +-- | Show the mapping of modules to where they come from.
    
    24
    +pprModuleMap :: ModuleNameProvidersMap -> SDoc
    
    25
    +pprModuleMap mod_map =
    
    26
    +  vcat (map pprLine (nonDetUniqMapToList mod_map))
    
    27
    +    where
    
    28
    +      pprLine (m,e) = ppr m $$ nest 50 (vcat (map (pprEntry m) (nonDetUniqMapToList e)))
    
    29
    +      pprEntry :: Outputable a => ModuleName -> (Module, a) -> SDoc
    
    30
    +      pprEntry m (m',o)
    
    31
    +        | m == moduleName m' = ppr (moduleUnit m') <+> parens (ppr o)
    
    32
    +        | otherwise = ppr m' <+> parens (ppr o)

  • compiler/GHC/Unit/External/Validate.hs
    1
    +module GHC.Unit.External.Validate (
    
    2
    +  UnusableUnits,
    
    3
    +  reportUnusable,
    
    4
    +
    
    5
    +  UnusableUnit(..),
    
    6
    +
    
    7
    +  UnusableUnitReason(..),
    
    8
    +  pprReason,
    
    9
    +) where
    
    10
    +
    
    11
    +import GHC.Prelude
    
    12
    +
    
    13
    +import GHC.Unit.Types
    
    14
    +import GHC.Types.Unique.Map
    
    15
    +import GHC.Unit.Info
    
    16
    +import GHC.Utils.Outputable
    
    17
    +import GHC.Utils.Logger
    
    18
    +import Control.Monad
    
    19
    +import GHC.Utils.Error
    
    20
    +
    
    21
    +type UnusableUnits = UniqMap UnitId (UnitInfo, UnusableUnitReason)
    
    22
    +
    
    23
    +-- | A unusable unit module origin
    
    24
    +data UnusableUnit = UnusableUnit
    
    25
    +  { uuUnit        :: !Unit               -- ^ Unusable unit
    
    26
    +  , uuReason      :: !UnusableUnitReason -- ^ Reason
    
    27
    +  , uuIsReexport  :: !Bool               -- ^ Is the "module" a reexport?
    
    28
    +  }
    
    29
    +
    
    30
    +-- | The reason why a unit is unusable.
    
    31
    +data UnusableUnitReason
    
    32
    +  = -- | We ignored it explicitly using @-ignore-package@.
    
    33
    +    IgnoredWithFlag
    
    34
    +    -- | This unit transitively depends on a unit that was never present
    
    35
    +    -- in any of the provided databases.
    
    36
    +  | BrokenDependencies   [UnitId]
    
    37
    +    -- | This unit transitively depends on a unit involved in a cycle.
    
    38
    +    -- Note that the list of 'UnitId' reports the direct dependencies
    
    39
    +    -- of this unit that (transitively) depended on the cycle, and not
    
    40
    +    -- the actual cycle itself (which we report separately at high verbosity.)
    
    41
    +  | CyclicDependencies   [UnitId]
    
    42
    +    -- | This unit transitively depends on a unit which was ignored.
    
    43
    +  | IgnoredDependencies  [UnitId]
    
    44
    +    -- | This unit transitively depends on a unit which was
    
    45
    +    -- shadowed by an ABI-incompatible unit.
    
    46
    +  | ShadowedDependencies [UnitId]
    
    47
    +
    
    48
    +instance Outputable UnusableUnitReason where
    
    49
    +    ppr IgnoredWithFlag = text "[ignored with flag]"
    
    50
    +    ppr (BrokenDependencies uids)   = brackets (text "broken" <+> ppr uids)
    
    51
    +    ppr (CyclicDependencies uids)   = brackets (text "cyclic" <+> ppr uids)
    
    52
    +    ppr (IgnoredDependencies uids)  = brackets (text "ignored" <+> ppr uids)
    
    53
    +    ppr (ShadowedDependencies uids) = brackets (text "shadowed" <+> ppr uids)
    
    54
    +
    
    55
    +pprReason :: SDoc -> UnusableUnitReason -> SDoc
    
    56
    +pprReason pref reason = case reason of
    
    57
    +  IgnoredWithFlag ->
    
    58
    +      pref <+> text "ignored due to an -ignore-package flag"
    
    59
    +  BrokenDependencies deps ->
    
    60
    +      pref <+> text "unusable due to missing dependencies:" $$
    
    61
    +        nest 2 (hsep (map ppr deps))
    
    62
    +  CyclicDependencies deps ->
    
    63
    +      pref <+> text "unusable due to cyclic dependencies:" $$
    
    64
    +        nest 2 (hsep (map ppr deps))
    
    65
    +  IgnoredDependencies deps ->
    
    66
    +      pref <+> text ("unusable because the -ignore-package flag was used to " ++
    
    67
    +                     "ignore at least one of its dependencies:") $$
    
    68
    +        nest 2 (hsep (map ppr deps))
    
    69
    +  ShadowedDependencies deps ->
    
    70
    +      pref <+> text "unusable due to shadowed dependencies:" $$
    
    71
    +        nest 2 (hsep (map ppr deps))
    
    72
    +
    
    73
    +reportUnusable :: Logger -> UnusableUnits -> IO ()
    
    74
    +reportUnusable logger pkgs = when (logVerbAtLeast logger 2) $ mapM_ report (nonDetUniqMapToList pkgs)
    
    75
    +  where
    
    76
    +    report (ipid, (_, reason)) =
    
    77
    +       debugTraceMsg logger 2 $
    
    78
    +         pprReason
    
    79
    +           (text "package" <+> ppr ipid <+> text "is") reason

  • compiler/GHC/Unit/External/Visibility.hs
    1
    +module GHC.Unit.External.Visibility (
    
    2
    +  VisibilityMap,
    
    3
    +  UnitVisibility(..),
    
    4
    +) where
    
    5
    +
    
    6
    +import GHC.Prelude
    
    7
    +
    
    8
    +import GHC.Data.FastString
    
    9
    +import GHC.Driver.DynFlags
    
    10
    +import GHC.Types.Unique.Map
    
    11
    +import GHC.Unit.Module
    
    12
    +import GHC.Utils.Outputable as Outputable
    
    13
    +
    
    14
    +import Control.Applicative
    
    15
    +import Data.Monoid (First (..))
    
    16
    +import Data.Semigroup qualified as Semigroup
    
    17
    +import Data.Set (Set)
    
    18
    +import Data.Set qualified as Set
    
    19
    +
    
    20
    +-- | 'UniqFM' map from 'Unit' to a 'UnitVisibility'.
    
    21
    +type VisibilityMap = UniqMap Unit UnitVisibility
    
    22
    +
    
    23
    +-- | 'UnitVisibility' records the various aspects of visibility of a particular
    
    24
    +-- 'Unit'.
    
    25
    +data UnitVisibility = UnitVisibility
    
    26
    +    { uv_expose_all :: Bool
    
    27
    +      --  ^ Should all modules in exposed-modules should be dumped into scope?
    
    28
    +    , uv_renamings :: [(ModuleName, ModuleName)]
    
    29
    +      -- ^ Any custom renamings that should bring extra 'ModuleName's into
    
    30
    +      -- scope.
    
    31
    +    , uv_package_name :: First FastString
    
    32
    +      -- ^ The package name associated with the 'Unit'.  This is used
    
    33
    +      -- to implement legacy behavior where @-package foo-0.1@ implicitly
    
    34
    +      -- hides any packages named @foo@
    
    35
    +    , uv_requirements :: UniqMap ModuleName (Set InstantiatedModule)
    
    36
    +      -- ^ The signatures which are contributed to the requirements context
    
    37
    +      -- from this unit ID.
    
    38
    +    , uv_explicit :: Maybe PackageArg
    
    39
    +      -- ^ Whether or not this unit was explicitly brought into scope,
    
    40
    +      -- as opposed to implicitly via the 'exposed' fields in the
    
    41
    +      -- package database (when @-hide-all-packages@ is not passed.)
    
    42
    +    }
    
    43
    +
    
    44
    +instance Outputable UnitVisibility where
    
    45
    +    ppr (UnitVisibility {
    
    46
    +        uv_expose_all = b,
    
    47
    +        uv_renamings = rns,
    
    48
    +        uv_package_name = First mb_pn,
    
    49
    +        uv_requirements = reqs,
    
    50
    +        uv_explicit = explicit
    
    51
    +    }) = ppr (b, rns, mb_pn, reqs, explicit)
    
    52
    +
    
    53
    +instance Semigroup UnitVisibility where
    
    54
    +    uv1 <> uv2
    
    55
    +        = UnitVisibility
    
    56
    +          { uv_expose_all = uv_expose_all uv1 || uv_expose_all uv2
    
    57
    +          , uv_renamings = uv_renamings uv1 ++ uv_renamings uv2
    
    58
    +          , uv_package_name = mappend (uv_package_name uv1) (uv_package_name uv2)
    
    59
    +          , uv_requirements = plusUniqMap_C Set.union (uv_requirements uv2) (uv_requirements uv1)
    
    60
    +          , uv_explicit = uv_explicit uv1 <|> uv_explicit uv2
    
    61
    +          }
    
    62
    +
    
    63
    +instance Monoid UnitVisibility where
    
    64
    +    mempty = UnitVisibility
    
    65
    +             { uv_expose_all = False
    
    66
    +             , uv_renamings = []
    
    67
    +             , uv_package_name = First Nothing
    
    68
    +             , uv_requirements = emptyUniqMap
    
    69
    +             , uv_explicit = Nothing
    
    70
    +             }
    
    71
    +    mappend = (Semigroup.<>)
    
    72
    +

  • compiler/GHC/Unit/External/Wired.hs
    1
    +module GHC.Unit.External.Wired (
    
    2
    +  WiringMap,
    
    3
    +  UnwiringMap,
    
    4
    +  findWiredInUnits,
    
    5
    +) where
    
    6
    +import GHC.Types.Unique.Map
    
    7
    +import GHC.Unit.Types
    
    8
    +
    
    9
    +import GHC.Prelude
    
    10
    +
    
    11
    +import GHC.Driver.DynFlags
    
    12
    +
    
    13
    +import GHC.Platform
    
    14
    +import GHC.Platform.Ways
    
    15
    +
    
    16
    +import GHC.Unit.Database
    
    17
    +import GHC.Unit.Info
    
    18
    +import GHC.Unit.Ppr
    
    19
    +import GHC.Unit.Types
    
    20
    +import GHC.Unit.Module
    
    21
    +import GHC.Unit.Home
    
    22
    +
    
    23
    +import GHC.Types.Unique.FM
    
    24
    +import GHC.Types.Unique.DFM
    
    25
    +import GHC.Types.Unique.DSet
    
    26
    +import GHC.Types.Unique.Map
    
    27
    +import GHC.Types.Unique
    
    28
    +import GHC.Types.PkgQual
    
    29
    +
    
    30
    +import GHC.Utils.Misc
    
    31
    +import GHC.Utils.Panic
    
    32
    +import GHC.Utils.Outputable as Outputable
    
    33
    +import GHC.Data.Maybe
    
    34
    +
    
    35
    +import System.Environment ( getEnv )
    
    36
    +import GHC.Data.FastString
    
    37
    +import GHC.Data.OsPath ( OsPath )
    
    38
    +import qualified GHC.Data.OsPath as OsPath
    
    39
    +import qualified GHC.Data.ShortText as ST
    
    40
    +import GHC.Utils.Logger
    
    41
    +import GHC.Utils.Error
    
    42
    +import GHC.Utils.Exception
    
    43
    +
    
    44
    +import System.Directory
    
    45
    +import System.FilePath as FilePath
    
    46
    +import Control.Monad
    
    47
    +import Data.Containers.ListUtils (nubOrd)
    
    48
    +import Data.Graph (stronglyConnComp, SCC(..))
    
    49
    +import Data.Char ( toUpper )
    
    50
    +import Data.List ( intersperse, partition, sortBy, sortOn, sort )
    
    51
    +import Data.Set (Set)
    
    52
    +import Data.Monoid (First(..))
    
    53
    +import qualified Data.Semigroup as Semigroup
    
    54
    +import qualified Data.Set as Set
    
    55
    +import Control.Applicative
    
    56
    +import GHC.Unit.External.Database
    
    57
    +import Data.IORef
    
    58
    +import Data.Either (partitionEithers)
    
    59
    +import Data.Map.Strict (Map)
    
    60
    +import qualified Data.Map.Strict as Map
    
    61
    +import GHC.Unit.External.Visibility
    
    62
    +
    
    63
    +type WiringMap =
    
    64
    +  UniqMap UnitId UnitId
    
    65
    +
    
    66
    +type UnwiringMap =
    
    67
    +  UniqMap UnitId UnitId
    
    68
    +
    
    69
    +-- -----------------------------------------------------------------------------
    
    70
    +-- Wired-in units
    
    71
    +--
    
    72
    +-- See Note [Wired-in units] in GHC.Unit.Types
    
    73
    +
    
    74
    +findWiredInUnits
    
    75
    +   :: Logger
    
    76
    +   -> UnitPrecedenceMap
    
    77
    +   -> [UnitInfo]           -- database
    
    78
    +   -> VisibilityMap             -- info on what units are visible
    
    79
    +                                -- for wired in selection
    
    80
    +   -> IO WiringMap   -- map from unit id to wired identity
    
    81
    +findWiredInUnits logger prec_map pkgs vis_map = do
    
    82
    +  -- Now we must find our wired-in units, and rename them to
    
    83
    +  -- their canonical names (eg. base-1.0 ==> base), as described
    
    84
    +  -- in Note [Wired-in units] in GHC.Unit.Types
    
    85
    +  let
    
    86
    +        matches :: UnitInfo -> UnitId -> Bool
    
    87
    +        pc `matches` pid = unitPackageName pc == PackageName (unitIdFS pid)
    
    88
    +
    
    89
    +        -- find which package corresponds to each wired-in package
    
    90
    +        -- delete any other packages with the same name
    
    91
    +        -- update the package and any dependencies to point to the new
    
    92
    +        -- one.
    
    93
    +        --
    
    94
    +        -- When choosing which package to map to a wired-in package
    
    95
    +        -- name, we try to pick the latest version of exposed packages.
    
    96
    +        -- However, if there are no exposed wired in packages available
    
    97
    +        -- (e.g. -hide-all-packages was used), we can't bail: we *have*
    
    98
    +        -- to assign a package for the wired-in package: so we try again
    
    99
    +        -- with hidden packages included to (and pick the latest
    
    100
    +        -- version).
    
    101
    +        --
    
    102
    +        -- You can also override the default choice by using -ignore-package:
    
    103
    +        -- this works even when there is no exposed wired in package
    
    104
    +        -- available.
    
    105
    +        --
    
    106
    +        findWiredInUnit :: [UnitInfo] -> UnitId -> IO (Maybe (UnitId, UnitInfo))
    
    107
    +        findWiredInUnit pkgs wired_pkg = firstJustsM [try all_exposed_ps, try all_ps, notfound]
    
    108
    +          where
    
    109
    +                all_ps = [ p | p <- pkgs, p `matches` wired_pkg ]
    
    110
    +                all_exposed_ps = [ p | p <- all_ps, (mkUnit p) `elemUniqMap` vis_map ]
    
    111
    +
    
    112
    +                try ps = case sortByPreference prec_map ps of
    
    113
    +                    p:_ -> Just <$> pick p
    
    114
    +                    _ -> pure Nothing
    
    115
    +
    
    116
    +                notfound = do
    
    117
    +                          debugTraceMsg logger 2 $
    
    118
    +                            text "wired-in package "
    
    119
    +                                 <> ftext (unitIdFS wired_pkg)
    
    120
    +                                 <> text " not found."
    
    121
    +                          return Nothing
    
    122
    +                pick :: UnitInfo -> IO (UnitId, UnitInfo)
    
    123
    +                pick pkg = do
    
    124
    +                        debugTraceMsg logger 2 $
    
    125
    +                            text "wired-in package "
    
    126
    +                                 <> ftext (unitIdFS wired_pkg)
    
    127
    +                                 <> text " mapped to "
    
    128
    +                                 <> ppr (unitId pkg)
    
    129
    +                        return (wired_pkg, pkg)
    
    130
    +
    
    131
    +
    
    132
    +  mb_wired_in_pkgs <- mapM (findWiredInUnit pkgs) wiredInUnitIds
    
    133
    +  let
    
    134
    +        wired_in_pkgs = catMaybes mb_wired_in_pkgs
    
    135
    +
    
    136
    +        wiredInMap :: UniqMap UnitId UnitId
    
    137
    +        wiredInMap = listToUniqMap
    
    138
    +          [ (unitId realUnitInfo, wiredInUnitId)
    
    139
    +          | (wiredInUnitId, realUnitInfo) <- wired_in_pkgs
    
    140
    +          , not (unitIsIndefinite realUnitInfo)
    
    141
    +          ]
    
    142
    +
    
    143
    +  return wiredInMap

  • compiler/GHC/Unit/Info.hs
    ... ... @@ -5,11 +5,14 @@ module GHC.Unit.Info
    5 5
        ( GenericUnitInfo (..)
    
    6 6
        , GenUnitInfo
    
    7 7
        , UnitInfo
    
    8
    +   , UnitInfoMap
    
    8 9
        , UnitKey (..)
    
    9 10
        , UnitKeyInfo
    
    10 11
        , mkUnitKeyInfo
    
    11 12
        , mapUnitInfo
    
    12 13
        , mkUnitPprInfo
    
    14
    +   , evaluateUnitInfo
    
    15
    +   , seqUnitInfo
    
    13 16
     
    
    14 17
        , mkUnit
    
    15 18
     
    
    ... ... @@ -53,6 +56,8 @@ import Data.Containers.ListUtils (nubOrd)
    53 56
     import Data.Version
    
    54 57
     import Data.Bifunctor
    
    55 58
     import Data.List (isPrefixOf, stripPrefix)
    
    59
    +import GHC.Types.Unique.Map
    
    60
    +import Control.Exception (evaluate)
    
    56 61
     
    
    57 62
     
    
    58 63
     -- | Information about an installed unit
    
    ... ... @@ -73,6 +78,9 @@ type UnitKeyInfo = GenUnitInfo UnitKey
    73 78
     -- UnitId)
    
    74 79
     type UnitInfo    = GenUnitInfo UnitId
    
    75 80
     
    
    81
    +-- TODO @fendor
    
    82
    +type UnitInfoMap = UniqMap UnitId UnitInfo
    
    83
    +
    
    76 84
     -- | Convert a DbUnitInfo (read from a package database) into `UnitKeyInfo`
    
    77 85
     mkUnitKeyInfo :: DbUnitInfo -> UnitKeyInfo
    
    78 86
     mkUnitKeyInfo = mapGenericUnitInfo
    
    ... ... @@ -250,3 +258,21 @@ unitHsLibs namever ways0 p = map (mkDynName . addSuffix . ST.unpack) (unitLibrar
    250 258
     
    
    251 259
             expandTag t | null t = ""
    
    252 260
                         | otherwise = '_':t
    
    261
    +
    
    262
    +evaluateUnitInfo :: UnitInfo -> IO UnitInfo
    
    263
    +evaluateUnitInfo ui = evaluate (seqUnitInfo ui ui)
    
    264
    +
    
    265
    +seqUnitInfo :: UnitInfo -> b -> b
    
    266
    +seqUnitInfo ui b =
    
    267
    +  unitImportDirs ui `seqList`
    
    268
    +  unitIncludeDirs ui `seqList`
    
    269
    +  unitLibraryDirs ui `seqList`
    
    270
    +  unitLibraryBytecodeDirs ui `seqList`
    
    271
    +  unitExtDepFrameworkDirs ui `seq`
    
    272
    +  unitHaddockInterfaces ui `seq`
    
    273
    +  unitHaddockHTMLs ui `seqList`
    
    274
    +  unitLibraryDynDirs ui `seqList`
    
    275
    +  unitLibraryDirsStatic ui `seqList`
    
    276
    +  unitDepends ui `seqList`
    
    277
    +  unitExposedModules ui `seqList`
    
    278
    +  b

  • compiler/GHC/Unit/State.hs
    ... ... @@ -5,7 +5,7 @@
    5 5
     module GHC.Unit.State (
    
    6 6
             module GHC.Unit.Info,
    
    7 7
     
    
    8
    -        UnitIndex(..),
    
    8
    +        UnitIndex,
    
    9 9
             initUnitIndex,
    
    10 10
             setWireMap,
    
    11 11
             isWireMapEmpty,
    
    ... ... @@ -26,7 +26,6 @@ module GHC.Unit.State (
    26 26
             listUnitInfo,
    
    27 27
     
    
    28 28
             -- * Querying the package config
    
    29
    -        UnitInfoMap,
    
    30 29
             lookupUnit,
    
    31 30
             lookupUnit',
    
    32 31
             unsafeLookupUnit,
    
    ... ... @@ -96,6 +95,14 @@ import GHC.Unit.Types
    96 95
     import GHC.Unit.Module
    
    97 96
     import GHC.Unit.Home
    
    98 97
     
    
    98
    +import GHC.Unit.External.Database
    
    99
    +import GHC.Unit.External.Index
    
    100
    +import GHC.Unit.External.Wired
    
    101
    +import GHC.Unit.External.Visibility
    
    102
    +import GHC.Unit.External.Validate
    
    103
    +import GHC.Unit.External.ModuleOrigin
    
    104
    +import GHC.Unit.External.Providers
    
    105
    +
    
    99 106
     import GHC.Types.Unique.FM
    
    100 107
     import GHC.Types.Unique.DFM
    
    101 108
     import GHC.Types.Unique.DSet
    
    ... ... @@ -108,28 +115,19 @@ import GHC.Utils.Panic
    108 115
     import GHC.Utils.Outputable as Outputable
    
    109 116
     import GHC.Data.Maybe
    
    110 117
     
    
    111
    -import System.Environment ( getEnv )
    
    112 118
     import GHC.Data.FastString
    
    113
    -import GHC.Data.OsPath ( OsPath )
    
    114 119
     import qualified GHC.Data.OsPath as OsPath
    
    115 120
     import qualified GHC.Data.ShortText as ST
    
    116 121
     import GHC.Utils.Logger
    
    117 122
     import GHC.Utils.Error
    
    118
    -import GHC.Utils.Exception
    
    119 123
     
    
    120
    -import System.Directory
    
    121
    -import System.FilePath as FilePath
    
    122 124
     import Control.Monad
    
    123 125
     import Data.Containers.ListUtils (nubOrd)
    
    124
    -import Data.Graph (stronglyConnComp, SCC(..))
    
    125
    -import Data.Char ( toUpper )
    
    126
    +import Data.Graph (SCC(..))
    
    126 127
     import Data.List ( intersperse, partition, sortBy, sortOn, sort )
    
    127 128
     import Data.Set (Set)
    
    128 129
     import Data.Monoid (First(..))
    
    129
    -import qualified Data.Semigroup as Semigroup
    
    130 130
     import qualified Data.Set as Set
    
    131
    -import Control.Applicative
    
    132
    -import GHC.Unit.External.Database
    
    133 131
     import Data.IORef
    
    134 132
     import Data.Either (partitionEithers)
    
    135 133
     
    
    ... ... @@ -177,162 +175,6 @@ import Data.Either (partitionEithers)
    177 175
     -- When compiling A, we record in B's Module value whether it's
    
    178 176
     -- in a different DLL, by setting the DLL flag.
    
    179 177
     
    
    180
    --- | Given a module name, there may be multiple ways it came into scope,
    
    181
    --- possibly simultaneously.  This data type tracks all the possible ways
    
    182
    --- it could have come into scope.  Warning: don't use the record functions,
    
    183
    --- they're partial!
    
    184
    -data ModuleOrigin =
    
    185
    -    -- | Module is hidden, and thus never will be available for import.
    
    186
    -    -- (But maybe the user didn't realize), so we'll still keep track
    
    187
    -    -- of these modules.)
    
    188
    -    ModHidden
    
    189
    -
    
    190
    -    -- | Module is unavailable because the unit is unusable.
    
    191
    -  | ModUnusable !UnusableUnit
    
    192
    -
    
    193
    -    -- | Module is public, and could have come from some places.
    
    194
    -  | ModOrigin {
    
    195
    -        -- | @Just False@ means that this module is in
    
    196
    -        -- someone's @exported-modules@ list, but that package is hidden;
    
    197
    -        -- @Just True@ means that it is available; @Nothing@ means neither
    
    198
    -        -- applies.
    
    199
    -        fromOrigUnit :: Maybe Bool
    
    200
    -        -- | Is the module available from a reexport of an exposed package?
    
    201
    -        -- There could be multiple.
    
    202
    -      , fromExposedReexport :: [UnitInfo]
    
    203
    -        -- | Is the module available from a reexport of a hidden package?
    
    204
    -      , fromHiddenReexport :: [UnitInfo]
    
    205
    -        -- | Did the module export come from a package flag? (ToDo: track
    
    206
    -        -- more information.
    
    207
    -      , fromPackageFlag :: Bool
    
    208
    -      }
    
    209
    -
    
    210
    --- | A unusable unit module origin
    
    211
    -data UnusableUnit = UnusableUnit
    
    212
    -  { uuUnit        :: !Unit               -- ^ Unusable unit
    
    213
    -  , uuReason      :: !UnusableUnitReason -- ^ Reason
    
    214
    -  , uuIsReexport  :: !Bool               -- ^ Is the "module" a reexport?
    
    215
    -  }
    
    216
    -
    
    217
    -instance Outputable ModuleOrigin where
    
    218
    -    ppr ModHidden = text "hidden module"
    
    219
    -    ppr (ModUnusable _) = text "unusable module"
    
    220
    -    ppr (ModOrigin e res rhs f) = sep (punctuate comma (
    
    221
    -        (case e of
    
    222
    -            Nothing -> []
    
    223
    -            Just False -> [text "hidden package"]
    
    224
    -            Just True -> [text "exposed package"]) ++
    
    225
    -        (if null res
    
    226
    -            then []
    
    227
    -            else [text "reexport by" <+>
    
    228
    -                    sep (map (ppr . mkUnit) res)]) ++
    
    229
    -        (if null rhs
    
    230
    -            then []
    
    231
    -            else [text "hidden reexport by" <+>
    
    232
    -                    sep (map (ppr . mkUnit) rhs)]) ++
    
    233
    -        (if f then [text "package flag"] else [])
    
    234
    -        ))
    
    235
    -
    
    236
    --- | Smart constructor for a module which is in @exposed-modules@.  Takes
    
    237
    --- as an argument whether or not the defining package is exposed.
    
    238
    -fromExposedModules :: Bool -> ModuleOrigin
    
    239
    -fromExposedModules e = ModOrigin (Just e) [] [] False
    
    240
    -
    
    241
    --- | Smart constructor for a module which is in @reexported-modules@.  Takes
    
    242
    --- as an argument whether or not the reexporting package is exposed, and
    
    243
    --- also its 'UnitInfo'.
    
    244
    -fromReexportedModules :: Bool -> UnitInfo -> ModuleOrigin
    
    245
    -fromReexportedModules True pkg = ModOrigin Nothing [pkg] [] False
    
    246
    -fromReexportedModules False pkg = ModOrigin Nothing [] [pkg] False
    
    247
    -
    
    248
    --- | Smart constructor for a module which was bound by a package flag.
    
    249
    -fromFlag :: ModuleOrigin
    
    250
    -fromFlag = ModOrigin Nothing [] [] True
    
    251
    -
    
    252
    -instance Semigroup ModuleOrigin where
    
    253
    -    x@(ModOrigin e res rhs f) <> y@(ModOrigin e' res' rhs' f') =
    
    254
    -        ModOrigin (g e e') (res ++ res') (rhs ++ rhs') (f || f')
    
    255
    -      where g (Just b) (Just b')
    
    256
    -                | b == b'   = Just b
    
    257
    -                | otherwise = pprPanic "ModOrigin: package both exposed/hidden" $
    
    258
    -                    text "x: " <> ppr x $$ text "y: " <> ppr y
    
    259
    -            g Nothing x = x
    
    260
    -            g x Nothing = x
    
    261
    -
    
    262
    -    x <> y = pprPanic "ModOrigin: module origin mismatch" $
    
    263
    -                 text "x: " <> ppr x $$ text "y: " <> ppr y
    
    264
    -
    
    265
    -instance Monoid ModuleOrigin where
    
    266
    -    mempty = ModOrigin Nothing [] [] False
    
    267
    -    mappend = (Semigroup.<>)
    
    268
    -
    
    269
    --- | Is the name from the import actually visible? (i.e. does it cause
    
    270
    --- ambiguity, or is it only relevant when we're making suggestions?)
    
    271
    -originVisible :: ModuleOrigin -> Bool
    
    272
    -originVisible ModHidden = False
    
    273
    -originVisible (ModUnusable _) = False
    
    274
    -originVisible (ModOrigin b res _ f) = b == Just True || not (null res) || f
    
    275
    -
    
    276
    --- | Are there actually no providers for this module?  This will never occur
    
    277
    --- except when we're filtering based on package imports.
    
    278
    -originEmpty :: ModuleOrigin -> Bool
    
    279
    -originEmpty (ModOrigin Nothing [] [] False) = True
    
    280
    -originEmpty _ = False
    
    281
    -
    
    282
    --- | 'UniqFM' map from 'Unit' to a 'UnitVisibility'.
    
    283
    -type VisibilityMap = UniqMap Unit UnitVisibility
    
    284
    -
    
    285
    --- | 'UnitVisibility' records the various aspects of visibility of a particular
    
    286
    --- 'Unit'.
    
    287
    -data UnitVisibility = UnitVisibility
    
    288
    -    { uv_expose_all :: Bool
    
    289
    -      --  ^ Should all modules in exposed-modules should be dumped into scope?
    
    290
    -    , uv_renamings :: [(ModuleName, ModuleName)]
    
    291
    -      -- ^ Any custom renamings that should bring extra 'ModuleName's into
    
    292
    -      -- scope.
    
    293
    -    , uv_package_name :: First FastString
    
    294
    -      -- ^ The package name associated with the 'Unit'.  This is used
    
    295
    -      -- to implement legacy behavior where @-package foo-0.1@ implicitly
    
    296
    -      -- hides any packages named @foo@
    
    297
    -    , uv_requirements :: UniqMap ModuleName (Set InstantiatedModule)
    
    298
    -      -- ^ The signatures which are contributed to the requirements context
    
    299
    -      -- from this unit ID.
    
    300
    -    , uv_explicit :: Maybe PackageArg
    
    301
    -      -- ^ Whether or not this unit was explicitly brought into scope,
    
    302
    -      -- as opposed to implicitly via the 'exposed' fields in the
    
    303
    -      -- package database (when @-hide-all-packages@ is not passed.)
    
    304
    -    }
    
    305
    -
    
    306
    -instance Outputable UnitVisibility where
    
    307
    -    ppr (UnitVisibility {
    
    308
    -        uv_expose_all = b,
    
    309
    -        uv_renamings = rns,
    
    310
    -        uv_package_name = First mb_pn,
    
    311
    -        uv_requirements = reqs,
    
    312
    -        uv_explicit = explicit
    
    313
    -    }) = ppr (b, rns, mb_pn, reqs, explicit)
    
    314
    -
    
    315
    -instance Semigroup UnitVisibility where
    
    316
    -    uv1 <> uv2
    
    317
    -        = UnitVisibility
    
    318
    -          { uv_expose_all = uv_expose_all uv1 || uv_expose_all uv2
    
    319
    -          , uv_renamings = uv_renamings uv1 ++ uv_renamings uv2
    
    320
    -          , uv_package_name = mappend (uv_package_name uv1) (uv_package_name uv2)
    
    321
    -          , uv_requirements = plusUniqMap_C Set.union (uv_requirements uv2) (uv_requirements uv1)
    
    322
    -          , uv_explicit = uv_explicit uv1 <|> uv_explicit uv2
    
    323
    -          }
    
    324
    -
    
    325
    -instance Monoid UnitVisibility where
    
    326
    -    mempty = UnitVisibility
    
    327
    -             { uv_expose_all = False
    
    328
    -             , uv_renamings = []
    
    329
    -             , uv_package_name = First Nothing
    
    330
    -             , uv_requirements = emptyUniqMap
    
    331
    -             , uv_explicit = Nothing
    
    332
    -             }
    
    333
    -    mappend = (Semigroup.<>)
    
    334
    -
    
    335
    -
    
    336 178
     -- | Unit configuration
    
    337 179
     data UnitConfig = UnitConfig
    
    338 180
        { unitConfigPlatformArchOS :: !ArchOS        -- ^ Platform arch and OS
    
    ... ... @@ -357,9 +199,6 @@ data UnitConfig = UnitConfig
    357 199
        , unitConfigHideAllPlugins :: !Bool     -- ^ Hide all plugins units by default
    
    358 200
     
    
    359 201
        , unitConfigDBCache      :: !(ExternalUnitDatabaseCache UnitId)
    
    360
    -      -- ^ Cache of databases to use, in the order they were specified on the
    
    361
    -      -- command line (later databases shadow earlier ones).
    
    362
    -      -- If Nothing, databases will be found using `unitConfigFlagsDB`.
    
    363 202
     
    
    364 203
        -- command-line flags
    
    365 204
        , unitConfigFlagsDB      :: [PackageDBFlag]     -- ^ Unit databases flags
    
    ... ... @@ -423,58 +262,6 @@ initUnitConfig dflags cached_dbs home_units =
    423 262
         offsetPackageDb (Just offset) (PackageDB (PkgDbPath p)) | OsPath.isRelative p = PackageDB (PkgDbPath (OsPath.unsafeEncodeUtf offset OsPath.</> p))
    
    424 263
         offsetPackageDb _ p = p
    
    425 264
     
    
    426
    -
    
    427
    --- | Map from 'ModuleName' to a set of module providers (i.e. a 'Module' and
    
    428
    --- its 'ModuleOrigin').
    
    429
    ---
    
    430
    --- NB: the set is in fact a 'Map Module ModuleOrigin', probably to keep only one
    
    431
    --- origin for a given 'Module'
    
    432
    -
    
    433
    -type ModuleNameProvidersMap =
    
    434
    -    UniqMap ModuleName (UniqMap Module ModuleOrigin)
    
    435
    -
    
    436
    -data GlobalUnitKey =
    
    437
    -  GlobalUnitKey
    
    438
    -    UnitId -- ^ Unit Id of the 'UnitInfo'
    
    439
    -    ST.ShortText
    
    440
    -
    
    441
    -data UnitIndex = UnitIndex
    
    442
    -  { ui_wireMap :: WiringMap
    
    443
    -  -- ^ TODO @fendor: document global property
    
    444
    -  , ui_unwireMap :: UnwiringMap
    
    445
    -  -- ^ TODO @fendor: document global property
    
    446
    -  , ui_unitInfoMap :: UnitInfoMap
    
    447
    -  -- ^ TODO @fendor: This needs to be Map (UnitId, AbiHash) UnitInfo for absolut correctness
    
    448
    -  }
    
    449
    -
    
    450
    -initUnitIndex :: UnitIndex
    
    451
    -initUnitIndex = UnitIndex
    
    452
    -  { ui_wireMap = emptyUniqMap
    
    453
    -  , ui_unwireMap = emptyUniqMap
    
    454
    -  , ui_unitInfoMap = emptyUniqMap
    
    455
    -  }
    
    456
    -
    
    457
    -setWireMap :: WiringMap -> UnitIndex -> UnitIndex
    
    458
    -setWireMap wired_map unit_index =
    
    459
    -  unit_index
    
    460
    -    { ui_wireMap = wired_map
    
    461
    -    , ui_unwireMap = listToUniqMap [ (v,k) | (k,v) <- nonDetUniqMapToList wired_map ]
    
    462
    -    }
    
    463
    -
    
    464
    -isWireMapEmpty :: UnitIndex -> Bool
    
    465
    -isWireMapEmpty unit_index =
    
    466
    -  isNullUniqMap (ui_wireMap unit_index)
    
    467
    -
    
    468
    -addUnitInfoMap :: UnitInfoMap -> UnitIndex -> UnitIndex
    
    469
    -addUnitInfoMap unit_info_map unit_index =
    
    470
    -  unit_index
    
    471
    -    { ui_unitInfoMap = unit_info_map `plusUniqMap` ui_unitInfoMap unit_index
    
    472
    -    }
    
    473
    -
    
    474
    --- lookupUnitInfoMap :: UnitIndex -> UnitId -> Maybe UnitInfo
    
    475
    --- lookupUnitInfoMap unit_index unit_id =
    
    476
    ---   lookupUniqMap (ui_unitInfoMap unit_index) unit_id
    
    477
    -
    
    478 265
     data UnitState = UnitState {
    
    479 266
       -- | A mapping of 'Unit' to 'UnitInfo'.  This list is adjusted
    
    480 267
       -- so that only valid units are here.  'UnitInfo' reflects
    
    ... ... @@ -495,12 +282,6 @@ data UnitState = UnitState {
    495 282
       -- And also to resolve package qualifiers with the PackageImports extension.
    
    496 283
       packageNameMap            :: UniqFM PackageName UnitId,
    
    497 284
     
    
    498
    -  -- -- | A mapping from database unit keys to wired in unit ids.
    
    499
    -  -- wireMap :: WiringMap,
    
    500
    -
    
    501
    -  -- -- | A mapping from wired in unit ids to unit keys from the database.
    
    502
    -  -- unwireMap :: UnwiringMap,
    
    503
    -
    
    504 285
       -- | The units we're going to link in eagerly.  This list
    
    505 286
       -- should be in reverse dependency order; that is, a unit
    
    506 287
       -- is always mentioned before the units it depends on.
    
    ... ... @@ -555,8 +336,6 @@ emptyUnitState = UnitState {
    555 336
         allowVirtualUnits = False
    
    556 337
         }
    
    557 338
     
    
    558
    -type UnitInfoMap = UniqMap UnitId UnitInfo
    
    559
    -
    
    560 339
     -- | Find the unit we know about with the given unit, if any
    
    561 340
     lookupUnit :: UnitState -> Unit -> Maybe UnitInfo
    
    562 341
     lookupUnit pkgs = lookupUnit' (allowVirtualUnits pkgs) (unitInfoMap pkgs)
    
    ... ... @@ -593,7 +372,6 @@ lookupUnitId state uid = lookupUnitId' (unitInfoMap state) uid
    593 372
     lookupUnitId' :: UnitInfoMap -> UnitId -> Maybe UnitInfo
    
    594 373
     lookupUnitId' db uid = lookupUniqMap db uid
    
    595 374
     
    
    596
    -
    
    597 375
     -- | Looks up the given unit in the unit state, panicking if it is not found
    
    598 376
     unsafeLookupUnit :: HasDebugCallStack => UnitState -> Unit -> UnitInfo
    
    599 377
     unsafeLookupUnit state u = case lookupUnit state u of
    
    ... ... @@ -711,7 +489,7 @@ initUnits logger dflags unit_index cached_dbs home_units = do
    711 489
         FormatText (updSDocContext (\ctx -> ctx {sdocLineLength = 200})
    
    712 490
                     $ pprModuleMap (moduleNameProvidersMap unit_state))
    
    713 491
     
    
    714
    -  wireMap <- ui_wireMap <$> readIORef unit_index
    
    492
    +  wireMap <- wiringMap <$> readIORef unit_index
    
    715 493
     
    
    716 494
       let home_unit = mkHomeUnit wireMap
    
    717 495
                                  (homeUnitId_ dflags)
    
    ... ... @@ -764,210 +542,6 @@ mkHomeUnit wmap hu_id hu_instanceof hu_instantiations_ =
    764 542
              | otherwise
    
    765 543
              -> DefiniteHomeUnit hu_id (Just (u, is))
    
    766 544
     
    
    767
    --- -----------------------------------------------------------------------------
    
    768
    --- Reading the unit database(s)
    
    769
    -
    
    770
    -readUnitDatabases :: Logger -> UnitConfig -> IO [UnitDatabase UnitId]
    
    771
    -readUnitDatabases logger cfg = do
    
    772
    -  conf_refs <- getUnitDbRefs cfg
    
    773
    -  confs     <- liftM catMaybes $ mapM (resolveUnitDatabase cfg) conf_refs
    
    774
    -  mapM (readOrGetUnitDatabase logger cfg) confs
    
    775
    -
    
    776
    -
    
    777
    -getUnitDbRefs :: UnitConfig -> IO [PkgDbRef]
    
    778
    -getUnitDbRefs cfg = do
    
    779
    -  let system_conf_refs = [UserPkgDb, GlobalPkgDb]
    
    780
    -
    
    781
    -  e_pkg_path <- tryIO (getEnv $ map toUpper (unitConfigProgramName cfg) ++ "_PACKAGE_PATH")
    
    782
    -  let base_conf_refs = case e_pkg_path of
    
    783
    -        Left _ -> system_conf_refs
    
    784
    -        Right path
    
    785
    -         | Just (xs, x) <- snocView path, isSearchPathSeparator x
    
    786
    -         -> map PkgDbPath (OsPath.splitSearchPath (OsPath.unsafeEncodeUtf xs)) ++ system_conf_refs
    
    787
    -         | otherwise
    
    788
    -         -> map PkgDbPath (OsPath.splitSearchPath (OsPath.unsafeEncodeUtf path))
    
    789
    -
    
    790
    -  -- Apply the package DB-related flags from the command line to get the
    
    791
    -  -- final list of package DBs.
    
    792
    -  --
    
    793
    -  -- Notes on ordering:
    
    794
    -  --  * The list of flags is reversed (later ones first)
    
    795
    -  --  * We work with the package DB list in "left shadows right" order
    
    796
    -  --  * and finally reverse it at the end, to get "right shadows left"
    
    797
    -  --
    
    798
    -  return $ reverse (foldr doFlag base_conf_refs (unitConfigFlagsDB cfg))
    
    799
    - where
    
    800
    -  doFlag (PackageDB p) dbs = p : dbs
    
    801
    -  doFlag NoUserPackageDB dbs = filter isNotUser dbs
    
    802
    -  doFlag NoGlobalPackageDB dbs = filter isNotGlobal dbs
    
    803
    -  doFlag ClearPackageDBs _ = []
    
    804
    -
    
    805
    -  isNotUser UserPkgDb = False
    
    806
    -  isNotUser _ = True
    
    807
    -
    
    808
    -  isNotGlobal GlobalPkgDb = False
    
    809
    -  isNotGlobal _ = True
    
    810
    -
    
    811
    --- | Return the path of a package database from a 'PkgDbRef'. Return 'Nothing'
    
    812
    --- when the user database filepath is expected but the latter doesn't exist.
    
    813
    ---
    
    814
    --- NB: This logic is reimplemented in Cabal, so if you change it,
    
    815
    --- make sure you update Cabal. (Or, better yet, dump it in the
    
    816
    --- compiler info so Cabal can use the info.)
    
    817
    -resolveUnitDatabase :: UnitConfig -> PkgDbRef -> IO (Maybe OsPath)
    
    818
    -resolveUnitDatabase cfg GlobalPkgDb = return $ Just $ OsPath.unsafeEncodeUtf $ unitConfigGlobalDB cfg
    
    819
    -resolveUnitDatabase cfg UserPkgDb = runMaybeT $ do
    
    820
    -  dir <- versionedAppDir (unitConfigProgramName cfg) (unitConfigPlatformArchOS cfg)
    
    821
    -  let pkgconf = dir </> unitConfigDBName cfg
    
    822
    -  exist <- tryMaybeT $ doesDirectoryExist pkgconf
    
    823
    -  if exist then return (OsPath.unsafeEncodeUtf pkgconf) else mzero
    
    824
    -resolveUnitDatabase _ (PkgDbPath name) = return $ Just name
    
    825
    -
    
    826
    --- | Get the cached 'UnitDatabase' or read the 'UnitDatabase' at the given location.
    
    827
    -readOrGetUnitDatabase :: Logger -> UnitConfig -> OsPath -> IO (UnitDatabase UnitId)
    
    828
    -readOrGetUnitDatabase logger cfg conf_file =
    
    829
    -  readExternalUnitDatabase (unitConfigDBCache cfg) conf_file >>= \ case
    
    830
    -    Nothing -> do
    
    831
    -      new_db <- readUnitDatabase logger cfg conf_file
    
    832
    -      cacheExternalUnitDatabase (unitConfigDBCache cfg) new_db
    
    833
    -      pure new_db
    
    834
    -    Just db ->
    
    835
    -      pure db
    
    836
    -
    
    837
    --- | Read the 'UnitDatabase' at the given location.
    
    838
    -readUnitDatabase :: Logger -> UnitConfig -> OsPath -> IO (UnitDatabase UnitId)
    
    839
    -readUnitDatabase logger cfg conf_file = do
    
    840
    -  isdir <- OsPath.doesDirectoryExist conf_file
    
    841
    -
    
    842
    -  proto_pkg_configs <-
    
    843
    -    if isdir
    
    844
    -       then readDirStyleUnitInfo conf_file
    
    845
    -       else do
    
    846
    -            isfile <- OsPath.doesFileExist conf_file
    
    847
    -            if isfile
    
    848
    -               then do
    
    849
    -                 mpkgs <- tryReadOldFileStyleUnitInfo
    
    850
    -                 case mpkgs of
    
    851
    -                   Just pkgs -> return pkgs
    
    852
    -                   Nothing   -> throwGhcExceptionIO $ InstallationError $
    
    853
    -                      "ghc no longer supports single-file style package " ++
    
    854
    -                      "databases (" ++ show conf_file ++
    
    855
    -                      ") use 'ghc-pkg init' to create the database with " ++
    
    856
    -                      "the correct format."
    
    857
    -               else throwGhcExceptionIO $ InstallationError $
    
    858
    -                      "can't find a package database at " ++ show conf_file
    
    859
    -
    
    860
    -  let
    
    861
    -      -- Fix #16360: remove trailing slash from conf_file before calculating pkgroot
    
    862
    -      conf_file' = OsPath.dropTrailingPathSeparator conf_file
    
    863
    -      top_dir = OsPath.unsafeEncodeUtf (unitConfigGHCDir cfg)
    
    864
    -      pkgroot = OsPath.takeDirectory conf_file'
    
    865
    -      pkg_configs1 = map (mungeUnitInfo top_dir pkgroot . mapUnitInfo (\(UnitKey x) -> UnitId x) . mkUnitKeyInfo)
    
    866
    -                         proto_pkg_configs
    
    867
    -  --
    
    868
    -  pkg_configs2 <- traverse evaluateUnitInfo pkg_configs1
    
    869
    -  return $ pkg_configs2 `seqList` UnitDatabase conf_file' pkg_configs2
    
    870
    -  where
    
    871
    -    readDirStyleUnitInfo :: OsPath -> IO [DbUnitInfo]
    
    872
    -    readDirStyleUnitInfo conf_dir = do
    
    873
    -      let filename = conf_dir OsPath.</> (OsPath.unsafeEncodeUtf "package.cache")
    
    874
    -      cache_exists <- OsPath.doesFileExist filename
    
    875
    -      if cache_exists
    
    876
    -        then do
    
    877
    -          debugTraceMsg logger 2 $ text "Using binary package database:" <+> ppr filename
    
    878
    -          readPackageDbForGhc filename
    
    879
    -        else do
    
    880
    -          -- If there is no package.cache file, we check if the database is not
    
    881
    -          -- empty by inspecting if the directory contains any .conf file. If it
    
    882
    -          -- does, something is wrong and we fail. Otherwise we assume that the
    
    883
    -          -- database is empty.
    
    884
    -          debugTraceMsg logger 2 $ text "There is no package.cache in"
    
    885
    -                      <+> ppr conf_dir
    
    886
    -                       <> text ", checking if the database is empty"
    
    887
    -          db_empty <- all (not . OsPath.isSuffixOf (OsPath.unsafeEncodeUtf ".conf"))
    
    888
    -                   <$> OsPath.getDirectoryContents conf_dir
    
    889
    -          if db_empty
    
    890
    -            then do
    
    891
    -              debugTraceMsg logger 3 $ text "There are no .conf files in"
    
    892
    -                          <+> ppr conf_dir <> text ", treating"
    
    893
    -                          <+> text "package database as empty"
    
    894
    -              return []
    
    895
    -            else
    
    896
    -              throwGhcExceptionIO $ InstallationError $
    
    897
    -                "there is no package.cache in " ++ show conf_dir ++
    
    898
    -                " even though package database is not empty"
    
    899
    -
    
    900
    -
    
    901
    -    -- Single-file style package dbs have been deprecated for some time, but
    
    902
    -    -- it turns out that Cabal was using them in one place. So this is a
    
    903
    -    -- workaround to allow older Cabal versions to use this newer ghc.
    
    904
    -    -- We check if the file db contains just "[]" and if so, we look for a new
    
    905
    -    -- dir-style db in conf_file.d/, ie in a dir next to the given file.
    
    906
    -    -- We cannot just replace the file with a new dir style since Cabal still
    
    907
    -    -- assumes it's a file and tries to overwrite with 'writeFile'.
    
    908
    -    -- ghc-pkg also cooperates with this workaround.
    
    909
    -    tryReadOldFileStyleUnitInfo = do
    
    910
    -      content <- readFile (OsPath.unsafeDecodeUtf conf_file) `catchIO` \_ -> return ""
    
    911
    -      if take 2 content == "[]"
    
    912
    -        then do
    
    913
    -          let conf_dir = conf_file OsPath.<.> OsPath.unsafeEncodeUtf "d"
    
    914
    -          direxists <- OsPath.doesDirectoryExist conf_dir
    
    915
    -          if direxists
    
    916
    -             then do debugTraceMsg logger 2 (text "Ignoring old file-style db and trying:" <+> ppr conf_dir)
    
    917
    -                     liftM Just (readDirStyleUnitInfo conf_dir)
    
    918
    -             else return (Just []) -- ghc-pkg will create it when it's updated
    
    919
    -        else return Nothing
    
    920
    -
    
    921
    -mungeUnitInfo :: OsPath -> OsPath
    
    922
    -                   -> UnitInfo -> UnitInfo
    
    923
    -mungeUnitInfo top_dir pkgroot =
    
    924
    -    mungeBytecodeLibFields
    
    925
    -  . mungeLibDirFields
    
    926
    -  . mungeUnitInfoPaths (ST.pack (OsPath.unsafeDecodeUtf top_dir)) (ST.pack (OsPath.unsafeDecodeUtf pkgroot))
    
    927
    -
    
    928
    -mungeLibDirFields :: UnitInfo -> UnitInfo
    
    929
    -mungeLibDirFields pkg =
    
    930
    -    pkg {
    
    931
    -      unitLibraryDynDirs = case unitLibraryDynDirs pkg of
    
    932
    -         [] -> unitLibraryDirs pkg
    
    933
    -         ds -> ds
    
    934
    -      , unitLibraryDirsStatic = case unitLibraryDirsStatic pkg of
    
    935
    -         [] -> unitLibraryDirs pkg
    
    936
    -         ds -> ds
    
    937
    -    }
    
    938
    -
    
    939
    --- | Default to using library-dirs if bytecode library dirs is not explicitly set.
    
    940
    -mungeBytecodeLibFields :: UnitInfo -> UnitInfo
    
    941
    -mungeBytecodeLibFields pkg =
    
    942
    -    pkg {
    
    943
    -      unitLibraryBytecodeDirs = case unitLibraryBytecodeDirs pkg of
    
    944
    -         [] -> unitLibraryDirs pkg
    
    945
    -         ds -> ds
    
    946
    -    }
    
    947
    -
    
    948
    -evaluateUnitInfo :: UnitInfo -> IO UnitInfo
    
    949
    -evaluateUnitInfo ui = do
    
    950
    -  importDirs <- evaluate $ unitImportDirs ui
    
    951
    -  includeDirs <- evaluate $ unitIncludeDirs ui
    
    952
    -  libraryDirs <- evaluate $ unitLibraryDirs ui
    
    953
    -  libraryBytecodeDirs <- evaluate $ unitLibraryBytecodeDirs ui
    
    954
    -  extDepFrameworkDirs <- evaluate $ unitExtDepFrameworkDirs ui
    
    955
    -  haddockInterfaces <- evaluate $ unitHaddockInterfaces ui
    
    956
    -  haddockHTMLs <- evaluate $ unitHaddockHTMLs ui
    
    957
    -  libraryDynDirs <- evaluate $ unitLibraryDynDirs ui
    
    958
    -  libraryDirsStatic <- evaluate $ unitLibraryDirsStatic ui
    
    959
    -  evaluate ui
    
    960
    -    { unitImportDirs = importDirs
    
    961
    -    , unitIncludeDirs = includeDirs
    
    962
    -    , unitLibraryDirs = libraryDirs
    
    963
    -    , unitLibraryDynDirs = libraryDynDirs
    
    964
    -    , unitLibraryDirsStatic = libraryDirsStatic
    
    965
    -    , unitLibraryBytecodeDirs = libraryBytecodeDirs
    
    966
    -    , unitExtDepFrameworkDirs = extDepFrameworkDirs
    
    967
    -    , unitHaddockInterfaces = haddockInterfaces
    
    968
    -    , unitHaddockHTMLs = haddockHTMLs
    
    969
    -    }
    
    970
    -
    
    971 545
     -- -----------------------------------------------------------------------------
    
    972 546
     -- Modify our copy of the unit database based on trust flags,
    
    973 547
     -- -trust and -distrust.
    
    ... ... @@ -1134,57 +708,6 @@ renameUnitInfo pkg_map insts conf =
    1134 708
                                  (unitExposedModules conf)
    
    1135 709
         }
    
    1136 710
     
    
    1137
    -
    
    1138
    --- A package named on the command line can either include the
    
    1139
    --- version, or just the name if it is unambiguous.
    
    1140
    -matchingStr :: String -> UnitInfo -> Bool
    
    1141
    -matchingStr str p
    
    1142
    -        =  str == unitPackageIdString p
    
    1143
    -        || str == unitPackageNameString p
    
    1144
    -
    
    1145
    -matchingId :: UnitId -> UnitInfo -> Bool
    
    1146
    -matchingId uid p = uid == unitId p
    
    1147
    -
    
    1148
    -matching :: PackageArg -> UnitInfo -> Bool
    
    1149
    -matching (PackageArg str) = matchingStr str
    
    1150
    -matching (UnitIdArg (RealUnit (Definite uid))) = matchingId uid
    
    1151
    -matching (UnitIdArg _)  = \_ -> False -- TODO: warn in this case
    
    1152
    -
    
    1153
    --- | This sorts a list of packages, putting "preferred" packages first.
    
    1154
    --- See 'compareByPreference' for the semantics of "preference".
    
    1155
    -sortByPreference :: UnitPrecedenceMap -> [UnitInfo] -> [UnitInfo]
    
    1156
    -sortByPreference prec_map = sortBy (flip (compareByPreference prec_map))
    
    1157
    -
    
    1158
    --- | Returns 'GT' if @pkg@ should be preferred over @pkg'@ when picking
    
    1159
    --- which should be "active".  Here is the order of preference:
    
    1160
    ---
    
    1161
    ---      1. First, prefer the latest version
    
    1162
    ---      2. If the versions are the same, prefer the package that
    
    1163
    ---      came in the latest package database.
    
    1164
    ---
    
    1165
    --- Pursuant to #12518, we could change this policy to, for example, remove
    
    1166
    --- the version preference, meaning that we would always prefer the units
    
    1167
    --- in later unit database.
    
    1168
    -compareByPreference
    
    1169
    -    :: UnitPrecedenceMap
    
    1170
    -    -> UnitInfo
    
    1171
    -    -> UnitInfo
    
    1172
    -    -> Ordering
    
    1173
    -compareByPreference prec_map pkg pkg'
    
    1174
    -  = case comparing unitPackageVersion pkg pkg' of
    
    1175
    -        GT -> GT
    
    1176
    -        EQ | Just prec  <- lookupUniqMap prec_map (unitId pkg)
    
    1177
    -           , Just prec' <- lookupUniqMap prec_map (unitId pkg')
    
    1178
    -           -- Prefer the unit from the later DB flag (i.e., higher
    
    1179
    -           -- precedence)
    
    1180
    -           -> compare prec prec'
    
    1181
    -           | otherwise
    
    1182
    -           -> EQ
    
    1183
    -        LT -> LT
    
    1184
    -
    
    1185
    -comparing :: Ord a => (t -> a) -> t -> t -> Ordering
    
    1186
    -comparing f a b = f a `compare` f b
    
    1187
    -
    
    1188 711
     pprFlag :: PackageFlag -> SDoc
    
    1189 712
     pprFlag flag = case flag of
    
    1190 713
         HidePackage p   -> text "-hide-package " <> text p
    
    ... ... @@ -1195,143 +718,6 @@ pprTrustFlag flag = case flag of
    1195 718
         TrustPackage p    -> text "-trust " <> text p
    
    1196 719
         DistrustPackage p -> text "-distrust " <> text p
    
    1197 720
     
    
    1198
    --- -----------------------------------------------------------------------------
    
    1199
    --- Wired-in units
    
    1200
    ---
    
    1201
    --- See Note [Wired-in units] in GHC.Unit.Types
    
    1202
    -
    
    1203
    -type WiringMap = UniqMap UnitId UnitId
    
    1204
    -type UnwiringMap = UniqMap UnitId UnitId
    
    1205
    -
    
    1206
    -findWiredInUnits
    
    1207
    -   :: Logger
    
    1208
    -   -> UnitPrecedenceMap
    
    1209
    -   -> [UnitInfo]           -- database
    
    1210
    -   -> VisibilityMap             -- info on what units are visible
    
    1211
    -                                -- for wired in selection
    
    1212
    -   -> IO WiringMap   -- map from unit id to wired identity
    
    1213
    -findWiredInUnits logger prec_map pkgs vis_map = do
    
    1214
    -  -- Now we must find our wired-in units, and rename them to
    
    1215
    -  -- their canonical names (eg. base-1.0 ==> base), as described
    
    1216
    -  -- in Note [Wired-in units] in GHC.Unit.Types
    
    1217
    -  let
    
    1218
    -        matches :: UnitInfo -> UnitId -> Bool
    
    1219
    -        pc `matches` pid = unitPackageName pc == PackageName (unitIdFS pid)
    
    1220
    -
    
    1221
    -        -- find which package corresponds to each wired-in package
    
    1222
    -        -- delete any other packages with the same name
    
    1223
    -        -- update the package and any dependencies to point to the new
    
    1224
    -        -- one.
    
    1225
    -        --
    
    1226
    -        -- When choosing which package to map to a wired-in package
    
    1227
    -        -- name, we try to pick the latest version of exposed packages.
    
    1228
    -        -- However, if there are no exposed wired in packages available
    
    1229
    -        -- (e.g. -hide-all-packages was used), we can't bail: we *have*
    
    1230
    -        -- to assign a package for the wired-in package: so we try again
    
    1231
    -        -- with hidden packages included to (and pick the latest
    
    1232
    -        -- version).
    
    1233
    -        --
    
    1234
    -        -- You can also override the default choice by using -ignore-package:
    
    1235
    -        -- this works even when there is no exposed wired in package
    
    1236
    -        -- available.
    
    1237
    -        --
    
    1238
    -        findWiredInUnit :: [UnitInfo] -> UnitId -> IO (Maybe (UnitId, UnitInfo))
    
    1239
    -        findWiredInUnit pkgs wired_pkg = firstJustsM [try all_exposed_ps, try all_ps, notfound]
    
    1240
    -          where
    
    1241
    -                all_ps = [ p | p <- pkgs, p `matches` wired_pkg ]
    
    1242
    -                all_exposed_ps = [ p | p <- all_ps, (mkUnit p) `elemUniqMap` vis_map ]
    
    1243
    -
    
    1244
    -                try ps = case sortByPreference prec_map ps of
    
    1245
    -                    p:_ -> Just <$> pick p
    
    1246
    -                    _ -> pure Nothing
    
    1247
    -
    
    1248
    -                notfound = do
    
    1249
    -                          debugTraceMsg logger 2 $
    
    1250
    -                            text "wired-in package "
    
    1251
    -                                 <> ftext (unitIdFS wired_pkg)
    
    1252
    -                                 <> text " not found."
    
    1253
    -                          return Nothing
    
    1254
    -                pick :: UnitInfo -> IO (UnitId, UnitInfo)
    
    1255
    -                pick pkg = do
    
    1256
    -                        debugTraceMsg logger 2 $
    
    1257
    -                            text "wired-in package "
    
    1258
    -                                 <> ftext (unitIdFS wired_pkg)
    
    1259
    -                                 <> text " mapped to "
    
    1260
    -                                 <> ppr (unitId pkg)
    
    1261
    -                        return (wired_pkg, pkg)
    
    1262
    -
    
    1263
    -
    
    1264
    -  mb_wired_in_pkgs <- mapM (findWiredInUnit pkgs) wiredInUnitIds
    
    1265
    -  let
    
    1266
    -        wired_in_pkgs = catMaybes mb_wired_in_pkgs
    
    1267
    -
    
    1268
    -        wiredInMap :: UniqMap UnitId UnitId
    
    1269
    -        wiredInMap = listToUniqMap
    
    1270
    -          [ (unitId realUnitInfo, wiredInUnitId)
    
    1271
    -          | (wiredInUnitId, realUnitInfo) <- wired_in_pkgs
    
    1272
    -          , not (unitIsIndefinite realUnitInfo)
    
    1273
    -          ]
    
    1274
    -
    
    1275
    -  return wiredInMap
    
    1276
    -
    
    1277
    -updateWiredInUnits :: WiringMap -> UnitInfoMap -> [UnitInfo] -> [Either UnitInfo UnitInfo]
    
    1278
    -updateWiredInUnits wiredInMap knownInfos pkgs =
    
    1279
    -  map (updateWiredInUnitsInUnitInfo wiredInMap knownInfos) pkgs
    
    1280
    -
    
    1281
    -updateWiredInUnitsInUnitInfo :: WiringMap -> UnitInfoMap -> UnitInfo -> Either UnitInfo UnitInfo
    
    1282
    -updateWiredInUnitsInUnitInfo wiredInMap knownInfos pkg =
    
    1283
    -  let
    
    1284
    -    upd_pkg pkg
    
    1285
    -      | Just wiredInUnitId <- lookupUniqMap wiredInMap (unitId pkg)
    
    1286
    -      = pkg { unitId         = wiredInUnitId
    
    1287
    -            , unitInstanceOf = wiredInUnitId
    
    1288
    -                -- every non instantiated unit is an instance of
    
    1289
    -                -- itself (required by Backpack...)
    
    1290
    -                --
    
    1291
    -                -- See Note [About units] in GHC.Unit
    
    1292
    -            }
    
    1293
    -      | otherwise
    
    1294
    -      = pkg
    
    1295
    -    upd_deps pkg = pkg {
    
    1296
    -          unitDepends = map (upd_wired_in wiredInMap) (unitDepends pkg),
    
    1297
    -          unitExposedModules
    
    1298
    -            = map (\(k,v) -> (k, fmap (upd_wired_in_mod wiredInMap) v))
    
    1299
    -                  (unitExposedModules pkg)
    
    1300
    -        }
    
    1301
    -  in
    
    1302
    -    case lookupUniqMap knownInfos (unitId pkg) of
    
    1303
    -      Just ui ->
    
    1304
    -        Right ui
    
    1305
    -      Nothing ->
    
    1306
    -        let
    
    1307
    -          updated_pkg = upd_deps $ upd_pkg pkg
    
    1308
    -        in
    
    1309
    -          Left updated_pkg
    
    1310
    -
    
    1311
    --- Helper functions for rewiring Module and Unit.  These
    
    1312
    --- rewrite Units of modules in wired-in packages to the form known to the
    
    1313
    --- compiler, as described in Note [Wired-in units] in GHC.Unit.Types.
    
    1314
    ---
    
    1315
    --- For instance, base-4.9.0.0 will be rewritten to just base, to match
    
    1316
    --- what appears in GHC.Builtin.Names.
    
    1317
    -
    
    1318
    -upd_wired_in_mod :: WiringMap -> Module -> Module
    
    1319
    -upd_wired_in_mod wiredInMap (Module uid m) = Module (upd_wired_in_uid wiredInMap uid) m
    
    1320
    -
    
    1321
    -upd_wired_in_uid :: WiringMap -> Unit -> Unit
    
    1322
    -upd_wired_in_uid wiredInMap u = case u of
    
    1323
    -   HoleUnit -> HoleUnit
    
    1324
    -   RealUnit (Definite uid) -> RealUnit (Definite (upd_wired_in wiredInMap uid))
    
    1325
    -   VirtUnit indef_uid ->
    
    1326
    -      VirtUnit $ mkInstantiatedUnit
    
    1327
    -        (instUnitInstanceOf indef_uid)
    
    1328
    -        (map (\(x,y) -> (x,upd_wired_in_mod wiredInMap y)) (instUnitInsts indef_uid))
    
    1329
    -
    
    1330
    -upd_wired_in :: WiringMap -> UnitId -> UnitId
    
    1331
    -upd_wired_in wiredInMap key
    
    1332
    -    | Just key' <- lookupUniqMap wiredInMap key = key'
    
    1333
    -    | otherwise = key
    
    1334
    -
    
    1335 721
     updateVisibilityMap :: WiringMap -> VisibilityMap -> VisibilityMap
    
    1336 722
     updateVisibilityMap wiredInMap vis_map = foldl' f vis_map (nonDetUniqMapToList wiredInMap)
    
    1337 723
       where f vm (from, to) = case lookupUniqMap vis_map (RealUnit (Definite from)) of
    
    ... ... @@ -1341,51 +727,6 @@ updateVisibilityMap wiredInMap vis_map = foldl' f vis_map (nonDetUniqMapToList w
    1341 727
     
    
    1342 728
       -- ----------------------------------------------------------------------------
    
    1343 729
     
    
    1344
    --- | The reason why a unit is unusable.
    
    1345
    -data UnusableUnitReason
    
    1346
    -  = -- | We ignored it explicitly using @-ignore-package@.
    
    1347
    -    IgnoredWithFlag
    
    1348
    -    -- | This unit transitively depends on a unit that was never present
    
    1349
    -    -- in any of the provided databases.
    
    1350
    -  | BrokenDependencies   [UnitId]
    
    1351
    -    -- | This unit transitively depends on a unit involved in a cycle.
    
    1352
    -    -- Note that the list of 'UnitId' reports the direct dependencies
    
    1353
    -    -- of this unit that (transitively) depended on the cycle, and not
    
    1354
    -    -- the actual cycle itself (which we report separately at high verbosity.)
    
    1355
    -  | CyclicDependencies   [UnitId]
    
    1356
    -    -- | This unit transitively depends on a unit which was ignored.
    
    1357
    -  | IgnoredDependencies  [UnitId]
    
    1358
    -    -- | This unit transitively depends on a unit which was
    
    1359
    -    -- shadowed by an ABI-incompatible unit.
    
    1360
    -  | ShadowedDependencies [UnitId]
    
    1361
    -
    
    1362
    -instance Outputable UnusableUnitReason where
    
    1363
    -    ppr IgnoredWithFlag = text "[ignored with flag]"
    
    1364
    -    ppr (BrokenDependencies uids)   = brackets (text "broken" <+> ppr uids)
    
    1365
    -    ppr (CyclicDependencies uids)   = brackets (text "cyclic" <+> ppr uids)
    
    1366
    -    ppr (IgnoredDependencies uids)  = brackets (text "ignored" <+> ppr uids)
    
    1367
    -    ppr (ShadowedDependencies uids) = brackets (text "shadowed" <+> ppr uids)
    
    1368
    -
    
    1369
    -type UnusableUnits = UniqMap UnitId (UnitInfo, UnusableUnitReason)
    
    1370
    -
    
    1371
    -pprReason :: SDoc -> UnusableUnitReason -> SDoc
    
    1372
    -pprReason pref reason = case reason of
    
    1373
    -  IgnoredWithFlag ->
    
    1374
    -      pref <+> text "ignored due to an -ignore-package flag"
    
    1375
    -  BrokenDependencies deps ->
    
    1376
    -      pref <+> text "unusable due to missing dependencies:" $$
    
    1377
    -        nest 2 (hsep (map ppr deps))
    
    1378
    -  CyclicDependencies deps ->
    
    1379
    -      pref <+> text "unusable due to cyclic dependencies:" $$
    
    1380
    -        nest 2 (hsep (map ppr deps))
    
    1381
    -  IgnoredDependencies deps ->
    
    1382
    -      pref <+> text ("unusable because the -ignore-package flag was used to " ++
    
    1383
    -                     "ignore at least one of its dependencies:") $$
    
    1384
    -        nest 2 (hsep (map ppr deps))
    
    1385
    -  ShadowedDependencies deps ->
    
    1386
    -      pref <+> text "unusable due to shadowed dependencies:" $$
    
    1387
    -        nest 2 (hsep (map ppr deps))
    
    1388
    -
    
    1389 730
     reportCycles :: Logger -> [SCC UnitInfo] -> IO ()
    
    1390 731
     reportCycles logger sccs = when (logVerbAtLeast logger 2) $ mapM_ report sccs
    
    1391 732
       where
    
    ... ... @@ -1395,193 +736,6 @@ reportCycles logger sccs = when (logVerbAtLeast logger 2) $ mapM_ report sccs
    1395 736
               text "these packages are involved in a cycle:" $$
    
    1396 737
                 nest 2 (hsep (map (ppr . unitId) vs))
    
    1397 738
     
    
    1398
    -reportUnusable :: Logger -> UnusableUnits -> IO ()
    
    1399
    -reportUnusable logger pkgs = when (logVerbAtLeast logger 2) $ mapM_ report (nonDetUniqMapToList pkgs)
    
    1400
    -  where
    
    1401
    -    report (ipid, (_, reason)) =
    
    1402
    -       debugTraceMsg logger 2 $
    
    1403
    -         pprReason
    
    1404
    -           (text "package" <+> ppr ipid <+> text "is") reason
    
    1405
    -
    
    1406
    --- ----------------------------------------------------------------------------
    
    1407
    ---
    
    1408
    --- Utilities on the database
    
    1409
    ---
    
    1410
    -
    
    1411
    --- | A reverse dependency index, mapping an 'UnitId' to
    
    1412
    --- the 'UnitId's which have a dependency on it.
    
    1413
    -type RevIndex = UniqMap UnitId [UnitId]
    
    1414
    -
    
    1415
    --- | Compute the reverse dependency index of a unit database.
    
    1416
    -reverseDeps :: UnitInfoMap -> RevIndex
    
    1417
    -reverseDeps db = nonDetFoldUniqMap go emptyUniqMap db
    
    1418
    -  where
    
    1419
    -    go :: (UnitId, UnitInfo) -> RevIndex -> RevIndex
    
    1420
    -    go (_uid, pkg) r = foldl' (go' (unitId pkg)) r (unitDepends pkg)
    
    1421
    -    go' from r to = addToUniqMap_C (++) r to [from]
    
    1422
    -
    
    1423
    --- | Given a list of 'UnitId's to remove, a database,
    
    1424
    --- and a reverse dependency index (as computed by 'reverseDeps'),
    
    1425
    --- remove those units, plus any units which depend on them.
    
    1426
    --- Returns the pruned database, as well as a list of 'UnitInfo's
    
    1427
    --- that was removed.
    
    1428
    -removeUnits :: [UnitId] -> RevIndex
    
    1429
    -               -> UnitInfoMap
    
    1430
    -               -> (UnitInfoMap, [UnitInfo])
    
    1431
    -removeUnits uids index m = go uids (m,[])
    
    1432
    -  where
    
    1433
    -    go [] (m,pkgs) = (m,pkgs)
    
    1434
    -    go (uid:uids) (m,pkgs)
    
    1435
    -        | Just pkg <- lookupUniqMap m uid
    
    1436
    -        = case lookupUniqMap index uid of
    
    1437
    -            Nothing    -> go uids (delFromUniqMap m uid, pkg:pkgs)
    
    1438
    -            Just rdeps -> go (rdeps ++ uids) (delFromUniqMap m uid, pkg:pkgs)
    
    1439
    -        | otherwise
    
    1440
    -        = go uids (m,pkgs)
    
    1441
    -
    
    1442
    --- | Given a 'UnitInfo' from some 'UnitInfoMap', return all entries in 'depends'
    
    1443
    --- which correspond to units that do not exist in the index.
    
    1444
    -depsNotAvailable :: UnitInfoMap
    
    1445
    -                 -> UnitInfo
    
    1446
    -                 -> [UnitId]
    
    1447
    -depsNotAvailable pkg_map pkg = filter (not . (`elemUniqMap` pkg_map)) (unitDepends pkg)
    
    1448
    -
    
    1449
    --- | Given a 'UnitInfo' from some 'UnitInfoMap' return all entries in
    
    1450
    --- 'unitAbiDepends' which correspond to units that do not exist, OR have
    
    1451
    --- mismatching ABIs.
    
    1452
    -depsAbiMismatch :: UnitInfoMap
    
    1453
    -                -> UnitInfo
    
    1454
    -                -> [UnitId]
    
    1455
    -depsAbiMismatch pkg_map pkg = map fst . filter (not . abiMatch) $ unitAbiDepends pkg
    
    1456
    -  where
    
    1457
    -    abiMatch (dep_uid, abi)
    
    1458
    -        | Just dep_pkg <- lookupUniqMap pkg_map dep_uid
    
    1459
    -        = unitAbiHash dep_pkg == abi
    
    1460
    -        | otherwise
    
    1461
    -        = False
    
    1462
    -
    
    1463
    --- -----------------------------------------------------------------------------
    
    1464
    --- Ignore units
    
    1465
    -
    
    1466
    -ignoreUnits :: [IgnorePackageFlag] -> [UnitInfo] -> UnusableUnits
    
    1467
    -ignoreUnits flags pkgs = listToUniqMap (concatMap doit flags)
    
    1468
    -  where
    
    1469
    -  doit (IgnorePackage str) =
    
    1470
    -     case partition (matchingStr str) pkgs of
    
    1471
    -         (ps, _) -> [ (unitId p, (p, IgnoredWithFlag))
    
    1472
    -                    | p <- ps ]
    
    1473
    -        -- missing unit is not an error for -ignore-package,
    
    1474
    -        -- because a common usage is to -ignore-package P as
    
    1475
    -        -- a preventative measure just in case P exists.
    
    1476
    -
    
    1477
    --- ----------------------------------------------------------------------------
    
    1478
    ---
    
    1479
    --- Merging databases
    
    1480
    ---
    
    1481
    -
    
    1482
    --- | For each unit, a mapping from uid -> i indicates that this
    
    1483
    --- unit was brought into GHC by the ith @-package-db@ flag on
    
    1484
    --- the command line.  We use this mapping to make sure we prefer
    
    1485
    --- units that were defined later on the command line, if there
    
    1486
    --- is an ambiguity.
    
    1487
    -type UnitPrecedenceMap = UniqMap UnitId Int
    
    1488
    -
    
    1489
    --- | Given a list of databases, merge them together, where
    
    1490
    --- units with the same unit id in later databases override
    
    1491
    --- earlier ones.  This does NOT check if the resulting database
    
    1492
    --- makes sense (that's done by 'validateDatabase').
    
    1493
    -mergeDatabases :: Logger -> [UnitDatabase UnitId]
    
    1494
    -               -> IO (UnitInfoMap, UnitPrecedenceMap)
    
    1495
    -mergeDatabases logger = foldM merge (emptyUniqMap, emptyUniqMap) . zip [1..]
    
    1496
    -  where
    
    1497
    -    merge (pkg_map, prec_map) (i, UnitDatabase db_path db) = do
    
    1498
    -      debugTraceMsg logger 2 $
    
    1499
    -          text "loading package database" <+> ppr db_path
    
    1500
    -      when (logVerbAtLeast logger 2) $
    
    1501
    -        forM_ (Set.toList override_set) $ \pkg ->
    
    1502
    -            debugTraceMsg logger 2 $
    
    1503
    -                text "package" <+> ppr pkg <+>
    
    1504
    -                text "overrides a previously defined package"
    
    1505
    -      return (pkg_map', prec_map')
    
    1506
    -     where
    
    1507
    -      db_map = mk_pkg_map db
    
    1508
    -      mk_pkg_map = listToUniqMap . map (\p -> (unitId p, p))
    
    1509
    -
    
    1510
    -      -- The set of UnitIds which appear in both db and pkgs.  These are the
    
    1511
    -      -- ones that get overridden.  Compute this just to give some
    
    1512
    -      -- helpful debug messages at -v2
    
    1513
    -      override_set :: Set UnitId
    
    1514
    -      override_set = Set.intersection (nonDetUniqMapToKeySet db_map)
    
    1515
    -                                      (nonDetUniqMapToKeySet pkg_map)
    
    1516
    -
    
    1517
    -      -- Now merge the sets together (NB: in case of duplicate,
    
    1518
    -      -- first argument preferred)
    
    1519
    -      pkg_map' :: UnitInfoMap
    
    1520
    -      pkg_map' = pkg_map `plusUniqMap` db_map
    
    1521
    -
    
    1522
    -      prec_map' :: UnitPrecedenceMap
    
    1523
    -      prec_map' = prec_map `plusUniqMap` (mapUniqMap (const i) db_map)
    
    1524
    -
    
    1525
    --- | Validates a database, removing unusable units from it
    
    1526
    --- (this includes removing units that the user has explicitly
    
    1527
    --- ignored.)  Our general strategy:
    
    1528
    ---
    
    1529
    --- 1. Remove all broken units (dangling dependencies)
    
    1530
    --- 2. Remove all units that are cyclic
    
    1531
    --- 3. Apply ignore flags
    
    1532
    --- 4. Remove all units which have deps with mismatching ABIs
    
    1533
    ---
    
    1534
    -validateDatabase :: UnitConfig -> UnitInfoMap
    
    1535
    -                 -> (UnitInfoMap, UnusableUnits, [SCC UnitInfo])
    
    1536
    -validateDatabase cfg pkg_map1 =
    
    1537
    -    (pkg_map5, unusable, sccs)
    
    1538
    -  where
    
    1539
    -    ignore_flags = reverse (unitConfigFlagsIgnored cfg)
    
    1540
    -
    
    1541
    -    -- Compute the reverse dependency index
    
    1542
    -    index = reverseDeps pkg_map1
    
    1543
    -
    
    1544
    -    -- Helper function
    
    1545
    -    mk_unusable mk_err dep_matcher m uids =
    
    1546
    -      listToUniqMap [ (unitId pkg, (pkg, mk_err (dep_matcher m pkg)))
    
    1547
    -                    | pkg <- uids
    
    1548
    -                    ]
    
    1549
    -
    
    1550
    -    -- Find broken units
    
    1551
    -    directly_broken = filter (not . null . depsNotAvailable pkg_map1)
    
    1552
    -                             (nonDetEltsUniqMap pkg_map1)
    
    1553
    -    (pkg_map2, broken) = removeUnits (map unitId directly_broken) index pkg_map1
    
    1554
    -    unusable_broken = mk_unusable BrokenDependencies depsNotAvailable pkg_map2 broken
    
    1555
    -
    
    1556
    -    -- Find recursive units
    
    1557
    -    sccs = stronglyConnComp [ (pkg, unitId pkg, unitDepends pkg)
    
    1558
    -                            | pkg <- nonDetEltsUniqMap pkg_map2 ]
    
    1559
    -    getCyclicSCC (CyclicSCC vs) = map unitId vs
    
    1560
    -    getCyclicSCC (AcyclicSCC _) = []
    
    1561
    -    (pkg_map3, cyclic) = removeUnits (concatMap getCyclicSCC sccs) index pkg_map2
    
    1562
    -    unusable_cyclic = mk_unusable CyclicDependencies depsNotAvailable pkg_map3 cyclic
    
    1563
    -
    
    1564
    -    -- Apply ignore flags
    
    1565
    -    directly_ignored = ignoreUnits ignore_flags (nonDetEltsUniqMap pkg_map3)
    
    1566
    -    (pkg_map4, ignored) = removeUnits (nonDetKeysUniqMap directly_ignored) index pkg_map3
    
    1567
    -    unusable_ignored = mk_unusable IgnoredDependencies depsNotAvailable pkg_map4 ignored
    
    1568
    -
    
    1569
    -    -- Knock out units whose dependencies don't agree with ABI
    
    1570
    -    -- (i.e., got invalidated due to shadowing)
    
    1571
    -    directly_shadowed = filter (not . null . depsAbiMismatch pkg_map4)
    
    1572
    -                               (nonDetEltsUniqMap pkg_map4)
    
    1573
    -    (pkg_map5, shadowed) = removeUnits (map unitId directly_shadowed) index pkg_map4
    
    1574
    -    unusable_shadowed = mk_unusable ShadowedDependencies depsAbiMismatch pkg_map5 shadowed
    
    1575
    -
    
    1576
    -    -- combine all unusables. The order is important for shadowing.
    
    1577
    -    -- plusUniqMapList folds using plusUFM which is right biased (opposite of
    
    1578
    -    -- Data.Map.union) so the head of the list should be the least preferred
    
    1579
    -    unusable = plusUniqMapList [ unusable_shadowed
    
    1580
    -                               , unusable_cyclic
    
    1581
    -                               , unusable_broken
    
    1582
    -                               , unusable_ignored
    
    1583
    -                               , directly_ignored
    
    1584
    -                               ]
    
    1585 739
     
    
    1586 740
     -- -----------------------------------------------------------------------------
    
    1587 741
     -- When all the command-line options are in, we can process our unit
    
    ... ... @@ -1646,7 +800,7 @@ mkUnitState logger unit_index cfg = do
    1646 800
               we build a mapping saying what every in scope module name points to.
    
    1647 801
     -}
    
    1648 802
     
    
    1649
    -  raw_dbs <- readUnitDatabases logger cfg
    
    803
    +  raw_dbs <- readUnitDatabases logger (initUnitDbConfig cfg)
    
    1650 804
     
    
    1651 805
       -- distrust all units if the flag is set
    
    1652 806
       let unitsOf db = Set.fromList $ map unitId (unitDatabaseUnits db)
    
    ... ... @@ -1669,14 +823,14 @@ mkUnitState logger unit_index cfg = do
    1669 823
       debugTraceMsg logger 2 $
    
    1670 824
           text "package flags" <+> ppr other_flags
    
    1671 825
     
    
    1672
    -  let home_unit_deps = selectHomeUnits (unitConfigHomeUnits cfg) hpt_flags
    
    826
    +  let !home_unit_deps = selectHomeUnits (unitConfigHomeUnits cfg) hpt_flags
    
    1673 827
     
    
    1674 828
       -- Merge databases together, without checking validity
    
    1675 829
       (pkg_map1, prec_map) <- mergeDatabases logger dbs
    
    1676 830
     
    
    1677 831
       -- Now that we've merged everything together, prune out unusable
    
    1678 832
       -- packages.
    
    1679
    -  let (pkg_map2, unusable, sccs) = validateDatabase cfg pkg_map1
    
    833
    +  let (pkg_map2, unusable, sccs) = validateDatabase (unitConfigFlagsIgnored cfg) pkg_map1
    
    1680 834
     
    
    1681 835
       reportCycles   logger sccs
    
    1682 836
       reportUnusable logger unusable
    
    ... ... @@ -1725,12 +879,12 @@ mkUnitState logger unit_index cfg = do
    1725 879
                                 -- Note: we NEVER expose indefinite packages by
    
    1726 880
                                 -- default, because it's almost assuredly not
    
    1727 881
                                 -- what you want (no mix-in linking has occurred).
    
    1728
    -                            if unitIsExposed p && unitIsDefinite (mkUnit p) && mostPreferable p
    
    882
    +                            let !x = fsPackageName p in if unitIsExposed p && unitIsDefinite (mkUnit p) && mostPreferable p
    
    1729 883
                                    then addToUniqMap vm (mkUnit p)
    
    1730 884
                                                    UnitVisibility {
    
    1731 885
                                                      uv_expose_all = True,
    
    1732 886
                                                      uv_renamings = [],
    
    1733
    -                                                 uv_package_name = First (Just (fsPackageName p)),
    
    887
    +                                                 uv_package_name = First (Just x),
    
    1734 888
                                                      uv_requirements = emptyUniqMap,
    
    1735 889
                                                      uv_explicit = Nothing
    
    1736 890
                                                    }
    
    ... ... @@ -1760,9 +914,9 @@ mkUnitState logger unit_index cfg = do
    1760 914
             modifyIORef' unit_index (setWireMap wmap)
    
    1761 915
             pure wmap
    
    1762 916
           else do
    
    1763
    -        pure $ ui_wireMap ui
    
    917
    +        pure $ wiringMap ui
    
    1764 918
     
    
    1765
    -    let all_pkgs = updateWiredInUnits wireMap (ui_unitInfoMap ui) pkgs1
    
    919
    +    let all_pkgs = updateWiredInUnits wireMap (globalUnits ui) pkgs1
    
    1766 920
             (new_pkgs, _pkgs_set) = partitionEithers all_pkgs
    
    1767 921
         modifyIORef' unit_index (addUnitInfoMap $ mkUnitInfoMap new_pkgs)
    
    1768 922
         pure (wireMap, map (either id id) all_pkgs)
    
    ... ... @@ -1853,13 +1007,22 @@ mkUnitState logger unit_index cfg = do
    1853 1007
              , moduleNameProvidersMap       = mod_map
    
    1854 1008
              , pluginModuleNameProvidersMap = mkModuleNameProvidersMap logger cfg pkg_db plugin_vis_map
    
    1855 1009
              , packageNameMap               = pkgname_map
    
    1856
    -        --  , wireMap                      = wired_map
    
    1857
    -        --  , unwireMap                    = listToUniqMap [ (v,k) | (k,v) <- nonDetUniqMapToList wired_map ]
    
    1858 1010
              , requirementContext           = req_ctx
    
    1859 1011
              , allowVirtualUnits            = unitConfigAllowVirtual cfg
    
    1860 1012
              }
    
    1861 1013
       return state
    
    1862 1014
     
    
    1015
    +initUnitDbConfig :: UnitConfig -> UnitDbConfig
    
    1016
    +initUnitDbConfig uc = UnitDbConfig
    
    1017
    +  { unitDbConfigFlagsDB = unitConfigFlagsDB uc
    
    1018
    +  , unitDbConfigProgramName = unitConfigProgramName uc
    
    1019
    +  , unitDbConfigDBName = unitConfigDBName uc
    
    1020
    +  , unitDbConfigPlatformArchOS = unitConfigPlatformArchOS uc
    
    1021
    +  , unitDbConfigGlobalDB = unitConfigGlobalDB uc
    
    1022
    +  , unitDbConfigGHCDir = unitConfigGHCDir uc
    
    1023
    +  , unitDbConfigDBCache = unitConfigDBCache uc
    
    1024
    +  }
    
    1025
    +
    
    1863 1026
     selectHptFlag :: Set.Set UnitId -> PackageFlag -> Bool
    
    1864 1027
     selectHptFlag home_units (ExposePackage _ (UnitIdArg uid) _) | toUnitId uid `Set.member` home_units = True
    
    1865 1028
     selectHptFlag _ _ = False
    
    ... ... @@ -1872,12 +1035,11 @@ selectHomeUnits home_units flags = foldl' go Set.empty flags
    1872 1035
         -- MP: This does not yet support thinning/renaming
    
    1873 1036
         go cur _ = cur
    
    1874 1037
     
    
    1875
    -
    
    1876 1038
     -- | Given a wired-in 'Unit', "unwire" it into the 'Unit'
    
    1877 1039
     -- that it was recorded as in the package database.
    
    1878 1040
     unwireUnit :: UnitIndex -> Unit -> Unit
    
    1879 1041
     unwireUnit state uid@(RealUnit (Definite def_uid)) =
    
    1880
    -    maybe uid (RealUnit . Definite) (lookupUniqMap (ui_unwireMap state) def_uid)
    
    1042
    +    maybe uid (RealUnit . Definite) (lookupUniqMap (unwiringMap state) def_uid)
    
    1881 1043
     unwireUnit _ uid = uid
    
    1882 1044
     
    
    1883 1045
     -- -----------------------------------------------------------------------------
    
    ... ... @@ -2164,7 +1326,7 @@ lookupModuleWithSuggestions' pkgs mod_map name mb_pn
    2164 1326
         suggestions = fuzzyLookup (moduleNameString name) all_mods
    
    2165 1327
     
    
    2166 1328
         all_mods :: [(String, ModuleSuggestion)]     -- All modules
    
    2167
    -    all_mods = sortBy (comparing fst) $
    
    1329
    +    all_mods = sortOn fst $
    
    2168 1330
             [ (moduleNameString m, suggestion)
    
    2169 1331
             | (m, e) <- nonDetUniqMapToList (moduleNameProvidersMap pkgs)
    
    2170 1332
             , suggestion <- map (getSuggestion m) (nonDetUniqMapToList e)
    
    ... ... @@ -2307,17 +1469,6 @@ pprUnitsSimple ue = pprUnitsWith pprIPI ue
    2307 1469
                                t = if isUnitInfoTrusted ue ipi then text "T" else text " "
    
    2308 1470
                            in e <> t <> text "  " <> ftext i
    
    2309 1471
     
    
    2310
    --- | Show the mapping of modules to where they come from.
    
    2311
    -pprModuleMap :: ModuleNameProvidersMap -> SDoc
    
    2312
    -pprModuleMap mod_map =
    
    2313
    -  vcat (map pprLine (nonDetUniqMapToList mod_map))
    
    2314
    -    where
    
    2315
    -      pprLine (m,e) = ppr m $$ nest 50 (vcat (map (pprEntry m) (nonDetUniqMapToList e)))
    
    2316
    -      pprEntry :: Outputable a => ModuleName -> (Module, a) -> SDoc
    
    2317
    -      pprEntry m (m',o)
    
    2318
    -        | m == moduleName m' = ppr (moduleUnit m') <+> parens (ppr o)
    
    2319
    -        | otherwise = ppr m' <+> parens (ppr o)
    
    2320
    -
    
    2321 1472
     fsPackageName :: UnitInfo -> FastString
    
    2322 1473
     fsPackageName info = fs
    
    2323 1474
        where
    

  • compiler/GHC/Unit/State.hs-boot
    1 1
     module GHC.Unit.State where
    
    2 2
     
    
    3 3
     data UnitState
    4
    -data ModuleSuggestion
    
    5
    -data ModuleOrigin
    
    6
    -data UnusableUnit

  • compiler/GHC/Unit/Types.hs
    ... ... @@ -578,7 +578,7 @@ had used @-ignore-package@).
    578 578
     The affected packages are compiled with, e.g., @-this-unit-id base@, so that
    
    579 579
     the symbols in the object files have the unversioned unit id in their name.
    
    580 580
     
    
    581
    -Make sure you change 'GHC.Unit.State.findWiredInUnits' if you add an entry here.
    
    581
    +Make sure you change 'wiredInUnitIds' if you add an entry here.
    
    582 582
     
    
    583 583
     -}
    
    584 584
     
    

  • compiler/ghc.cabal.in
    ... ... @@ -968,6 +968,12 @@ Library
    968 968
             GHC.Unit.Env
    
    969 969
             GHC.Unit.External
    
    970 970
             GHC.Unit.External.Database
    
    971
    +        GHC.Unit.External.Index
    
    972
    +        GHC.Unit.External.ModuleOrigin
    
    973
    +        GHC.Unit.External.Providers
    
    974
    +        GHC.Unit.External.Validate
    
    975
    +        GHC.Unit.External.Visibility
    
    976
    +        GHC.Unit.External.Wired
    
    971 977
             GHC.Unit.Finder
    
    972 978
             GHC.Unit.Finder.Types
    
    973 979
             GHC.Unit.Home
    

  • ghc/GHCi/UI.hs
    ... ... @@ -855,8 +855,9 @@ installInteractiveHomeUnits dflags = do
    855 855
         setupHomeUnitFor :: GHC.GhcMonad m => Logger -> DynFlags -> S.Set UnitId -> m HomeUnitEnv
    
    856 856
         setupHomeUnitFor logger dflags all_home_units = do
    
    857 857
           env <- GHC.getSession
    
    858
    +      let unit_index = hsc_unit_index env
    
    858 859
           (unit_state,home_unit,_mconstants) <-
    
    859
    -        liftIO $ initUnits logger dflags (hscEUDC env) all_home_units
    
    860
    +        liftIO $ initUnits logger dflags unit_index (hscEUDC env) all_home_units
    
    860 861
           hpt <- liftIO emptyHomePackageTable
    
    861 862
           pure (HUG.mkHomeUnitEnv unit_state dflags hpt (Just home_unit))
    
    862 863
     
    

  • libraries/ghc-boot/GHC/Unit/Database.hs
    ... ... @@ -746,11 +746,20 @@ mungeUnitInfoPaths top_dir pkgroot pkg =
    746 746
           , unitHaddockHTMLs        = munge_paths (munge_urls (unitHaddockHTMLs pkg))
    
    747 747
           }
    
    748 748
        where
    
    749
    -      munge_paths = map munge_path
    
    750
    -      munge_urls  = map munge_url
    
    749
    +      munge_paths = strictMap munge_path
    
    750
    +      munge_urls  = strictMap munge_url
    
    751 751
           (munge_path,munge_url) = mkMungePathUrl top_dir pkgroot
    
    752 752
     
    
    753 753
     -- | Decode an 'OsPath' to 'FilePath', throwing an 'error' if decoding failed.
    
    754 754
     -- Prefer 'decodeUtf' and gracious error handling.
    
    755 755
     unsafeDecodeUtf :: HasCallStack => OsPath -> FilePath
    
    756 756
     unsafeDecodeUtf = OsPath.Internal.so
    
    757
    +
    
    758
    +strictMap :: (a -> b) -> [a] -> [b]
    
    759
    +strictMap _ []     = []
    
    760
    +strictMap f (x:xs) =
    
    761
    +  let
    
    762
    +    !x' = f x
    
    763
    +    !xs' = strictMap f xs
    
    764
    +  in
    
    765
    +    x' : xs'

  • utils/haddock/haddock-api/src/Haddock.hs
    ... ... @@ -260,7 +260,9 @@ haddockWithGhc ghc args = handleTopExceptions $ do
    260 260
         logger' <- getLogger
    
    261 261
         let logger = setLogFlags logger' (initLogFlags dflags)
    
    262 262
         let parserOpts = Parser.initParserOpts dflags
    
    263
    -    !unit_state <- hsc_units <$> getSession
    
    263
    +    env <- getSession
    
    264
    +    let !unit_state = hsc_units env
    
    265
    +    !unit_index <- liftIO $ hscUnitIndex env
    
    264 266
     
    
    265 267
         -- If any --show-interface was used, show the given interfaces
    
    266 268
         forM_ (optShowInterfaceFile flags) $ \path -> liftIO $ do
    
    ... ... @@ -287,7 +289,7 @@ haddockWithGhc ghc args = handleTopExceptions $ do
    287 289
               }
    
    288 290
     
    
    289 291
           -- Render the interfaces.
    
    290
    -      liftIO $ renderStep dflags parserOpts logger unit_state flags sinceQual qual concSem packages ifaces
    
    292
    +      liftIO $ renderStep dflags parserOpts logger unit_index unit_state flags sinceQual qual concSem packages ifaces
    
    291 293
     
    
    292 294
         -- If we were not given any input files, error if documentation was
    
    293 295
         -- requested
    
    ... ... @@ -300,7 +302,7 @@ haddockWithGhc ghc args = handleTopExceptions $ do
    300 302
           packages <- liftIO $ readInterfaceFiles name_cache (readIfaceArgs flags) noChecks
    
    301 303
     
    
    302 304
           -- Render even though there are no input files (usually contents/index).
    
    303
    -      liftIO $ renderStep dflags parserOpts logger unit_state flags sinceQual qual concSem packages []
    
    305
    +      liftIO $ renderStep dflags parserOpts logger unit_index unit_state flags sinceQual qual concSem packages []
    
    304 306
     
    
    305 307
     -- | Run the GHC action using a temporary output directory
    
    306 308
     withTempOutputDir :: Ghc a -> Ghc a
    
    ... ... @@ -356,6 +358,7 @@ renderStep
    356 358
       :: DynFlags
    
    357 359
       -> ParserOpts
    
    358 360
       -> Logger
    
    361
    +  -> UnitIndex
    
    359 362
       -> UnitState
    
    360 363
       -> [Flag]
    
    361 364
       -> SinceQual
    
    ... ... @@ -364,7 +367,7 @@ renderStep
    364 367
       -> [(DocPaths, Visibility, FilePath, InterfaceFile)]
    
    365 368
       -> [Interface]
    
    366 369
       -> IO ()
    
    367
    -renderStep dflags parserOpts logger unit_state flags sinceQual nameQual concSem pkgs interfaces = do
    
    370
    +renderStep dflags parserOpts logger unit_index unit_state flags sinceQual nameQual concSem pkgs interfaces = do
    
    368 371
       updateHTMLXRefs (map (\(docPath, _ifaceFilePath, _showModules, ifaceFile) ->
    
    369 372
                               ( case baseUrl flags of
    
    370 373
                                   Nothing  -> docPathsHtml docPath
    
    ... ... @@ -380,7 +383,7 @@ renderStep dflags parserOpts logger unit_state flags sinceQual nameQual concSem
    380 383
           (DocPaths {docPathsSources=Just path}, _, _, ifile) <- pkgs
    
    381 384
           iface <- ifInstalledIfaces ifile
    
    382 385
           return (instMod iface, path)
    
    383
    -  render dflags parserOpts logger unit_state flags sinceQual nameQual concSem interfaces installedIfaces extSrcMap
    
    386
    +  render dflags parserOpts logger unit_index unit_state flags sinceQual nameQual concSem interfaces installedIfaces extSrcMap
    
    384 387
       where
    
    385 388
         -- get package name from unit-id
    
    386 389
         packageName :: Unit -> String
    
    ... ... @@ -394,6 +397,7 @@ render
    394 397
       :: DynFlags
    
    395 398
       -> ParserOpts
    
    396 399
       -> Logger
    
    400
    +  -> UnitIndex
    
    397 401
       -> UnitState
    
    398 402
       -> [Flag]
    
    399 403
       -> SinceQual
    
    ... ... @@ -403,7 +407,7 @@ render
    403 407
       -> [(FilePath, PackageInterfaces)]
    
    404 408
       -> Map Module FilePath
    
    405 409
       -> IO ()
    
    406
    -render dflags parserOpts logger unit_state flags sinceQual qual concSem ifaces packages extSrcMap = do
    
    410
    +render dflags parserOpts logger unit_index unit_state flags sinceQual qual concSem ifaces packages extSrcMap = do
    
    407 411
       let
    
    408 412
         packageInfo = PackageInfo { piPackageName    = fromMaybe (PackageName mempty)
    
    409 413
                                                      $ optPackageName flags
    
    ... ... @@ -505,7 +509,7 @@ render dflags parserOpts logger unit_state flags sinceQual qual concSem ifaces p
    505 509
         -- records the *wired in* identity base.  So untranslate it
    
    506 510
         -- so that we can service the request.
    
    507 511
         unwire :: Module -> Module
    
    508
    -    unwire m = m { moduleUnit = unwireUnit unit_state (moduleUnit m) }
    
    512
    +    unwire m = m { moduleUnit = unwireUnit unit_index (moduleUnit m) }
    
    509 513
     
    
    510 514
       reexportedIfaces <- concat `fmap` (for (reexportFlags flags) $ \mod_str -> do
    
    511 515
         let warn' = hPutStrLn stderr . ("Warning: " ++)