Hannes Siebenhandl pushed to branch wip/fendor/external-unit-db-cache at Glasgow Haskell Compiler / GHC
Commits:
21 changed files:
- compiler/GHC.hs
- compiler/GHC/Driver/Backpack.hs
- compiler/GHC/Driver/Env.hs
- compiler/GHC/Driver/Session/Units.hs
- compiler/GHC/Types/Unique.hs
- compiler/GHC/Unit/Env.hs
- compiler/GHC/Unit/External/Database.hs
- + compiler/GHC/Unit/External/Index.hs
- + compiler/GHC/Unit/External/ModuleOrigin.hs
- + compiler/GHC/Unit/External/Providers.hs
- + compiler/GHC/Unit/External/Validate.hs
- + compiler/GHC/Unit/External/Visibility.hs
- + compiler/GHC/Unit/External/Wired.hs
- compiler/GHC/Unit/Info.hs
- compiler/GHC/Unit/State.hs
- compiler/GHC/Unit/State.hs-boot
- compiler/GHC/Unit/Types.hs
- compiler/ghc.cabal.in
- ghc/GHCi/UI.hs
- libraries/ghc-boot/GHC/Unit/Database.hs
- utils/haddock/haddock-api/src/Haddock.hs
Changes:
| ... | ... | @@ -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
|
| ... | ... | @@ -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 |
| ... | ... | @@ -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 | --------------------------------------------------------------------------------
|
| ... | ... | @@ -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
|
| ... | ... | @@ -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
|
| ... | ... | @@ -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
|
| ... | ... | @@ -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 |
| 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 |
| 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 |
| 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) |
| 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 |
| 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 | + |
| 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 |
| ... | ... | @@ -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 |
| ... | ... | @@ -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
|
| 1 | 1 | module GHC.Unit.State where
|
| 2 | 2 | |
| 3 | 3 | data UnitState |
| 4 | -data ModuleSuggestion
|
|
| 5 | -data ModuleOrigin
|
|
| 6 | -data UnusableUnit |
| ... | ... | @@ -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 |
| ... | ... | @@ -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
|
| ... | ... | @@ -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 |
| ... | ... | @@ -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' |
| ... | ... | @@ -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: " ++)
|