GHC.Unit.State

ghc-lib-parser-9.14.1.20251220: The GHC API, decoupled from GHC versions

Safe Haskell | Ignore
Language | GHC2021

GHC.Unit.State

Contents

- Reading the package config, and processing cmdline args
- Querying the package config
- Module hole substitution
- Pretty-printing
- Utils

Description

Unit manipulation

Synopsis

- module GHC.Unit.Info
- data UnitState = UnitState {
  - unitInfoMap :: UnitInfoMap
  - preloadClosure :: PreloadUnitClosure
  - packageNameMap :: UniqFM PackageName UnitId
  - wireMap :: UniqMap UnitId UnitId
  - unwireMap :: UniqMap UnitId UnitId
  - preloadUnits :: [UnitId]
  - explicitUnits :: [(Unit, Maybe PackageArg)]
  - homeUnitDepends :: [UnitId]
  - moduleNameProvidersMap :: !ModuleNameProvidersMap
  - pluginModuleNameProvidersMap :: !ModuleNameProvidersMap
  - requirementContext :: UniqMap ModuleName [InstantiatedModule]
  - allowVirtualUnits :: !Bool
  }
- type PreloadUnitClosure = UniqSet UnitId
- data UnitDatabase unit = UnitDatabase {
  - unitDatabasePath :: FilePath
  - unitDatabaseUnits :: [GenUnitInfo unit]
  }
- data UnitErr
  - = CloseUnitErr !UnitId !(Maybe UnitId)
  - | PackageFlagErr !PackageFlag ![(UnitInfo, UnusableUnitReason)]
  - | TrustFlagErr !TrustFlag ![(UnitInfo, UnusableUnitReason)]
- emptyUnitState :: UnitState
- initUnits :: Logger -> DynFlags -> Maybe [UnitDatabase UnitId] -> Set UnitId -> IO ([UnitDatabase UnitId], UnitState, HomeUnit, Maybe PlatformConstants)
- readUnitDatabases :: Logger -> UnitConfig -> IO [UnitDatabase UnitId]
- readUnitDatabase :: Logger -> UnitConfig -> FilePath -> IO (UnitDatabase UnitId)
- getUnitDbRefs :: UnitConfig -> IO [PkgDbRef]
- resolveUnitDatabase :: UnitConfig -> PkgDbRef -> IO (Maybe FilePath)
- listUnitInfo :: UnitState -> [UnitInfo]
- type UnitInfoMap = UniqMap UnitId UnitInfo
- lookupUnit :: UnitState -> Unit -> Maybe UnitInfo
- lookupUnit' :: Bool -> UnitInfoMap -> PreloadUnitClosure -> Unit -> Maybe UnitInfo
- unsafeLookupUnit :: HasDebugCallStack => UnitState -> Unit -> UnitInfo
- lookupUnitId :: UnitState -> UnitId -> Maybe UnitInfo
- lookupUnitId' :: UnitInfoMap -> UnitId -> Maybe UnitInfo
- unsafeLookupUnitId :: HasDebugCallStack => UnitState -> UnitId -> UnitInfo
- lookupPackageName :: UnitState -> PackageName -> Maybe UnitId
- resolvePackageImport :: UnitState -> ModuleName -> PackageName -> Maybe UnitId
- improveUnit :: UnitState -> Unit -> Unit
- searchPackageId :: UnitState -> PackageId -> [UnitInfo]
- listVisibleModuleNames :: UnitState -> [ModuleName]
- lookupModuleInAllUnits :: UnitState -> ModuleName -> [(Module, UnitInfo)]
- lookupModuleWithSuggestions :: UnitState -> ModuleName -> PkgQual -> LookupResult
- lookupModulePackage :: UnitState -> ModuleName -> PkgQual -> Maybe [UnitInfo]
- lookupPluginModuleWithSuggestions :: UnitState -> ModuleName -> PkgQual -> LookupResult
- requirementMerges :: UnitState -> ModuleName -> [InstantiatedModule]
- data LookupResult
  - = LookupFound Module (UnitInfo, ModuleOrigin)
  - | LookupMultiple [(Module, ModuleOrigin)]
  - | LookupHidden [(Module, ModuleOrigin)] [(Module, ModuleOrigin)]
  - | LookupUnusable [(Module, ModuleOrigin)]
  - | LookupNotFound [ModuleSuggestion]
- data ModuleSuggestion
  - = SuggestVisible ModuleName Module ModuleOrigin
  - | SuggestHidden ModuleName Module ModuleOrigin
- data ModuleOrigin
  - = ModHidden
  - | ModUnusable !UnusableUnit
  - | ModOrigin {
    - fromOrigUnit :: Maybe Bool
    - fromExposedReexport :: [UnitInfo]
    - fromHiddenReexport :: [UnitInfo]
    - fromPackageFlag :: Bool
    }
- data UnusableUnit = UnusableUnit {
  - uuUnit :: !Unit
  - uuReason :: !UnusableUnitReason
  - uuIsReexport :: !Bool
  }
- data UnusableUnitReason
  - = IgnoredWithFlag
  - | BrokenDependencies [UnitId]
  - | CyclicDependencies [UnitId]
  - | IgnoredDependencies [UnitId]
  - | ShadowedDependencies [UnitId]
- pprReason :: SDoc -> UnusableUnitReason -> SDoc
- closeUnitDeps :: UnitInfoMap -> [(UnitId, Maybe UnitId)] -> MaybeErr UnitErr [UnitId]
- closeUnitDeps' :: UnitInfoMap -> [UnitId] -> [(UnitId, Maybe UnitId)] -> MaybeErr UnitErr [UnitId]
- mayThrowUnitErr :: MaybeErr UnitErr a -> IO a
- type ShHoleSubst = ModuleNameEnv Module
- renameHoleUnit :: UnitState -> ShHoleSubst -> Unit -> Unit
- renameHoleModule :: UnitState -> ShHoleSubst -> Module -> Module
- renameHoleUnit' :: UnitInfoMap -> PreloadUnitClosure -> ShHoleSubst -> Unit -> Unit
- renameHoleModule' :: UnitInfoMap -> PreloadUnitClosure -> ShHoleSubst -> Module -> Module
- instUnitToUnit :: UnitState -> InstantiatedUnit -> Unit
- instModuleToModule :: UnitState -> InstantiatedModule -> Module
- pprFlag :: PackageFlag -> SDoc
- pprUnits :: UnitState -> SDoc
- pprUnitsSimple :: UnitState -> SDoc
- pprUnitIdForUser :: UnitState -> UnitId -> SDoc
- pprUnitInfoForUser :: UnitInfo -> SDoc
- pprModuleMap :: ModuleNameProvidersMap -> SDoc
- pprWithUnitState :: UnitState -> SDoc -> SDoc
- pprRawUnitIds :: SDoc -> SDoc
- unwireUnit :: UnitState -> Unit -> Unit

# Documentation

module GHC.Unit.Info

# Reading the package config, and processing cmdline args

data UnitState #

Constructors

