Skip to content

--allow-boot-library-installs fails on GHC < 9.14 with "unbuildable library from ghc-internal" #12328

Description

@andreabedini

Describe the bug

On master, passing --allow-boot-library-installs turns an otherwise working
plan into a failure, on any GHC that does not report wired-in unit ids (GHC < 9.14).
The error names ghc-internal, a package the user never mentioned:

Error:
    Dependency on unbuildable library from ghc-internal
    In the stanza 'library'
    In the package 'base-4.22.0.0'

Note that the solver does not report an unsolvable plan. It succeeds, having
selected base-4.22.0.0 from Hackage; the failure happens afterwards, during
elaboration.

This is a regression on master only. Released cabal-install 3.18.1.0 is not
affected.

To Reproduce

#!/usr/bin/env bash
# Usage:  ./repro.sh            # uses `cabal` and `ghc` from PATH
#         CABAL=/path/to/cabal GHC=ghc-9.12.2 ./repro.sh
#
# Exits 0 if cabal behaves correctly, non-zero if the bug is present.
set -eu

CABAL=${CABAL:-cabal}
GHC=${GHC:-ghc}

dir=$(mktemp -d)
trap 'rm -rf "$dir"' EXIT
cd "$dir"

cat > repro.cabal <<'EOF'
cabal-version: 2.4
name:          repro
version:       0
build-type:    Simple

library
  exposed-modules:  Lib
  build-depends:    base
  default-language: Haskell2010
EOF
printf 'module Lib where\n' > Lib.hs

echo "cabal-install $("$CABAL" --numeric-version), ghc $("$GHC" --numeric-version)"
echo

echo "=== 1. without --allow-boot-library-installs (expected: succeeds) ==="
"$CABAL" build --dry-run -w "$GHC"
echo

echo "=== 2. with --allow-boot-library-installs (expected: succeeds) ==="
if "$CABAL" build --dry-run -w "$GHC" --allow-boot-library-installs; then
  echo
  echo "RESULT: ok -- no bug on this cabal/ghc combination."
else
  echo
  echo "RESULT: BUG -- the same plan fails once --allow-boot-library-installs is passed."
  exit 1
fi

Step 1 establishes that the plan is fine; step 2 differs only by the flag.

GHC result
9.10.3 fails
9.12.2 fails
9.14.1 succeeds (reports wired-in unit ids)

Without the flag, all three succeed.

Expected behavior

--allow-boot-library-installs should not make a plan fail. It relaxes a
restriction; it should never turn a solvable plan into an unsolvable one.

System information

  • Linux
  • cabal-install built from master (a0c8112), version 3.19.0.0
  • GHC 9.10.3, 9.12.2, 9.14.1

Additional context

dependOnWiredIns adds two kinds of constraint: one installed-unit-id
constraint per wired-in unit of the compiler, and one base >= 4.22 version
constraint added in #12055.

dependOnWiredIns :: CompilerInfo -> DepResolverParams -> DepResolverParams
dependOnWiredIns compiler params = addConstraints extraConstraints params
where
extraConstraints =
[ LabeledPackageConstraint
(PackageConstraint (ScopeAnyQualifier pkgName) (PackagePropertyInstalledSpecificUnitId unitId))
ConstraintSourceNonReinstallablePackage
| (pkgName, unitId) <- fromMaybe [] $ compilerInfoWiredInUnitIds compiler
]
++
-- Old versions of `base` must be excluded from build plans still as they do not depend on any version of a wired-in unit.
-- If we do not do this then we will get confusing error messages about old versions of `base` being unbuildable.
-- Newer versions of `base` will be handled gracefully as they were designed to be reinstallable.
[ LabeledPackageConstraint
(PackageConstraint (ScopeAnyQualifier $ mkPackageName "base") (PackagePropertyVersion (orLaterVersion (mkVersion [4, 22]))))
ConstraintSourceNonReinstallablePackage
]

The second constraint only makes sense next to the first. The unit-id
constraints pin the new, reinstallable base; the version constraint then
excludes the old, non-reinstallable one. But it is added unconditionally, while
the unit-id constraints are empty for a compiler that reports no wired-in units.

That path is reachable for such a compiler, because the caller enters it on
either of two conditions:

if isJust (compilerInfoWiredInUnitIds comp) || asBool (depResolverAllowBootLibInstalls params)
then dependOnWiredIns comp params
else dontInstallNonReinstallablePackages params

--allow-boot-library-installs alone is enough. So on GHC 9.12, the installed
base-4.21.0.0 is excluded by the version constraint, base-4.22.0.0 is
selected from Hackage instead, and it cannot be built because ghc-internal is
not available there.

Fixed by #12301, which guards the version constraint on the compiler actually
reporting wired-in unit ids.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions