haskell / haskell/cabal

Re-design the ProgramDb abstraction to avoid accidentally dropping unconfigured programs

Open
#9,840 3 comments 2 reactions 0 assignees View on GitHub
needs triage type: bug
Dominant language
Haskell
Stars
1.7k
Forks
750
Avg merge
4d 3h
Merged PRs (30d)
28

Description

We have

```haskell
data ProgramDb = ProgramDb
{ unconfiguredProgs :: UnconfiguredProgs
, progSearchPath :: ProgramSearchPath
, configuredProgs :: ConfiguredProgs
}

-- | Note that this instance does not preserve the known 'Program's.
-- See 'restoreProgramDb' for details.
instance Binary ProgramDb where
put db = do
put (progSearchPath db)
put (configuredProgs db)

get = do
searchpath <- get
progs <- get
return $!
emptyProgramDb
{ progSearchPath = searchpath
, configuredProgs = progs
}
```

Note here that the `Binary` instance for `ProgramDb` discards the unconfigured programs. This is because arbitrary functions can be stored in that field (e.g. `programFindVersion :: Verbosity -> FilePath -> IO (Maybe Version)`).

However, this easily leads to bugs; #2241 was an example. I ran into another bug today, which was that the `configureCompiler` function in `cabal-install` would also drop unconfigured programs, which could lead to e.g. failing to find the `ar` executable (`The program 'ar' is required but it could not be found.`).

One first step which could help avoiding bugs is to define a newtype around `ProgramDb` and attach the `Binary` instance to that newtype instead. The wrapping/unwrapping of the newtype would hopefully introduce the appropriate amount of ceremony to avoid accidents.

More ambitiously, we could re-design `ProgramDb`, e.g. by introducing a serialisable DSL for unconfigured programs, or perhaps by using static pointers.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.