UnitState |
Fields unitInfoMap :: UnitInfoMap A mapping of `Unit` to `UnitInfo`. This list is adjusted so that only valid units are here. `UnitInfo` reflects what was stored *on disk*, except for the `trusted` flag, which is adjusted at runtime. (In particular, some units in this map may have the `exposed` flag be `False`.) preloadClosure :: PreloadUnitClosure The set of transitively reachable units according to the explicitly provided command line arguments. A fully instantiated VirtUnit may only be replaced by a RealUnit from this set. See Note [VirtUnit to RealUnit improvement] packageNameMap :: UniqFM PackageName UnitId A mapping of `PackageName` to `UnitId`. If several units have the same package name (e.g. different instantiations), then we return one of them... This is used when users refer to packages in Backpack includes. And also to resolve package qualifiers with the PackageImports extension. wireMap :: UniqMap UnitId UnitId A mapping from database unit keys to wired in unit ids. unwireMap :: UniqMap UnitId UnitId A mapping from wired in unit ids to unit keys from the database. preloadUnits :: [UnitId] The units we're going to link in eagerly. This list should be in reverse dependency order; that is, a unit is always mentioned before the units it depends on. explicitUnits :: [(Unit, Maybe PackageArg)] Units which we explicitly depend on (from a command line flag). We'll use this to generate version macros and the unused packages warning. The original flag which was used to bring the unit into scope is recorded for the -Wunused-packages warning. homeUnitDepends :: [UnitId] moduleNameProvidersMap :: !ModuleNameProvidersMap This is a full map from `ModuleName` to all modules which may possibly be providing it. These providers may be hidden (but we'll still want to report them in error messages), or it may be an ambiguous import. pluginModuleNameProvidersMap :: !ModuleNameProvidersMap A map, like `moduleNameProvidersMap`, but controlling plugin visibility. requirementContext :: UniqMap ModuleName [InstantiatedModule] A map saying, for each requirement, what interfaces must be merged together when we use them. For example, if our dependencies are `p[A=<A>]` and `q[A=<A>,B=r[C=<A>]:B]`, then the interfaces to merge for A are `p[A=<A>]:A`, `q[A=<A>,B=r[C=<A>]:B]:A` and `r[C=<A>]:C`. There's an entry in this map for each hole in our home library. allowVirtualUnits :: !Bool Indicate if we can instantiate units on-the-fly. This should only be true when we are type-checking an indefinite unit. See Note [About units] in GHC.Unit.

type PreloadUnitClosure = UniqSet UnitId #

data UnitDatabase unit #

Unit database

Constructors

UnitDatabase |
Fields unitDatabasePath :: FilePath unitDatabaseUnits :: [GenUnitInfo unit]

#### Instances

Instances details

Outputable u => Outputable (UnitDatabase u) # |
Instance details Defined in GHC.Unit.State Methods ppr :: UnitDatabase u -> SDoc #

data UnitErr #

Constructors

CloseUnitErr !UnitId !(Maybe UnitId) |
PackageFlagErr !PackageFlag ![(UnitInfo, UnusableUnitReason)] |
TrustFlagErr !TrustFlag ![(UnitInfo, UnusableUnitReason)] |

#### Instances

Instances details

Outputable UnitErr # |
Instance details Defined in GHC.Unit.State Methods ppr :: UnitErr -> SDoc #

emptyUnitState :: UnitState #

initUnits :: Logger -> DynFlags -> Maybe [UnitDatabase UnitId] -> Set UnitId -> IO ([UnitDatabase UnitId], UnitState, HomeUnit, Maybe PlatformConstants) #

Read the unit database files, and sets up various internal tables of unit information, according to the unit-related flags on the command-line (`-package`, `-hide-package` etc.)

`initUnits` can be called again subsequently after updating the `packageFlags` field of the `DynFlags`, and it will update the `unitState` in `DynFlags`.

readUnitDatabases :: Logger -> UnitConfig -> IO [UnitDatabase UnitId] #

readUnitDatabase :: Logger -> UnitConfig -> FilePath -> IO (UnitDatabase UnitId) #

getUnitDbRefs :: UnitConfig -> IO [PkgDbRef] #

resolveUnitDatabase :: UnitConfig -> PkgDbRef -> IO (Maybe FilePath) #

Return the path of a package database from a `PkgDbRef`. Return `Nothing` when the user database filepath is expected but the latter doesn't exist.

NB: This logic is reimplemented in Cabal, so if you change it, make sure you update Cabal. (Or, better yet, dump it in the compiler info so Cabal can use the info.)

listUnitInfo :: UnitState -> [UnitInfo] #

Get a list of entries from the unit database. NB: be careful with this function, although all units in this map are "visible", this does not imply that the exposed-modules of the unit are available (they may have been thinned or renamed).

# Querying the package config

type UnitInfoMap = UniqMap UnitId UnitInfo #

lookupUnit :: UnitState -> Unit -> Maybe UnitInfo #

Find the unit we know about with the given unit, if any

lookupUnit' :: Bool -> UnitInfoMap -> PreloadUnitClosure -> Unit -> Maybe UnitInfo #

A more specialized interface, which doesn't require a `UnitState` (so it can be used while we're initializing `DynFlags`)

Parameters: * a boolean specifying whether or not to look for on-the-fly renamed interfaces * a `UnitInfoMap` * a `PreloadUnitClosure`

unsafeLookupUnit :: HasDebugCallStack => UnitState -> Unit -> UnitInfo #

Looks up the given unit in the unit state, panicking if it is not found

lookupUnitId :: UnitState -> UnitId -> Maybe UnitInfo #

Find the unit we know about with the given unit id, if any

lookupUnitId' :: UnitInfoMap -> UnitId -> Maybe UnitInfo #

Find the unit we know about with the given unit id, if any

unsafeLookupUnitId :: HasDebugCallStack => UnitState -> UnitId -> UnitInfo #

Looks up the given unit id in the unit state, panicking if it is not found

lookupPackageName :: UnitState -> PackageName -> Maybe UnitId #

Find the unit we know about with the given package name (e.g. `foo`), if any (NB: there might be a locally defined unit name which overrides this) This function is unsafe to use in general because it doesn't respect package visibility.

