ghc-9.14.1.20260916: The GHC API
Safe HaskellNone
LanguageGHC2021

GHC.Unit.External.Index

Description

The UnitIndex is a UnitEnv wide data structure that shares external unit information across the UnitState of all home units (e.g., HomeUnitEnv) in a particular UnitEnv.

It caches already read unit databases, all processed UnitInfos and the WireMap.

This module is meant to be imported as Index.

A short overview of how the different types here related to UnitState, UnitEnv and the HomeUnitEnv.

┌─────────┐ │ UnitEnv │ └────┬────┘ ├───────────────────────┐ │ │ ┌────▼──────┐ ┌─────▼─────┐ │HomeUnitEnv│ │ UnitIndex ├────────────────┐ └────┬──────┘ └───────────┘ │ │ │ │ Reads cached unit DBs │ ┌────▼──────┐ ┌─────────────────────┐ │ │ UnitState ├──────────>ExternalUnitDatabases◄──────┤ └────┬──┬───┘ └─────────────────────┘ │ │ └───────────────────────┐ │ │ Writes new UnitInfos │ │ │ during initialisation │ │ ┌────▼────────┐ ┌────────v──────────┐ │ │ UnitInfoMap │ │ GlobalUnitInfoMap ◄────────┘ └────┬────────┘ └────────^──────────┘ │ │ └──────────────────────────┘ UnitInfoMap references GlobalUnitInfoMap values (All UnitInfos are shared)

Open arrow A ───> B: A uses B. Closed arrow A ◄─── B: A is a field of B.

Also, see Note [Sharing UnitInfos across the UnitEnv] for more technical discussion about sharing UnitInfos.

Synopsis

The UnitIndexCache.

newtype UnitIndexCache Source #

Mutable version of UnitIndex.

The UnitIndexCache ensures that all calls to initUnits will share the UnitInfo if it is possible.

To share the UnitInfo, the UnitInfo needs to be fully-resolved, i.e., its wired-in dependencies and modules need to be replaced with the UnitId of the wired-in unit. Thus, the UnitIndexCache caches both the global WireMap and the UnitInfoMap.

The WireMap is globally valid, as other parts of the compiler rely on the fact that only one instance of wired-in units is used.

Memory Invariant: The UnitIndexCache is the root object for retaining fully-resolved UnitInfo. UnitState is expected to reference only UnitInfos from the UnitIndexCache. There is exactly one fully-resolved UnitInfo alive for each external unit per unit database.

A second instance may or may not be stored in the externalUnitDatabases, which represent the in-memory cache of the on-disk unit databases.

Constructors

UnitIndexCache 

UnitIndex

data UnitIndex Source #

Global index for external units that can be shared across multiple HomeUnitEnvs.

Allows sharing of the WireMap and UnitInfos that are stored in the UnitState of each HomeUnitEnv.

See Note [Sharing UnitInfos across the UnitEnv] for details about memory usage.

wiringMap :: UnitIndex -> WireMap Source #

Get the WireMap.

At the moment, the WireMap is global, there can only be one version of a wired-in package.

unwiringMap :: UnitIndex -> UnwireMap Source #

Get the UnwireMap.

At the moment, the UnwireMap is global, there can only be one version of a wired-in package.

globalUnits :: UnitIndex -> GlobalUnitInfoMap Source #

Access the global map of fully-resolved UnitInfos.

A UnitInfo is fully-resolved, if its dependencies were updated to reference the wired-in packages (e.g., wiringMap) and the wired-in packages are updated. Further, the UnitInfo is based on the ExternalUnitDatabases results, resolving variables such as ${pkgroot} in paths.

See Note [Sharing UnitInfos across the UnitEnv] for why this is helpful.

externalUnitDatabases :: UnitIndex -> ExternalUnitDatabases UnitId Source #

Access the already processed unit databases.

setWireMap :: WireMap -> UnitIndex -> UnitIndex Source #

Set the WireMap of UnitIndex. Automatically computes the UnwireMap based on the WireMap.

wireMapExists :: UnitIndex -> Bool Source #

Is there already a WireMap in this UnitIndex?

GlobalUnitInfoMap

data GlobalUnitInfoMap Source #

Like a UnitInfoMap but stores all UnitInfos.

It is keyed by the UnitId and the UnitInfos UnitAbiHash. In modern cabal, there should never be a conflict of UnitIds, as cabal hashes the Abi, dependency hashes, source hashes and more.

However, a user can choose a conflicting UnitId, causing a conflict after all. We use the UnitAbiHash for disambiguation. If both UnitId and UnitAbiHash are identical in separate unit databases, we can assume they are the same unit, according to the documentation of GHC.

lookupGlobalUnitInfoMap :: GlobalUnitKey -> GlobalUnitInfoMap -> Maybe UnitInfo Source #

Lookup the UnitInfo in the GlobalUnitInfoMap.

This does not check whether the GlobalUnitKey refers to a unit that needs to be resolved in the WireMap. For example, if the UnitId is ghc-internal-version (and ghc-internal is a wired-in package), then lookupGlobalUnitInfoMap won't find it, as in the GlobalUnitInfoMap, the key is ghc-internal.

GlobalUnitKey

data GlobalUnitKey Source #

A GlobalUnitKey is a key that can globally identify a UnitInfo, not just in the UnitInfoMap.

The UnitId and UnitAbiHash uniquely identify a UnitInfo.

Wired-in units

setupWiredInUnits :: Logger -> UnitPrecedenceMap -> [UnitInfo] -> VisibilityMap -> UnitIndexCache -> IO WireMap Source #

Find the wired-in units in the given '[UnitInfo]' if there isn't already one in the UnitIndexCache. If there is, simply return the existing WireMap. Otherwise, update the wiringMap in the UnitIndexCache

updateWiredInUnitIndex :: WireMap -> [UnitInfo] -> UnitIndexCache -> IO [UnitInfo] Source #

Resolve the wired-in units in the '[UnitInfo]'. If the fully-resolved can be found in UnitIndexCache, then we use it. If the resolved UnitInfo is new, we immediately cache it in the UnitIndexCache. We return the fully-resolved UnitInfo list in the same order as provided.

unwireUnit :: UnitIndex -> Unit -> Unit Source #

Given a wired-in Unit, "unwire" it into the Unit that it was recorded as in the package database.

Reading external unit databases into the UnitIndexCache

readOrGetUnitDatabase :: Logger -> UnitIndexCache -> UnitDbConfig -> OsPath -> IO (UnitDatabase UnitId) Source #

Get the cached UnitDatabase or read the UnitDatabase at the given location.