resolvePackageImport :: UnitState -> ModuleName -> PackageName -> Maybe UnitId #

Find the UnitId which an import qualified by a package import comes from. Compared to `lookupPackageName`, this function correctly accounts for visibility, renaming and thinning.

improveUnit :: UnitState -> Unit -> Unit #

Given a fully instantiated `InstantiatedUnit`, improve it into a `RealUnit` if we can find it in the package database.

searchPackageId :: UnitState -> PackageId -> [UnitInfo] #

Search for units with a given package ID (e.g. "foo-0.1")

listVisibleModuleNames :: UnitState -> [ModuleName] #

lookupModuleInAllUnits :: UnitState -> ModuleName -> [(Module, UnitInfo)] #

Takes a `ModuleName`, and if the module is in any package returns list of modules which take that name.

lookupModuleWithSuggestions :: UnitState -> ModuleName -> PkgQual -> LookupResult #

lookupModulePackage :: UnitState -> ModuleName -> PkgQual -> Maybe [UnitInfo] #

The package which the module **appears** to come from, this could be the one which reexports the module from it's original package. This function is currently only used for -Wunused-packages

lookupPluginModuleWithSuggestions :: UnitState -> ModuleName -> PkgQual -> LookupResult #

requirementMerges :: UnitState -> ModuleName -> [InstantiatedModule] #

Return this list of requirement interfaces that need to be merged to form `mod_name`, or `[]` if this is not a requirement.

data LookupResult #

The result of performing a lookup

Constructors

LookupFound Module (UnitInfo, ModuleOrigin) | Found the module uniquely, nothing else to do
LookupMultiple [(Module, ModuleOrigin)] | Multiple modules with the same name in scope
LookupHidden [(Module, ModuleOrigin)] [(Module, ModuleOrigin)] | No modules found, but there were some hidden ones with an exact name match. First is due to package hidden, second is due to module being hidden
LookupUnusable [(Module, ModuleOrigin)] | No modules found, but there were some unusable ones with an exact name match
LookupNotFound [ModuleSuggestion] | Nothing found, here are some suggested different names

data ModuleSuggestion #

Constructors

SuggestVisible ModuleName Module ModuleOrigin |
SuggestHidden ModuleName Module ModuleOrigin |

data ModuleOrigin #

Given a module name, there may be multiple ways it came into scope, possibly simultaneously. This data type tracks all the possible ways it could have come into scope. Warning: don't use the record functions, they're partial!

Constructors

ModHidden | Module is hidden, and thus never will be available for import. (But maybe the user didn't realize), so we'll still keep track of these modules.)
ModUnusable !UnusableUnit | Module is unavailable because the unit is unusable.
ModOrigin | Module is public, and could have come from some places.
Fields fromOrigUnit :: Maybe Bool `Just False` means that this module is in someone's `exported-modules` list, but that package is hidden; `Just True` means that it is available; `Nothing` means neither applies. fromExposedReexport :: [UnitInfo] Is the module available from a reexport of an exposed package? There could be multiple. fromHiddenReexport :: [UnitInfo] Is the module available from a reexport of a hidden package? fromPackageFlag :: Bool Did the module export come from a package flag? (ToDo: track more information.

#### Instances

Instances details

Monoid ModuleOrigin # |
Instance details Defined in GHC.Unit.State Methods mempty :: ModuleOrigin # mappend :: ModuleOrigin -> ModuleOrigin -> ModuleOrigin # mconcat :: [ModuleOrigin] -> ModuleOrigin #
Semigroup ModuleOrigin # |
Instance details Defined in GHC.Unit.State Methods (<>) :: ModuleOrigin -> ModuleOrigin -> ModuleOrigin # sconcat :: NonEmpty ModuleOrigin -> ModuleOrigin # stimes :: Integral b => b -> ModuleOrigin -> ModuleOrigin #
Outputable ModuleOrigin # |
Instance details Defined in GHC.Unit.State Methods ppr :: ModuleOrigin -> SDoc #

data UnusableUnit #

A unusable unit module origin

Constructors

UnusableUnit |
Fields uuUnit :: !Unit Unusable unit uuReason :: !UnusableUnitReason Reason uuIsReexport :: !Bool Is the "module" a reexport?

data UnusableUnitReason #

The reason why a unit is unusable.

Constructors

IgnoredWithFlag | We ignored it explicitly using `-ignore-package`.
BrokenDependencies [UnitId] | This unit transitively depends on a unit that was never present in any of the provided databases.
CyclicDependencies [UnitId] | This unit transitively depends on a unit involved in a cycle. Note that the list of `UnitId` reports the direct dependencies of this unit that (transitively) depended on the cycle, and not the actual cycle itself (which we report separately at high verbosity.)
IgnoredDependencies [UnitId] | This unit transitively depends on a unit which was ignored.
ShadowedDependencies [UnitId] | This unit transitively depends on a unit which was shadowed by an ABI-incompatible unit.

#### Instances

Instances details

Outputable UnusableUnitReason # |
Instance details Defined in GHC.Unit.State Methods ppr :: UnusableUnitReason -> SDoc #

pprReason :: SDoc -> UnusableUnitReason -> SDoc #

closeUnitDeps :: UnitInfoMap -> [(UnitId, Maybe UnitId)] -> MaybeErr UnitErr [UnitId] #

Takes a list of UnitIds (and their "parent" dependency, used for error messages), and returns the list with dependencies included, in reverse dependency order (a units appears before those it depends on).

closeUnitDeps' :: UnitInfoMap -> [UnitId] -> [(UnitId, Maybe UnitId)] -> MaybeErr UnitErr [UnitId] #

Similar to closeUnitDeps but takes a list of already loaded units as an additional argument.

mayThrowUnitErr :: MaybeErr UnitErr a -> IO a #

# Module hole substitution

type ShHoleSubst = ModuleNameEnv Module #

Substitution on module variables, mapping module names to module identifiers.

renameHoleUnit :: UnitState -> ShHoleSubst -> Unit -> Unit #

Substitutes holes in a `Unit`, suitable for renaming when an include occurs; see Note [Representation of module/name variables].

`p[A=<A>]` maps to `p[A=<B>]` with `A=<B>`.

renameHoleModule :: UnitState -> ShHoleSubst -> Module -> Module #

Substitutes holes in a `Module`. NOT suitable for being called directly on a `nameModule`, see Note [Representation of module/name variables]. `p[A=<A>]:B` maps to `p[A=q():A]:B` with `A=q():A`; similarly, `<A>` maps to `q():A`.

renameHoleUnit' :: UnitInfoMap -> PreloadUnitClosure -> ShHoleSubst -> Unit -> Unit #

Like 'renameHoleUnit, but requires only `ClosureUnitInfoMap` so it can be used by GHC.Unit.State.

renameHoleModule' :: UnitInfoMap -> PreloadUnitClosure -> ShHoleSubst -> Module -> Module #

Like `renameHoleModule`, but requires only `ClosureUnitInfoMap` so it can be used by GHC.Unit.State.

instUnitToUnit :: UnitState -> InstantiatedUnit -> Unit #

Check the database to see if we already have an installed unit that corresponds to the given `InstantiatedUnit`.

Return a `UnitId` which either wraps the `InstantiatedUnit` unchanged or references a matching installed unit.

See Note [VirtUnit to RealUnit improvement]

instModuleToModule :: UnitState -> InstantiatedModule -> Module #

Injects an `InstantiatedModule` to `Module` (see also `instUnitToUnit`.

# Pretty-printing

pprFlag :: PackageFlag -> SDoc #

pprUnits :: UnitState -> SDoc #

Show (very verbose) package info

pprUnitsSimple :: UnitState -> SDoc #

Show simplified unit info.

The idea is to only print package id, and any information that might be different from the package databases (exposure, trust)

pprUnitIdForUser :: UnitState -> UnitId -> SDoc #

Pretty-print a UnitId for the user.

Cabal packages may contain several components (programs, libraries, etc.). As far as GHC is concerned, installed package components ("units") are identified by an opaque UnitId string provided by Cabal. As the string contains a hash, we don't want to display it to users so GHC queries the database to retrieve some infos about the original source package (name, version, component name).

Instead we want to display: packagename-version[:componentname]

Component name is only displayed if it isn't the default library

To do this we need to query a unit database.

pprUnitInfoForUser :: UnitInfo -> SDoc #

pprModuleMap :: ModuleNameProvidersMap -> SDoc #

Show the mapping of modules to where they come from.

pprWithUnitState :: UnitState -> SDoc -> SDoc #

Print unit-ids with UnitInfo found in the given UnitState

pprRawUnitIds :: SDoc -> SDoc #

Print raw unit-ids, without removing the hash

# Utils

unwireUnit :: UnitState -> Unit -> Unit #

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