From 18989a4f0b942437976ad470170b234c73d40e7e Mon Sep 17 00:00:00 2001 From: Matthew Pickering Date: Thu, 23 Nov 2023 10:30:04 +0000 Subject: [PATCH 01/12] feature: Private Dependencies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit introduces so-called "private dependencies". High-level Overview ~~~~~~~~~~~~~~~~~~~ Since its inception, Cabal has enforced the restriction that a library must only link against one version of each package it depends on. This ensures that all of the dependencies in the build plan work together. In your application you use different libraries together, so it’s of paramount importance that they all agree on what `Text` means or what a `ByteString` is. However, sometimes it’s desirable to allow multiple versions of the same library into a build plan. In this case, it’s desirable to allow a library author to specify a private dependency with the promise that its existence will not leak from the interface of the library which uses it. The two main use cases of private dependencies are: - Writing benchmarks and testsuites for your library which test new versions of your library against old versions. - Writing libraries which can communicate with processes built against a range of different library versions (such as cabal-install calling ./Setup). A user specifies a private dependency in their cabal file using `private-build-depends`. The specification starts with the name of the private dependency scope and then contains a list of normal dependency specifications which dictates what is included in that private scope: private-build-depends: TEXT1 with (text == 1.2.*), TEXT2 with (text == 2.*) Each private scope is then solved independently of all other scopes. In this example the TEXT1 scope can choose a version of text in the 1.2.x range and the TEXT2 scope can choose a version of text in the 2.* range. Private scopes do not apply transitively, so the dependencies of text will be solved in the normal top-level scope. If your program contains a value of type Bool, that comes from the base package, which text depends on, because the scopes are not applied transitively the same Bool value can be passed to functions from the TEXT1 scope and TEXT2 scope. Dependencies introduced privately can be imported into modules in the project by prefixing the name of the private scope to an exposed module name. import qualified TEXT1.Data.Text as T1 import qualified TEXT2.Data.Text as T2 Closure of Private Scopes ~~~~~~~~~~~~~~~~~~~~~~~~~ Private dependency scopes can contain multiple packages. Packages in the same scope are solved together. For example, if two packages are tightly coupled and you need to use compatible versions with each other, then you can list them in the same private scope. Such packages will then be solved together, but independently of other packages. Private scopes must be closed. A scope is closed if, whenever we have a dependency chain P1 -> Q -> P2, in which P1 and P2 are both in a given private scope S, then Q also belongs to the private scope S. The solver checks this property, but doesn’t implicitly add packages into a private scope. Implementation ~~~~~~~~~~~~~~ To implement private dependencies we changed * Cabal-syntax to introduce the new `private-build-depends: ALIAS (packages, in, private, scope)` syntax. See the new type `Dependencies` and changes in `Distribution.Types.Dependency`. * cabal-install-solver now considers both public and private dependencies of a given package (see e.g. `solverPkgLibDeps`), has a new constructor `PrivateScope` in `ConstraintScope` for goals in a private scope, and there's a new `Qualifier` for packages introduced in private scopes (see also [Namespace vs Qualifier refactor] below), to solve them separately from packages introduced by `build-depends`. * cabal-install-solver needs to check that the private-scope closure property holds (the closure of the packages in a private scope is in the private scope) (see `Distribution.Solver.Modular.PrivateScopeClosure`). We check that the closure holds by looking at the reverse dependency map while traversing down the tree, at every node: For every package in a private scope, traverse up the reverse dependency map until a package in the same private scope is found. If one exists, and if along the way up any package was not in the same private scope as the packages in the two ends, we fail. * cabal-install understands plans with private dependencies and has a new `UserQualifier` to support constrainting packages in private scopes using the `--constraint` flag. Example: `--constraint=private.pkg-a.TEXT01:text == 1.2.*` * Cabal the library uses the ghc module-renaming mechanism (also used by Backpack) to rename modules from the packages in a private scope to prefix them with the private scope alias. It also ensures `cabal check` fails if there exist the package has private dependencies, as it is currently an experimental feature which we don't necessarily want to allow in hackage yet -- e.g. how will haddock render private dependencies? Namespace vs Qualifier refactor ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ We also refactored the `Namespace` vs `Qualifier` types in the solver, clarifying their interaction such that: * A package goal with an indepedent namespace is fully solved indepently from other namespaces, i.e. all the dependency goals introduced by a goal in a given namespace are also solved in that namespace. * In contrast, a package goal with a qualifier is shallow-solved separately from other goals in the same namespace. The dependency goals introduced by it will be solved unqualified (`QualTopLevel`) in that namespace. For example, goal `pkg-a == 0.1` in `DefaultNamespace+QualTopLevel`, and goal `pkg-a == 0.2` in the same namespace but with `QualAlias A2 ...` can be solved together and yield a different version of pkg-a for each of the goals, however, the dependencies of both will be solved together -- if they both dependend on `base`, we'd have to find a single solution. If `pkg-a == 0.2` was in an `Independent` namespace, we could still solve the two goals with two versions of `pkg-a`, but we could also pick different versions for all the subdependencies of `pkg-a == 0.2`. Besides Namespace vs Qualifier being a welcome refactor that facilitates implementing private dependencies, it also fixes #9466 and helps with #9467. --- Co-authored-by: Rodrigo Mesquita --- .../src/Test/QuickCheck/Instances/Cabal.hs | 17 + Cabal-described/src/Distribution/Described.hs | 18 +- Cabal-syntax/Cabal-syntax.cabal | 1 + Cabal-syntax/src/Distribution/ModuleName.hs | 20 +- .../PackageDescription/Configuration.hs | 63 +- .../PackageDescription/FieldGrammar.hs | 10 + .../Distribution/PackageDescription/Parsec.hs | 30 +- .../PackageDescription/PrettyPrint.hs | 28 +- .../src/Distribution/Types/BuildInfo.hs | 3 + .../src/Distribution/Types/BuildInfo/Lens.hs | 9 +- .../src/Distribution/Types/ComponentName.hs | 1 + .../src/Distribution/Types/Dependency.hs | 66 + .../src/Distribution/Types/Dependency/Lens.hs | 14 + .../src/Distribution/Types/DependencyMap.hs | 28 +- .../Types/GenericPackageDescription.hs | 20 +- .../Types/GenericPackageDescription/Lens.hs | 18 +- .../Distribution/Types/PackageDescription.hs | 17 +- Cabal-tests/tests/NoThunks.hs | 3 + .../ParserTests/regressions/Octree-0.5.expr | 128 +- .../ParserTests/regressions/anynone.expr | 14 +- .../ParserTests/regressions/big-version.expr | 6 +- .../regressions/common-conditional.expr | 136 +- .../tests/ParserTests/regressions/common.expr | 28 +- .../ParserTests/regressions/common2.expr | 176 ++- .../ParserTests/regressions/common3.expr | 52 +- .../tests/ParserTests/regressions/elif.expr | 20 +- .../tests/ParserTests/regressions/elif2.expr | 46 +- .../ParserTests/regressions/encoding-0.8.expr | 22 +- .../ParserTests/regressions/generics-sop.expr | 204 +-- .../ParserTests/regressions/hasktorch.expr | 1158 +++++++++-------- .../regressions/hidden-main-lib.expr | 14 +- .../ParserTests/regressions/indentation.expr | 6 +- .../ParserTests/regressions/indentation2.expr | 6 +- .../ParserTests/regressions/indentation3.expr | 6 +- .../ParserTests/regressions/issue-5055.expr | 50 +- .../ParserTests/regressions/issue-5846.expr | 78 +- .../ParserTests/regressions/issue-6083-a.expr | 92 +- .../ParserTests/regressions/issue-6083-b.expr | 102 +- .../ParserTests/regressions/issue-6083-c.expr | 38 +- .../regressions/issue-6083-pkg-pkg.expr | 22 +- .../ParserTests/regressions/issue-774.expr | 6 +- .../regressions/jaeger-flamegraph.expr | 178 +-- .../regressions/leading-comma-2.expr | 54 +- .../regressions/leading-comma.expr | 54 +- .../tests/ParserTests/regressions/libpq1.expr | 112 +- .../tests/ParserTests/regressions/libpq2.expr | 112 +- .../ParserTests/regressions/mixin-1.expr | 30 +- .../ParserTests/regressions/mixin-2.expr | 30 +- .../ParserTests/regressions/mixin-3.expr | 30 +- .../ParserTests/regressions/monad-param.expr | 30 +- .../regressions/multiple-libs-2.expr | 28 +- .../ParserTests/regressions/noVersion.expr | 14 +- .../regressions/nothing-unicode.expr | 12 +- .../tests/ParserTests/regressions/shake.expr | 668 +++++----- .../tests/ParserTests/regressions/spdx-1.expr | 6 +- .../tests/ParserTests/regressions/spdx-2.expr | 6 +- .../tests/ParserTests/regressions/spdx-3.expr | 6 +- .../regressions/th-lift-instances.expr | 262 ++-- .../ParserTests/regressions/version-sets.expr | 106 +- .../regressions/wl-pprint-indef.expr | 56 +- .../tests/UnitTests/Distribution/Described.hs | 3 +- .../Distribution/Utils/Structured.hs | 8 +- .../src/Data/TreeDiff/Instances/Cabal.hs | 5 + .../Distribution/Backpack/ComponentsGraph.hs | 2 +- Cabal/src/Distribution/Backpack/Configure.hs | 10 +- .../Backpack/ConfiguredComponent.hs | 33 +- .../Distribution/Backpack/LinkedComponent.hs | 9 +- .../src/Distribution/Backpack/ModuleScope.hs | 4 +- .../Backpack/PreExistingComponent.hs | 7 +- Cabal/src/Distribution/Backpack/UnifyM.hs | 25 +- .../Distribution/PackageDescription/Check.hs | 11 +- .../PackageDescription/Check/Conditional.hs | 30 +- Cabal/src/Distribution/Simple/Configure.hs | 91 +- Cabal/src/Distribution/Simple/Errors.hs | 5 +- Cabal/src/Distribution/Simple/GHC/Internal.hs | 2 +- Cabal/src/Distribution/Simple/Setup/Config.hs | 12 +- .../Distribution/Types/ComponentInclude.hs | 3 + .../src/Distribution/Types/GivenComponent.hs | 2 + .../Distribution/Types/LocalBuildConfig.hs | 2 +- .../src/Distribution/Types/LocalBuildInfo.hs | 2 +- .../cabal-install-solver.cabal | 1 + .../Distribution/Solver/Modular/Builder.hs | 14 +- .../Solver/Modular/ConfiguredConversion.hs | 61 +- .../Solver/Modular/ConflictSet.hs | 9 + .../Distribution/Solver/Modular/Dependency.hs | 47 +- .../Distribution/Solver/Modular/Explore.hs | 15 +- .../src/Distribution/Solver/Modular/Index.hs | 4 +- .../Solver/Modular/IndexConversion.hs | 43 +- .../Distribution/Solver/Modular/Linking.hs | 64 +- .../Distribution/Solver/Modular/Message.hs | 2 + .../Distribution/Solver/Modular/Package.hs | 25 - .../Distribution/Solver/Modular/Preference.hs | 7 +- .../Solver/Modular/PrivateScopeClosure.hs | 126 ++ .../src/Distribution/Solver/Modular/Solver.hs | 3 + .../src/Distribution/Solver/Modular/Tree.hs | 1 + .../Distribution/Solver/Modular/Validate.hs | 12 +- .../Solver/Types/ComponentDeps.hs | 2 +- .../Solver/Types/InstSolverPackage.hs | 4 +- .../Solver/Types/PackageConstraint.hs | 37 +- .../Distribution/Solver/Types/PackagePath.hs | 53 +- .../Solver/Types/ResolverPackage.hs | 5 +- .../src/Distribution/Solver/Types/SolverId.hs | 2 +- .../Solver/Types/SolverPackage.hs | 3 +- .../src/Distribution/Client/CmdOutdated.hs | 8 +- .../src/Distribution/Client/CmdRepl.hs | 5 +- .../src/Distribution/Client/Configure.hs | 4 +- .../src/Distribution/Client/Dependency.hs | 66 +- .../src/Distribution/Client/GenBounds.hs | 18 +- .../src/Distribution/Client/Init/Utils.hs | 2 +- .../src/Distribution/Client/Install.hs | 4 +- .../src/Distribution/Client/InstallPlan.hs | 21 +- .../src/Distribution/Client/InstallSymlink.hs | 2 +- cabal-install/src/Distribution/Client/List.hs | 3 +- .../src/Distribution/Client/ProjectConfig.hs | 2 +- .../Client/ProjectOrchestration.hs | 2 +- .../Distribution/Client/ProjectPlanOutput.hs | 6 +- .../Distribution/Client/ProjectPlanning.hs | 127 +- .../Client/ProjectPlanning/SetupPolicy.hs | 2 +- .../Client/ProjectPlanning/Types.hs | 20 +- .../src/Distribution/Client/ScriptUtils.hs | 6 +- .../src/Distribution/Client/Setup.hs | 7 +- .../Distribution/Client/SolverInstallPlan.hs | 48 +- .../src/Distribution/Client/Targets.hs | 38 +- .../Client/Types/ConfiguredPackage.hs | 2 +- cabal-install/tests/IntegrationTests2.hs | 2 +- cabal-install/tests/UnitTests.hs | 3 +- .../Distribution/Client/DescribedInstances.hs | 2 + .../Distribution/Client/Init/Utils.hs | 12 +- .../Distribution/Solver/Modular/DSL.hs | 97 +- .../Solver/Modular/DSL/TestCaseUtils.hs | 17 +- .../Distribution/Solver/Modular/QuickCheck.hs | 28 +- .../Distribution/Solver/Modular/Solver.hs | 283 +++- .../PrivateDeps/cabal-hooks-demo/README.md | 10 + .../cabal-hooks-demo/cabal.project | 1 + .../cabal-hooks-demo/cabal.test.hs | 20 + .../cabal-hooks-demo/hooks-exe/CHANGELOG.md | 5 + .../cabal-hooks-demo/hooks-exe/app/Main.hs | 35 + .../hooks-exe/hooks-exe.cabal | 19 + .../cabal-hooks-demo/hooks-lib/CHANGELOG.md | 5 + .../hooks-lib/hooks-lib.cabal | 20 + .../hooks-lib/src/HooksLib.hs | 133 ++ .../cabal-hooks-demo/hooks-lib/src/MyLib.hs | 4 + .../cabal-hooks-demo/main-prog/CHANGELOG.md | 5 + .../cabal-hooks-demo/main-prog/app/Main.hs | 21 + .../main-prog/main-prog.cabal | 18 + .../repo/lib01-0.1.0.0/CHANGELOG.md | 5 + .../repo/lib01-0.1.0.0/lib01.cabal | 18 + .../repo/lib01-0.1.0.0/src/Lib.hs | 16 + .../repo/lib01-0.2.0.0/CHANGELOG.md | 5 + .../repo/lib01-0.2.0.0/lib01.cabal | 18 + .../repo/lib01-0.2.0.0/src/Lib.hs | 16 + .../closure-property-test/README.md | 30 + .../closure-property-test/cabal.project.1 | 1 + .../closure-property-test/cabal.project.2 | 1 + .../closure-property-test/cabal.project.3 | 1 + .../closure-property-test/cabal.project.4 | 1 + .../closure-property-test/cabal.test.hs | 29 + .../libA-0.1.0.0/MyLib.hs | 3 + .../libA-0.1.0.0/libA.cabal | 13 + .../libA-0.2.0.0/MyLib.hs | 3 + .../libA-0.2.0.0/libA.cabal | 14 + .../libA-0.3.0.0/MyLib.hs | 3 + .../libA-0.3.0.0/libA.cabal | 14 + .../libA-0.4.0.0/MyLib.hs | 3 + .../libA-0.4.0.0/libA.cabal | 13 + .../repo/libB-0.1.0.0/MyLib.hs | 3 + .../repo/libB-0.1.0.0/libB.cabal | 12 + .../repo/libB-0.2.0.0/MyLib.hs | 3 + .../repo/libB-0.2.0.0/libB.cabal | 12 + .../repo/libB-0.3.0.0/MyLib.hs | 3 + .../repo/libB-0.3.0.0/libB.cabal | 12 + .../repo/libC-0.1.0.0/MyLib.hs | 3 + .../repo/libC-0.1.0.0/libC.cabal | 11 + .../repo/libC-0.2.0.0/MyLib.hs | 3 + .../repo/libC-0.2.0.0/libC.cabal | 12 + .../repo/libD-0.1.0.0/MyLib.hs | 3 + .../repo/libD-0.1.0.0/libD.cabal | 11 + .../PrivateDeps/pd-backpack/README.md | 15 + .../PrivateDeps/pd-backpack/cabal.project | 1 + .../PrivateDeps/pd-backpack/cabal.test.hs | 9 + .../PrivateDeps/pd-backpack/libA/app/Main.hs | 8 + .../PrivateDeps/pd-backpack/libA/libA.cabal | 22 + .../PrivateDeps/pd-backpack/libA/src/A.hs | 3 + .../pd-backpack/libA/src/AHole.hsig | 3 + .../pd-backpack/repo/libB-0.1.0.0/Fill.hs | 4 + .../pd-backpack/repo/libB-0.1.0.0/libB.cabal | 10 + .../pd-backpack/repo/libB-0.1.0.0/tags | 2 + .../pd-backpack/repo/libB-0.2.0.0/Fill.hs | 4 + .../pd-backpack/repo/libB-0.2.0.0/libB.cabal | 10 + .../pd-backpack/repo/libB-0.2.0.0/tags | 2 + .../pd-backpack/repo/libB-0.3.0.0/Fill.hs | 4 + .../pd-backpack/repo/libB-0.3.0.0/libB.cabal | 10 + .../pd-backpack/repo/libB-0.3.0.0/tags | 2 + cabal-testsuite/src/Test/Cabal/Prelude.hs | 4 +- doc/buildinfo-fields-reference.rst | 7 + doc/cabal-package-description-file.rst | 24 + 196 files changed, 4520 insertions(+), 2428 deletions(-) create mode 100644 Cabal-syntax/src/Distribution/Types/Dependency/Lens.hs create mode 100644 cabal-install-solver/src/Distribution/Solver/Modular/PrivateScopeClosure.hs create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/README.md create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/cabal.project create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/cabal.test.hs create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/hooks-exe/CHANGELOG.md create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/hooks-exe/app/Main.hs create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/hooks-exe/hooks-exe.cabal create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/hooks-lib/CHANGELOG.md create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/hooks-lib/hooks-lib.cabal create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/hooks-lib/src/HooksLib.hs create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/hooks-lib/src/MyLib.hs create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/main-prog/CHANGELOG.md create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/main-prog/app/Main.hs create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/main-prog/main-prog.cabal create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/repo/lib01-0.1.0.0/CHANGELOG.md create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/repo/lib01-0.1.0.0/lib01.cabal create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/repo/lib01-0.1.0.0/src/Lib.hs create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/repo/lib01-0.2.0.0/CHANGELOG.md create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/repo/lib01-0.2.0.0/lib01.cabal create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/repo/lib01-0.2.0.0/src/Lib.hs create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/README.md create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/cabal.project.1 create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/cabal.project.2 create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/cabal.project.3 create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/cabal.project.4 create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/cabal.test.hs create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/libA-0.1.0.0/MyLib.hs create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/libA-0.1.0.0/libA.cabal create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/libA-0.2.0.0/MyLib.hs create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/libA-0.2.0.0/libA.cabal create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/libA-0.3.0.0/MyLib.hs create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/libA-0.3.0.0/libA.cabal create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/libA-0.4.0.0/MyLib.hs create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/libA-0.4.0.0/libA.cabal create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/repo/libB-0.1.0.0/MyLib.hs create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/repo/libB-0.1.0.0/libB.cabal create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/repo/libB-0.2.0.0/MyLib.hs create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/repo/libB-0.2.0.0/libB.cabal create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/repo/libB-0.3.0.0/MyLib.hs create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/repo/libB-0.3.0.0/libB.cabal create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/repo/libC-0.1.0.0/MyLib.hs create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/repo/libC-0.1.0.0/libC.cabal create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/repo/libC-0.2.0.0/MyLib.hs create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/repo/libC-0.2.0.0/libC.cabal create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/repo/libD-0.1.0.0/MyLib.hs create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/repo/libD-0.1.0.0/libD.cabal create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/README.md create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/cabal.project create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/cabal.test.hs create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/libA/app/Main.hs create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/libA/libA.cabal create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/libA/src/A.hs create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/libA/src/AHole.hsig create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/repo/libB-0.1.0.0/Fill.hs create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/repo/libB-0.1.0.0/libB.cabal create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/repo/libB-0.1.0.0/tags create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/repo/libB-0.2.0.0/Fill.hs create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/repo/libB-0.2.0.0/libB.cabal create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/repo/libB-0.2.0.0/tags create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/repo/libB-0.3.0.0/Fill.hs create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/repo/libB-0.3.0.0/libB.cabal create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/repo/libB-0.3.0.0/tags diff --git a/Cabal-QuickCheck/src/Test/QuickCheck/Instances/Cabal.hs b/Cabal-QuickCheck/src/Test/QuickCheck/Instances/Cabal.hs index e5b5077d414..91fd47863cf 100644 --- a/Cabal-QuickCheck/src/Test/QuickCheck/Instances/Cabal.hs +++ b/Cabal-QuickCheck/src/Test/QuickCheck/Instances/Cabal.hs @@ -208,6 +208,23 @@ instance Arbitrary Dependency where | (pn', vr', lb') <- shrink (pn, vr, lb) ] +------------------------------------------------------------------------------- +-- Private Dependency +------------------------------------------------------------------------------- + +instance Arbitrary PrivateAlias where + arbitrary = PrivateAlias <$> arbitrary + shrink (PrivateAlias al) = PrivateAlias <$> shrink al +instance Arbitrary PrivateDependency where + arbitrary = PrivateDependency + <$> arbitrary + <*> arbitrary + + shrink (PrivateDependency al dps) = + [ PrivateDependency al' dps' + | (al', dps') <- shrink (al, dps) + ] + ------------------------------------------------------------------------------- -- PackageVersionConstraint ------------------------------------------------------------------------------- diff --git a/Cabal-described/src/Distribution/Described.hs b/Cabal-described/src/Distribution/Described.hs index 717fd6a5c7a..a47126b8247 100644 --- a/Cabal-described/src/Distribution/Described.hs +++ b/Cabal-described/src/Distribution/Described.hs @@ -76,7 +76,7 @@ import Distribution.Types.AbiDependency (AbiDependency) import Distribution.Types.AbiHash (AbiHash) import Distribution.Types.BenchmarkType (BenchmarkType) import Distribution.Types.BuildType (BuildType) -import Distribution.Types.Dependency (Dependency) +import Distribution.Types.Dependency (Dependency, PrivateAlias(..), PrivateDependency) import Distribution.Types.ExecutableScope (ExecutableScope) import Distribution.Types.ExeDependency (ExeDependency) import Distribution.Types.ExposedModule (ExposedModule) @@ -391,6 +391,19 @@ instance Described Dependency where where vr = RENamed "version-range" (describe (Proxy :: Proxy VersionRange)) +instance Described PrivateDependency where + describe _ = REAppend + [ RENamed "alias" (describe (Proxy :: Proxy PrivateAlias)) + , RESpaces1 + , "with" + , RESpaces1 + , reChar '(' + , RESpaces + , REMunch reSpacedComma (describe (Proxy :: Proxy Dependency)) + , RESpaces + , reChar ')' + ] + instance Described ExecutableScope where describe _ = REUnion ["public","private"] @@ -446,6 +459,9 @@ instance Described ModuleName where describe _ = REMunch1 (reChar '.') component where component = RECharSet csUpper <> REMunch reEps (REUnion [RECharSet csAlphaNum, RECharSet (fromString "_'")]) +instance Described PrivateAlias where + describe _ = describe (Proxy :: Proxy ModuleName) + instance Described ModuleReexport where describe _ = RETodo diff --git a/Cabal-syntax/Cabal-syntax.cabal b/Cabal-syntax/Cabal-syntax.cabal index 7cb73b50bae..a1ddd3018df 100644 --- a/Cabal-syntax/Cabal-syntax.cabal +++ b/Cabal-syntax/Cabal-syntax.cabal @@ -135,6 +135,7 @@ library Distribution.Types.Condition Distribution.Types.ConfVar Distribution.Types.Dependency + Distribution.Types.Dependency.Lens Distribution.Types.DependencyMap Distribution.Types.ExeDependency Distribution.Types.Executable diff --git a/Cabal-syntax/src/Distribution/ModuleName.hs b/Cabal-syntax/src/Distribution/ModuleName.hs index 90082d29f06..09f1fddb763 100644 --- a/Cabal-syntax/src/Distribution/ModuleName.hs +++ b/Cabal-syntax/src/Distribution/ModuleName.hs @@ -18,6 +18,7 @@ module Distribution.ModuleName ( ModuleName , fromString , fromComponents + , combineModuleName , components , toFilePath , main @@ -99,12 +100,6 @@ validModuleComponent (c : cs) = isUpper c && all validModuleChar cs instance IsString ModuleName where fromString = ModuleName . toShortText --- | Construct a 'ModuleName' from valid module components, i.e. parts --- separated by dots. -fromComponents :: [String] -> ModuleName -fromComponents comps = fromString (intercalate "." comps) -{-# DEPRECATED fromComponents "Exists for cabal-install only" #-} - -- | The module name @Main@. main :: ModuleName main = ModuleName (fromString "Main") @@ -119,6 +114,19 @@ components mn = split (unModuleName mn) (chunk, []) -> chunk : [] (chunk, _ : rest) -> chunk : split rest +-- | Construct a 'ModuleName' from valid module components, i.e. parts +-- separated by dots. +-- +-- Inverse of 'components', i.e. @fromComponents (components x) = x@ +fromComponents :: [String] -> ModuleName +fromComponents comps = fromString (intercalate "." comps) +{-# DEPRECATED fromComponents "Exists for cabal-install only" #-} + +-- | Append one valid module name onto another valid module name +-- This is used when adding the module suffix to private dependencies +combineModuleName :: ModuleName -> ModuleName -> ModuleName +combineModuleName mn1 mn2 = fromComponents (components mn1 ++ components mn2) + -- | Convert a module name to a file path, but without any file extension. -- For example: -- diff --git a/Cabal-syntax/src/Distribution/PackageDescription/Configuration.hs b/Cabal-syntax/src/Distribution/PackageDescription/Configuration.hs index e811c361221..397c4a40ad0 100644 --- a/Cabal-syntax/src/Distribution/PackageDescription/Configuration.hs +++ b/Cabal-syntax/src/Distribution/PackageDescription/Configuration.hs @@ -31,7 +31,6 @@ module Distribution.PackageDescription.Configuration , mapTreeConstrs , transformAllBuildInfos , transformAllBuildDepends - , transformAllBuildDependsN , simplifyWithSysParams ) where @@ -63,6 +62,7 @@ import Distribution.Version import qualified Data.Map.Lazy as Map import Data.Tree (Tree (Node)) +import qualified Distribution.Types.Dependency.Lens as L ------------------------------------------------------------------------------ @@ -187,12 +187,12 @@ resolveWithFlags -- ^ Arch where the installed artifacts will run (host Arch) -> CompilerInfo -- ^ Compiler information - -> [PackageVersionConstraint] + -> [(IsPrivate, PackageVersionConstraint)] -- ^ Additional constraints - -> [CondTree ConfVar [Dependency] PDTagged] - -> ([Dependency] -> DepTestRslt [Dependency]) + -> [CondTree ConfVar Dependencies PDTagged] + -> (Dependencies -> DepTestRslt Dependencies) -- ^ Dependency test function. - -> Either [Dependency] (TargetSet PDTagged, FlagAssignment) + -> Either Dependencies (TargetSet PDTagged, FlagAssignment) -- ^ Either the missing dependencies (error case), or a pair of -- (set of build targets with dependencies, chosen flag assignments) resolveWithFlags dom enabled os arch impl constrs trees checkDeps = @@ -324,7 +324,7 @@ extractConditions f gpkg = ] -- | A map of package constraints that combines version ranges using 'unionVersionRanges'. -newtype DepMapUnion = DepMapUnion {unDepMapUnion :: Map PackageName (VersionRange, NonEmptySet LibraryName)} +newtype DepMapUnion = DepMapUnion {unDepMapUnion :: Map (PackageName, IsPrivate) (VersionRange, NonEmptySet LibraryName)} instance Semigroup DepMapUnion where DepMapUnion x <> DepMapUnion y = @@ -337,12 +337,22 @@ unionVersionRanges' -> (VersionRange, NonEmptySet LibraryName) unionVersionRanges' (vr, cs) (vr', cs') = (unionVersionRanges vr vr', cs <> cs') -toDepMapUnion :: [Dependency] -> DepMapUnion +toDepMapUnion :: Dependencies -> DepMapUnion toDepMapUnion ds = - DepMapUnion $ Map.fromListWith unionVersionRanges' [(p, (vr, cs)) | Dependency p vr cs <- ds] + DepMapUnion $ + Map.fromListWith + unionVersionRanges' + ( [((p, Public), (vr, cs)) | Dependency p vr cs <- publicDependencies ds] + ++ [((p, Private (private_alias d)), (vr, cs)) | d <- privateDependencies ds, Dependency p vr cs <- private_depends d] + ) -fromDepMapUnion :: DepMapUnion -> [Dependency] -fromDepMapUnion m = [Dependency p vr cs | (p, (vr, cs)) <- Map.toList (unDepMapUnion m)] +fromDepMapUnion :: DepMapUnion -> Dependencies +fromDepMapUnion m = + Dependencies + [Dependency p vr cs | ((p, Public), (vr, cs)) <- Map.toList (unDepMapUnion m)] + [PrivateDependency alias deps | (alias, deps) <- Map.toList priv_deps] + where + priv_deps = Map.fromListWith (++) [(sn, [Dependency p vr cs]) | ((p, Private sn), (vr, cs)) <- Map.toList (unDepMapUnion m)] freeVars :: CondTree ConfVar c a -> [FlagName] freeVars t = [f | PackageFlag f <- freeVars' t] @@ -400,8 +410,9 @@ flattenTaggedTargets (TargetSet targets) = foldr untag (Nothing, []) targets | otherwise -> (mb_lib, (n, redoBD c) : comps) (PDNull, x) -> x -- actually this should not happen, but let's be liberal where + deps = fromDepMap depMap redoBD :: L.HasBuildInfo a => a -> a - redoBD = set L.targetBuildDepends $ fromDepMap depMap + redoBD = set L.targetPrivateBuildDepends (privateDependencies deps) . set L.targetBuildDepends (publicDependencies deps) ------------------------------------------------------------------------------ -- Convert GenericPackageDescription to PackageDescription @@ -453,7 +464,7 @@ finalizePD :: FlagAssignment -- ^ Explicitly specified flag assignments -> ComponentRequestedSpec - -> (Dependency -> Bool) + -> (Maybe PrivateAlias -> Dependency -> Bool) -- ^ Is a given dependency satisfiable from the set of -- available packages? If this is unknown then use -- True. @@ -461,11 +472,11 @@ finalizePD -- ^ The 'Arch' and 'OS' -> CompilerInfo -- ^ Compiler information - -> [PackageVersionConstraint] + -> [(IsPrivate, PackageVersionConstraint)] -- ^ Additional constraints -> GenericPackageDescription -> Either - [Dependency] + Dependencies (PackageDescription, FlagAssignment) -- ^ Either missing dependencies or the resolved package -- description along with the flag assignments chosen. @@ -526,8 +537,11 @@ finalizePD | otherwise -> [b, not b] -- flagDefaults = map (\(n,x:_) -> (n,x)) flagChoices check ds = - let missingDeps = filter (not . satisfyDep) ds - in if null missingDeps + let missingDeps = + Dependencies + (filter (not . satisfyDep Nothing) (publicDependencies ds)) + (mapMaybe (\(PrivateDependency priv pds) -> case filter (not . satisfyDep (Just priv)) pds of [] -> Nothing; pds' -> Just (PrivateDependency priv pds')) (privateDependencies ds)) + in if null (publicDependencies missingDeps) && null (privateDependencies missingDeps) then DepOk else MissingDeps missingDeps @@ -652,19 +666,8 @@ transformAllBuildDepends -> GenericPackageDescription -> GenericPackageDescription transformAllBuildDepends f = - over (L.traverseBuildInfos . L.targetBuildDepends . traverse) f + over (L.traverseBuildInfos . L.targetPrivateBuildDepends . traverse . L.private_depends . traverse) f + . over (L.traverseBuildInfos . L.targetBuildDepends . traverse) f . over (L.packageDescription . L.setupBuildInfo . traverse . L.setupDepends . traverse) f -- cannot be point-free as normal because of higher rank - . over (\f' -> L.allCondTrees $ traverseCondTreeC f') (map f) - --- | Walk a 'GenericPackageDescription' and apply @f@ to all nested --- @build-depends@ fields. -transformAllBuildDependsN - :: ([Dependency] -> [Dependency]) - -> GenericPackageDescription - -> GenericPackageDescription -transformAllBuildDependsN f = - over (L.traverseBuildInfos . L.targetBuildDepends) f - . over (L.packageDescription . L.setupBuildInfo . traverse . L.setupDepends) f - -- cannot be point-free as normal because of higher rank - . over (\f' -> L.allCondTrees $ traverseCondTreeC f') f + . over (\f' -> L.allCondTrees $ traverseCondTreeC f') (mapDependencies f) diff --git a/Cabal-syntax/src/Distribution/PackageDescription/FieldGrammar.hs b/Cabal-syntax/src/Distribution/PackageDescription/FieldGrammar.hs index db6b7f7607b..1f3e2a90bc2 100644 --- a/Cabal-syntax/src/Distribution/PackageDescription/FieldGrammar.hs +++ b/Cabal-syntax/src/Distribution/PackageDescription/FieldGrammar.hs @@ -171,6 +171,7 @@ libraryFieldGrammar , c (List CommaFSep (Identity LegacyExeDependency) LegacyExeDependency) , c (List CommaFSep (Identity PkgconfigDependency) PkgconfigDependency) , c (List CommaVCat (Identity Dependency) Dependency) + , c (List CommaVCat (Identity PrivateDependency) PrivateDependency) , c (List CommaVCat (Identity Mixin) Mixin) , c (List CommaVCat (Identity ModuleReexport) ModuleReexport) , c (List FSep (MQuoted Extension) Extension) @@ -220,6 +221,7 @@ foreignLibFieldGrammar , c (List CommaFSep (Identity ExeDependency) ExeDependency) , c (List CommaFSep (Identity LegacyExeDependency) LegacyExeDependency) , c (List CommaFSep (Identity PkgconfigDependency) PkgconfigDependency) + , c (List CommaVCat (Identity PrivateDependency) PrivateDependency) , c (List CommaVCat (Identity Dependency) Dependency) , c (List CommaVCat (Identity Mixin) Mixin) , c (List FSep (Identity ForeignLibOption) ForeignLibOption) @@ -260,6 +262,7 @@ executableFieldGrammar , c (List CommaFSep (Identity LegacyExeDependency) LegacyExeDependency) , c (List CommaFSep (Identity PkgconfigDependency) PkgconfigDependency) , c (List CommaVCat (Identity Dependency) Dependency) + , c (List CommaVCat (Identity PrivateDependency) PrivateDependency) , c (List CommaVCat (Identity Mixin) Mixin) , c (List FSep (MQuoted Extension) Extension) , c (List FSep (MQuoted Language) Language) @@ -336,6 +339,7 @@ testSuiteFieldGrammar , c (List CommaFSep (Identity PkgconfigDependency) PkgconfigDependency) , c (List CommaFSep Token String) , c (List CommaVCat (Identity Dependency) Dependency) + , c (List CommaVCat (Identity PrivateDependency) PrivateDependency) , c (List CommaVCat (Identity Mixin) Mixin) , c (List FSep (MQuoted Extension) Extension) , c (List FSep (MQuoted Language) Language) @@ -480,6 +484,7 @@ benchmarkFieldGrammar , c (List CommaFSep (Identity LegacyExeDependency) LegacyExeDependency) , c (List CommaFSep (Identity PkgconfigDependency) PkgconfigDependency) , c (List CommaVCat (Identity Dependency) Dependency) + , c (List CommaVCat (Identity PrivateDependency) PrivateDependency) , c (List CommaVCat (Identity Mixin) Mixin) , c (List FSep (MQuoted Extension) Extension) , c (List FSep (MQuoted Language) Language) @@ -582,6 +587,7 @@ buildInfoFieldGrammar , c (List CommaFSep (Identity LegacyExeDependency) LegacyExeDependency) , c (List CommaFSep (Identity PkgconfigDependency) PkgconfigDependency) , c (List CommaVCat (Identity Dependency) Dependency) + , c (List CommaVCat (Identity PrivateDependency) PrivateDependency) , c (List CommaVCat (Identity Mixin) Mixin) , c (List FSep (MQuoted Extension) Extension) , c (List FSep (MQuoted Language) Language) @@ -676,6 +682,7 @@ buildInfoFieldGrammar = <*> pure mempty -- static-options ??? <*> prefixedFields "x-" L.customFieldsBI <*> monoidalFieldAla "build-depends" formatDependencyList L.targetBuildDepends + <*> monoidalFieldAla "private-build-depends" formatPrivateDependencyList L.targetPrivateBuildDepends <*> monoidalFieldAla "mixins" formatMixinList L.mixins ^^^ availableSince CabalSpecV2_0 [] {-# SPECIALIZE buildInfoFieldGrammar :: ParsecFieldGrammar' BuildInfo #-} @@ -800,6 +807,9 @@ setupBInfoFieldGrammar def = formatDependencyList :: [Dependency] -> List CommaVCat (Identity Dependency) Dependency formatDependencyList = alaList CommaVCat +formatPrivateDependencyList :: [PrivateDependency] -> List CommaVCat (Identity PrivateDependency) PrivateDependency +formatPrivateDependencyList = alaList CommaVCat + formatMixinList :: [Mixin] -> List CommaVCat (Identity Mixin) Mixin formatMixinList = alaList CommaVCat diff --git a/Cabal-syntax/src/Distribution/PackageDescription/Parsec.hs b/Cabal-syntax/src/Distribution/PackageDescription/Parsec.hs index ae4c0cfec6b..3294fb4fec1 100644 --- a/Cabal-syntax/src/Distribution/PackageDescription/Parsec.hs +++ b/Cabal-syntax/src/Distribution/PackageDescription/Parsec.hs @@ -64,6 +64,7 @@ import qualified Data.Set as Set import qualified Distribution.Compat.Newtype as Newtype import qualified Distribution.Compat.NonEmptySet as NES import qualified Distribution.Types.BuildInfo.Lens as L +import qualified Distribution.Types.Dependency.Lens as L import qualified Distribution.Types.Executable.Lens as L import qualified Distribution.Types.ForeignLib.Lens as L import qualified Distribution.Types.GenericPackageDescription.Lens as L @@ -264,7 +265,7 @@ goSections specVer = traverse_ process -> Map String CondTreeBuildInfo -- \^ common stanzas -> [Field Position] - -> ParseResult (CondTree ConfVar [Dependency] a) + -> ParseResult (CondTree ConfVar Dependencies a) parseCondTree' = parseCondTreeWithCommonStanzas specVer parseSection :: Name Position -> [SectionArg Position] -> [Field Position] -> SectionParser () @@ -480,10 +481,10 @@ parseCondTree -- ^ common stanzas -> (BuildInfo -> a) -- ^ constructor from buildInfo - -> (a -> [Dependency]) + -> (a -> Dependencies) -- ^ condition extractor -> [Field Position] - -> ParseResult (CondTree ConfVar [Dependency] a) + -> ParseResult (CondTree ConfVar Dependencies a) parseCondTree v hasElif grammar commonStanzas fromBuildInfo cond = go where go fields0 = do @@ -497,7 +498,7 @@ parseCondTree v hasElif grammar commonStanzas fromBuildInfo cond = go branches <- concat <$> traverse parseIfs ss return $ endo $ CondNode x (cond x) branches - parseIfs :: [Section Position] -> ParseResult [CondBranch ConfVar [Dependency] a] + parseIfs :: [Section Position] -> ParseResult [CondBranch ConfVar Dependencies a] parseIfs [] = return [] parseIfs (MkSection (Name _ name) test fields : sections) | name == "if" = do test' <- parseConditionConfVar test @@ -510,7 +511,7 @@ parseCondTree v hasElif grammar commonStanzas fromBuildInfo cond = go parseElseIfs :: [Section Position] - -> ParseResult (Maybe (CondTree ConfVar [Dependency] a), [CondBranch ConfVar [Dependency] a]) + -> ParseResult (Maybe (CondTree ConfVar Dependencies a), [CondBranch ConfVar Dependencies a]) parseElseIfs [] = return (Nothing, []) parseElseIfs (MkSection (Name pos name) args fields : sections) | name == "else" = do unless (null args) $ @@ -589,7 +590,7 @@ with new AST, this all need to be rewritten. -- The approach is simple, and have good properties: -- -- * Common stanzas are parsed exactly once, even if not-used. Thus we report errors in them. -type CondTreeBuildInfo = CondTree ConfVar [Dependency] BuildInfo +type CondTreeBuildInfo = CondTree ConfVar Dependencies BuildInfo -- | Create @a@ from 'BuildInfo'. -- This class is used to implement common stanza parsing. @@ -631,10 +632,10 @@ parseCondTreeWithCommonStanzas -> Map String CondTreeBuildInfo -- ^ common stanzas -> [Field Position] - -> ParseResult (CondTree ConfVar [Dependency] a) + -> ParseResult (CondTree ConfVar Dependencies a) parseCondTreeWithCommonStanzas v grammar fromBuildInfo commonStanzas fields = do (fields', endo) <- processImports v fromBuildInfo commonStanzas fields - x <- parseCondTree v hasElif grammar commonStanzas fromBuildInfo (view L.targetBuildDepends) fields' + x <- parseCondTree v hasElif grammar commonStanzas fromBuildInfo (\bi -> Dependencies (view L.targetBuildDepends bi) (view L.targetPrivateBuildDepends bi)) fields' return (endo x) where hasElif = specHasElif v @@ -648,7 +649,7 @@ processImports -> Map String CondTreeBuildInfo -- ^ common stanzas -> [Field Position] - -> ParseResult ([Field Position], CondTree ConfVar [Dependency] a -> CondTree ConfVar [Dependency] a) + -> ParseResult ([Field Position], CondTree ConfVar Dependencies a -> CondTree ConfVar Dependencies a) processImports v fromBuildInfo commonStanzas = go [] where hasCommonStanzas = specHasCommonStanzas v @@ -691,11 +692,11 @@ warnImport _ f = pure (Just f) mergeCommonStanza :: L.HasBuildInfo a => (BuildInfo -> a) - -> CondTree ConfVar [Dependency] BuildInfo - -> CondTree ConfVar [Dependency] a - -> CondTree ConfVar [Dependency] a + -> CondTree ConfVar Dependencies BuildInfo + -> CondTree ConfVar Dependencies a + -> CondTree ConfVar Dependencies a mergeCommonStanza fromBuildInfo (CondNode bi _ bis) (CondNode x _ cs) = - CondNode x' (x' ^. L.targetBuildDepends) cs' + CondNode x' (Dependencies (view L.targetBuildDepends x') (view L.targetPrivateBuildDepends x')) cs' where -- new value is old value with buildInfo field _prepended_. x' = x & L.buildInfo %~ (bi <>) @@ -814,7 +815,8 @@ postProcessInternalDeps specVer gpd where transformBI :: BuildInfo -> BuildInfo transformBI = - over L.targetBuildDepends (concatMap transformD) + over (L.targetPrivateBuildDepends . traverse . L.private_depends) (concatMap transformD) + . over L.targetBuildDepends (concatMap transformD) . over L.mixins (map transformM) transformSBI :: SetupBuildInfo -> SetupBuildInfo diff --git a/Cabal-syntax/src/Distribution/PackageDescription/PrettyPrint.hs b/Cabal-syntax/src/Distribution/PackageDescription/PrettyPrint.hs index b03b1b99ada..425b273aeb2 100644 --- a/Cabal-syntax/src/Distribution/PackageDescription/PrettyPrint.hs +++ b/Cabal-syntax/src/Distribution/PackageDescription/PrettyPrint.hs @@ -61,6 +61,7 @@ import Text.PrettyPrint (Doc, char, hsep, parens, text) import qualified Data.ByteString.Lazy.Char8 as BS.Char8 import qualified Distribution.Compat.NonEmptySet as NES +import qualified Distribution.Types.Dependency.Lens as L -- | Writes a .cabal file from a generic package description writeGenericPackageDescription :: FilePath -> GenericPackageDescription -> IO () @@ -121,7 +122,7 @@ ppFlag v flag@(MkPackageFlag name _ _ _) = PrettySection () "flag" [ppFlagName name] $ prettyFieldGrammar v (flagFieldGrammar name) flag -ppCondTree2 :: CabalSpecVersion -> PrettyFieldGrammar' s -> CondTree ConfVar [Dependency] s -> [PrettyField ()] +ppCondTree2 :: CabalSpecVersion -> PrettyFieldGrammar' s -> CondTree ConfVar Dependencies s -> [PrettyField ()] ppCondTree2 v grammar = go where -- TODO: recognise elif opportunities @@ -140,42 +141,42 @@ ppCondTree2 v grammar = go , PrettySection () "else" [] (go elseTree) ] -ppCondLibrary :: CabalSpecVersion -> Maybe (CondTree ConfVar [Dependency] Library) -> [PrettyField ()] +ppCondLibrary :: CabalSpecVersion -> Maybe (CondTree ConfVar Dependencies Library) -> [PrettyField ()] ppCondLibrary _ Nothing = mempty ppCondLibrary v (Just condTree) = pure $ PrettySection () "library" [] $ ppCondTree2 v (libraryFieldGrammar LMainLibName) condTree -ppCondSubLibraries :: CabalSpecVersion -> [(UnqualComponentName, CondTree ConfVar [Dependency] Library)] -> [PrettyField ()] +ppCondSubLibraries :: CabalSpecVersion -> [(UnqualComponentName, CondTree ConfVar Dependencies Library)] -> [PrettyField ()] ppCondSubLibraries v libs = [ PrettySection () "library" [pretty n] $ ppCondTree2 v (libraryFieldGrammar $ LSubLibName n) condTree | (n, condTree) <- libs ] -ppCondForeignLibs :: CabalSpecVersion -> [(UnqualComponentName, CondTree ConfVar [Dependency] ForeignLib)] -> [PrettyField ()] +ppCondForeignLibs :: CabalSpecVersion -> [(UnqualComponentName, CondTree ConfVar Dependencies ForeignLib)] -> [PrettyField ()] ppCondForeignLibs v flibs = [ PrettySection () "foreign-library" [pretty n] $ ppCondTree2 v (foreignLibFieldGrammar n) condTree | (n, condTree) <- flibs ] -ppCondExecutables :: CabalSpecVersion -> [(UnqualComponentName, CondTree ConfVar [Dependency] Executable)] -> [PrettyField ()] +ppCondExecutables :: CabalSpecVersion -> [(UnqualComponentName, CondTree ConfVar Dependencies Executable)] -> [PrettyField ()] ppCondExecutables v exes = [ PrettySection () "executable" [pretty n] $ ppCondTree2 v (executableFieldGrammar n) condTree | (n, condTree) <- exes ] -ppCondTestSuites :: CabalSpecVersion -> [(UnqualComponentName, CondTree ConfVar [Dependency] TestSuite)] -> [PrettyField ()] +ppCondTestSuites :: CabalSpecVersion -> [(UnqualComponentName, CondTree ConfVar Dependencies TestSuite)] -> [PrettyField ()] ppCondTestSuites v suites = [ PrettySection () "test-suite" [pretty n] $ ppCondTree2 v testSuiteFieldGrammar (fmap FG.unvalidateTestSuite condTree) | (n, condTree) <- suites ] -ppCondBenchmarks :: CabalSpecVersion -> [(UnqualComponentName, CondTree ConfVar [Dependency] Benchmark)] -> [PrettyField ()] +ppCondBenchmarks :: CabalSpecVersion -> [(UnqualComponentName, CondTree ConfVar Dependencies Benchmark)] -> [PrettyField ()] ppCondBenchmarks v suites = [ PrettySection () "benchmark" [pretty n] $ ppCondTree2 v benchmarkFieldGrammar (fmap FG.unvalidateBenchmark condTree) @@ -239,16 +240,16 @@ pdToGpd pd = , condBenchmarks = mkCondTree' benchmarkName <$> benchmarks pd } where - -- We set CondTree's [Dependency] to an empty list, as it + -- We set CondTree's Dependencies to an empty list, as it -- is not pretty printed anyway. - mkCondTree x = CondNode x [] [] - mkCondTreeL l = (fromMaybe (mkUnqualComponentName "") (libraryNameString (libName l)), CondNode l [] []) + mkCondTree x = CondNode x mempty mempty + mkCondTreeL l = (fromMaybe (mkUnqualComponentName "") (libraryNameString (libName l)), CondNode l mempty mempty) mkCondTree' :: (a -> UnqualComponentName) -> a - -> (UnqualComponentName, CondTree ConfVar [Dependency] a) - mkCondTree' f x = (f x, CondNode x [] []) + -> (UnqualComponentName, CondTree ConfVar Dependencies a) + mkCondTree' f x = (f x, CondNode x mempty []) ------------------------------------------------------------------------------- -- Internal libs @@ -263,7 +264,8 @@ preProcessInternalDeps specVer gpd where transformBI :: BuildInfo -> BuildInfo transformBI = - over L.targetBuildDepends (concatMap transformD) + over (L.targetPrivateBuildDepends . traverse . L.private_depends) (concatMap transformD) + . over L.targetBuildDepends (concatMap transformD) . over L.mixins (map transformM) transformSBI :: SetupBuildInfo -> SetupBuildInfo diff --git a/Cabal-syntax/src/Distribution/Types/BuildInfo.hs b/Cabal-syntax/src/Distribution/Types/BuildInfo.hs index da1f8aea88f..5fd8e737b9f 100644 --- a/Cabal-syntax/src/Distribution/Types/BuildInfo.hs +++ b/Cabal-syntax/src/Distribution/Types/BuildInfo.hs @@ -140,6 +140,7 @@ data BuildInfo = BuildInfo -- simple assoc-list. , targetBuildDepends :: [Dependency] -- ^ Dependencies specific to a library or executable target + , targetPrivateBuildDepends :: [PrivateDependency] , mixins :: [Mixin] } deriving (Generic, Show, Read, Eq, Ord, Typeable, Data) @@ -196,6 +197,7 @@ instance Monoid BuildInfo where , staticOptions = mempty , customFieldsBI = [] , targetBuildDepends = [] + , targetPrivateBuildDepends = [] , mixins = [] } mappend = (<>) @@ -248,6 +250,7 @@ instance Semigroup BuildInfo where , staticOptions = combine staticOptions , customFieldsBI = combine customFieldsBI , targetBuildDepends = combineNub targetBuildDepends + , targetPrivateBuildDepends = combineNub targetPrivateBuildDepends , mixins = combine mixins } where diff --git a/Cabal-syntax/src/Distribution/Types/BuildInfo/Lens.hs b/Cabal-syntax/src/Distribution/Types/BuildInfo/Lens.hs index 19453a671b9..84b49ad7bb1 100644 --- a/Cabal-syntax/src/Distribution/Types/BuildInfo/Lens.hs +++ b/Cabal-syntax/src/Distribution/Types/BuildInfo/Lens.hs @@ -13,7 +13,7 @@ import Prelude () import Distribution.Compiler (PerCompilerFlavor) import Distribution.ModuleName (ModuleName) import Distribution.Types.BuildInfo (BuildInfo) -import Distribution.Types.Dependency (Dependency) +import Distribution.Types.Dependency (Dependency, PrivateDependency) import Distribution.Types.ExeDependency (ExeDependency) import Distribution.Types.LegacyExeDependency (LegacyExeDependency) import Distribution.Types.Mixin (Mixin) @@ -207,6 +207,10 @@ class HasBuildInfo a where targetBuildDepends = buildInfo . targetBuildDepends {-# INLINE targetBuildDepends #-} + targetPrivateBuildDepends :: Lens' a [PrivateDependency] + targetPrivateBuildDepends = buildInfo . targetPrivateBuildDepends + {-# INLINE targetPrivateBuildDepends #-} + mixins :: Lens' a [Mixin] mixins = buildInfo . mixins {-# INLINE mixins #-} @@ -350,6 +354,9 @@ instance HasBuildInfo BuildInfo where targetBuildDepends f s = fmap (\x -> s{T.targetBuildDepends = x}) (f (T.targetBuildDepends s)) {-# INLINE targetBuildDepends #-} + targetPrivateBuildDepends f s = fmap (\x -> s{T.targetPrivateBuildDepends = x}) (f (T.targetPrivateBuildDepends s)) + {-# INLINE targetPrivateBuildDepends #-} + mixins f s = fmap (\x -> s{T.mixins = x}) (f (T.mixins s)) {-# INLINE mixins #-} diff --git a/Cabal-syntax/src/Distribution/Types/ComponentName.hs b/Cabal-syntax/src/Distribution/Types/ComponentName.hs index 01ed6f7655f..2b791bb50cc 100644 --- a/Cabal-syntax/src/Distribution/Types/ComponentName.hs +++ b/Cabal-syntax/src/Distribution/Types/ComponentName.hs @@ -8,6 +8,7 @@ module Distribution.Types.ComponentName , componentNameRaw , componentNameStanza , componentNameString + , NotLibComponentName (..) ) where import Distribution.Compat.Prelude diff --git a/Cabal-syntax/src/Distribution/Types/Dependency.hs b/Cabal-syntax/src/Distribution/Types/Dependency.hs index 10d0506b57e..a50c863d6bd 100644 --- a/Cabal-syntax/src/Distribution/Types/Dependency.hs +++ b/Cabal-syntax/src/Distribution/Types/Dependency.hs @@ -1,5 +1,7 @@ {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE InstanceSigs #-} +{-# LANGUAGE ScopedTypeVariables #-} module Distribution.Types.Dependency ( Dependency (..) @@ -9,6 +11,11 @@ module Distribution.Types.Dependency , depLibraries , simplifyDependency , mainLibSet + , PrivateDependency (..) + , PrivateAlias (..) + , Dependencies (..) + , IsPrivate (..) + , mapDependencies ) where import Distribution.Compat.Prelude @@ -26,9 +33,55 @@ import Distribution.Types.LibraryName import Distribution.Types.PackageName import Distribution.Types.UnqualComponentName +import qualified Distribution.Compat.CharParsing as P import qualified Distribution.Compat.NonEmptySet as NES +import Distribution.ModuleName import qualified Text.PrettyPrint as PP +data IsPrivate = Private PrivateAlias | Public deriving (Show, Ord, Read, Eq) + +data Dependencies = Dependencies {publicDependencies :: [Dependency], privateDependencies :: [PrivateDependency]} deriving (Eq, Show, Generic, Data) + +newtype PrivateAlias = PrivateAlias ModuleName deriving (Show, Eq, Generic, Data, Read, Ord) + +instance Pretty PrivateAlias where + pretty (PrivateAlias p) = pretty p + +instance Parsec PrivateAlias where + parsec = PrivateAlias <$> parsec + +-- | Construct a 'PrivateAlias' from a valid module name 'String'. +-- +-- This is just a convenience function intended for valid module strings. It is +-- an error if it is used with a string that is not a valid module name. If you +-- are parsing user input then use 'Distribution.Text.simpleParse' instead. +instance IsString PrivateAlias where + fromString = PrivateAlias . fromString + +data PrivateDependency = PrivateDependency {private_alias :: PrivateAlias, private_depends :: [Dependency]} deriving (Eq, Show, Generic, Data, Read, Ord) + +instance Parsec PrivateDependency where + parsec = do + alias <- parsec + P.spaces + _ <- P.string "with" + P.spaces + let parensLax p = P.between (P.char '(' >> P.spaces) (P.char ')' >> P.spaces) p + deps <- parensLax (parsecCommaList parsec) + return (PrivateDependency alias deps) + +instance Pretty PrivateDependency where + pretty (PrivateDependency alias deps) = PP.hsep [pretty alias, PP.text "with", PP.parens (PP.hsep (PP.punctuate PP.comma (map pretty deps)))] + +instance Semigroup Dependencies where + (Dependencies p1 pr1) <> (Dependencies p2 pr2) = Dependencies (p1 <> p2) (pr1 <> pr2) + +instance Monoid Dependencies where + mempty = Dependencies mempty mempty + +mapDependencies :: (Dependency -> Dependency) -> Dependencies -> Dependencies +mapDependencies f (Dependencies pub priv) = Dependencies (map f pub) (map (\d -> d{private_depends = map f (private_depends d)}) priv) + -- | Describes a dependency on a source package (API) -- -- /Invariant:/ package name does not appear as 'LSubLibName' in @@ -76,6 +129,18 @@ instance Binary Dependency instance Structured Dependency instance NFData Dependency where rnf = genericRnf +instance Binary PrivateDependency +instance Structured PrivateDependency +instance NFData PrivateDependency where rnf = genericRnf + +instance Binary PrivateAlias +instance Structured PrivateAlias +instance NFData PrivateAlias where rnf = genericRnf + +instance Binary Dependencies +instance Structured Dependencies +instance NFData Dependencies where rnf = genericRnf + -- | -- -- >>> prettyShow $ Dependency (mkPackageName "pkg") anyVersion mainLibSet @@ -139,6 +204,7 @@ instance Pretty Dependency where -- >>> map (`simpleParsec'` "mylib:sub") [CabalSpecV2_4, CabalSpecV3_0] :: [Maybe Dependency] -- [Nothing,Just (Dependency (PackageName "mylib") (OrLaterVersion (mkVersion [0])) (fromNonEmpty (LSubLibName (UnqualComponentName "sub") :| [])))] instance Parsec Dependency where + parsec :: forall m. CabalParsing m => m Dependency parsec = do name <- parsec diff --git a/Cabal-syntax/src/Distribution/Types/Dependency/Lens.hs b/Cabal-syntax/src/Distribution/Types/Dependency/Lens.hs new file mode 100644 index 00000000000..8dfb9d5bd27 --- /dev/null +++ b/Cabal-syntax/src/Distribution/Types/Dependency/Lens.hs @@ -0,0 +1,14 @@ +module Distribution.Types.Dependency.Lens + ( private_depends + ) where + +import Distribution.Compat.Lens +import Distribution.Compat.Prelude +import Prelude () + +import Distribution.Types.Dependency (Dependency, PrivateDependency) + +import qualified Distribution.Types.Dependency as T + +private_depends :: Lens' PrivateDependency [Dependency] +private_depends f d = fmap (\x -> d{T.private_depends = x}) (f (T.private_depends d)) diff --git a/Cabal-syntax/src/Distribution/Types/DependencyMap.hs b/Cabal-syntax/src/Distribution/Types/DependencyMap.hs index aebca2c4cbf..c7175d21404 100644 --- a/Cabal-syntax/src/Distribution/Types/DependencyMap.hs +++ b/Cabal-syntax/src/Distribution/Types/DependencyMap.hs @@ -18,7 +18,7 @@ import qualified Data.Map.Lazy as Map -- | A map of dependencies. Newtyped since the default monoid instance is not -- appropriate. The monoid instance uses 'intersectVersionRanges'. -newtype DependencyMap = DependencyMap {unDependencyMap :: Map PackageName (VersionRange, NonEmptySet LibraryName)} +newtype DependencyMap = DependencyMap {unDependencyMap :: Map (PackageName, IsPrivate) (VersionRange, NonEmptySet LibraryName)} deriving (Show, Read, Eq) instance Monoid DependencyMap where @@ -36,12 +36,22 @@ intersectVersionRangesAndJoinComponents intersectVersionRangesAndJoinComponents (va, ca) (vb, cb) = (intersectVersionRanges va vb, ca <> cb) -toDepMap :: [Dependency] -> DependencyMap +toDepMap :: Dependencies -> DependencyMap toDepMap ds = - DependencyMap $ Map.fromListWith intersectVersionRangesAndJoinComponents [(p, (vr, cs)) | Dependency p vr cs <- ds] + DependencyMap $ + Map.fromListWith + intersectVersionRangesAndJoinComponents + ( [((p, Public), (vr, cs)) | Dependency p vr cs <- publicDependencies ds] + ++ [((p, Private pn), (vr, cs)) | PrivateDependency pn pds <- privateDependencies ds, Dependency p vr cs <- pds] + ) -fromDepMap :: DependencyMap -> [Dependency] -fromDepMap m = [Dependency p vr cs | (p, (vr, cs)) <- Map.toList (unDependencyMap m)] +fromDepMap :: DependencyMap -> Dependencies +fromDepMap m = + Dependencies + [Dependency p vr cs | ((p, Public), (vr, cs)) <- Map.toList (unDependencyMap m)] + [PrivateDependency alias deps | (alias, deps) <- Map.toList priv_deps] + where + priv_deps = Map.fromListWith (++) [(sn, [Dependency p vr cs]) | ((p, (Private sn)), (vr, cs)) <- Map.toList (unDependencyMap m)] -- Apply extra constraints to a dependency map. -- Combines dependencies where the result will only contain keys from the left @@ -49,11 +59,11 @@ fromDepMap m = [Dependency p vr cs | (p, (vr, cs)) <- Map.toList (unDependencyMa -- be intersected. constrainBy :: DependencyMap - -> [PackageVersionConstraint] + -> [(IsPrivate, PackageVersionConstraint)] -> DependencyMap constrainBy = foldl' tightenConstraint where - tightenConstraint (DependencyMap l) (PackageVersionConstraint pn vr) = DependencyMap $ - case Map.lookup pn l of + tightenConstraint (DependencyMap l) (ip, PackageVersionConstraint pn vr) = DependencyMap $ + case Map.lookup (pn, ip) l of Nothing -> l - Just (vr', cs) -> Map.insert pn (intersectVersionRanges vr' vr, cs) l + Just (vr', cs) -> Map.insert (pn, ip) (intersectVersionRanges vr' vr, cs) l diff --git a/Cabal-syntax/src/Distribution/Types/GenericPackageDescription.hs b/Cabal-syntax/src/Distribution/Types/GenericPackageDescription.hs index 55ec8652304..312db47053b 100644 --- a/Cabal-syntax/src/Distribution/Types/GenericPackageDescription.hs +++ b/Cabal-syntax/src/Distribution/Types/GenericPackageDescription.hs @@ -44,30 +44,30 @@ data GenericPackageDescription = GenericPackageDescription -- Perfectly, PackageIndex should have sum type, so we don't need to -- have dummy GPDs. , genPackageFlags :: [PackageFlag] - , condLibrary :: Maybe (CondTree ConfVar [Dependency] Library) + , condLibrary :: Maybe (CondTree ConfVar Dependencies Library) , condSubLibraries :: [ ( UnqualComponentName - , CondTree ConfVar [Dependency] Library + , CondTree ConfVar Dependencies Library ) ] , condForeignLibs :: [ ( UnqualComponentName - , CondTree ConfVar [Dependency] ForeignLib + , CondTree ConfVar Dependencies ForeignLib ) ] , condExecutables :: [ ( UnqualComponentName - , CondTree ConfVar [Dependency] Executable + , CondTree ConfVar Dependencies Executable ) ] , condTestSuites :: [ ( UnqualComponentName - , CondTree ConfVar [Dependency] TestSuite + , CondTree ConfVar Dependencies TestSuite ) ] , condBenchmarks :: [ ( UnqualComponentName - , CondTree ConfVar [Dependency] Benchmark + , CondTree ConfVar Dependencies Benchmark ) ] } @@ -99,15 +99,15 @@ instance L.HasBuildInfos GenericPackageDescription where <*> (traverse . L._2 . traverseCondTreeBuildInfo) f x5 <*> (traverse . L._2 . traverseCondTreeBuildInfo) f x6 --- We use this traversal to keep [Dependency] field in CondTree up to date. +-- We use this traversal to keep Dependencies field in CondTree up to date. traverseCondTreeBuildInfo :: forall f comp v . (Applicative f, L.HasBuildInfo comp) - => LensLike' f (CondTree v [Dependency] comp) L.BuildInfo + => LensLike' f (CondTree v Dependencies comp) L.BuildInfo traverseCondTreeBuildInfo g = node where - mkCondNode :: comp -> [CondBranch v [Dependency] comp] -> CondTree v [Dependency] comp - mkCondNode comp = CondNode comp (view L.targetBuildDepends comp) + mkCondNode :: comp -> [CondBranch v Dependencies comp] -> CondTree v Dependencies comp + mkCondNode comp = CondNode comp (Dependencies (view L.targetBuildDepends comp) (view L.targetPrivateBuildDepends comp)) node (CondNode comp _ branches) = mkCondNode diff --git a/Cabal-syntax/src/Distribution/Types/GenericPackageDescription/Lens.hs b/Cabal-syntax/src/Distribution/Types/GenericPackageDescription/Lens.hs index 213c97128f9..9d6ad5d2a2b 100644 --- a/Cabal-syntax/src/Distribution/Types/GenericPackageDescription/Lens.hs +++ b/Cabal-syntax/src/Distribution/Types/GenericPackageDescription/Lens.hs @@ -22,7 +22,7 @@ import Distribution.System (Arch, OS) import Distribution.Types.Benchmark (Benchmark) import Distribution.Types.CondTree (CondTree) import Distribution.Types.ConfVar (ConfVar (..)) -import Distribution.Types.Dependency (Dependency) +import Distribution.Types.Dependency (Dependencies) import Distribution.Types.Executable (Executable) import Distribution.Types.Flag (FlagName, PackageFlag (MkPackageFlag)) import Distribution.Types.ForeignLib (ForeignLib) @@ -49,35 +49,35 @@ genPackageFlags :: Lens' GenericPackageDescription [PackageFlag] genPackageFlags f s = fmap (\x -> s{T.genPackageFlags = x}) (f (T.genPackageFlags s)) {-# INLINE genPackageFlags #-} -condLibrary :: Lens' GenericPackageDescription (Maybe (CondTree ConfVar [Dependency] Library)) +condLibrary :: Lens' GenericPackageDescription (Maybe (CondTree ConfVar Dependencies Library)) condLibrary f s = fmap (\x -> s{T.condLibrary = x}) (f (T.condLibrary s)) {-# INLINE condLibrary #-} -condSubLibraries :: Lens' GenericPackageDescription [(UnqualComponentName, (CondTree ConfVar [Dependency] Library))] +condSubLibraries :: Lens' GenericPackageDescription [(UnqualComponentName, (CondTree ConfVar Dependencies Library))] condSubLibraries f s = fmap (\x -> s{T.condSubLibraries = x}) (f (T.condSubLibraries s)) {-# INLINE condSubLibraries #-} -condForeignLibs :: Lens' GenericPackageDescription [(UnqualComponentName, (CondTree ConfVar [Dependency] ForeignLib))] +condForeignLibs :: Lens' GenericPackageDescription [(UnqualComponentName, (CondTree ConfVar Dependencies ForeignLib))] condForeignLibs f s = fmap (\x -> s{T.condForeignLibs = x}) (f (T.condForeignLibs s)) {-# INLINE condForeignLibs #-} -condExecutables :: Lens' GenericPackageDescription [(UnqualComponentName, (CondTree ConfVar [Dependency] Executable))] +condExecutables :: Lens' GenericPackageDescription [(UnqualComponentName, (CondTree ConfVar Dependencies Executable))] condExecutables f s = fmap (\x -> s{T.condExecutables = x}) (f (T.condExecutables s)) {-# INLINE condExecutables #-} -condTestSuites :: Lens' GenericPackageDescription [(UnqualComponentName, (CondTree ConfVar [Dependency] TestSuite))] +condTestSuites :: Lens' GenericPackageDescription [(UnqualComponentName, (CondTree ConfVar Dependencies TestSuite))] condTestSuites f s = fmap (\x -> s{T.condTestSuites = x}) (f (T.condTestSuites s)) {-# INLINE condTestSuites #-} -condBenchmarks :: Lens' GenericPackageDescription [(UnqualComponentName, (CondTree ConfVar [Dependency] Benchmark))] +condBenchmarks :: Lens' GenericPackageDescription [(UnqualComponentName, (CondTree ConfVar Dependencies Benchmark))] condBenchmarks f s = fmap (\x -> s{T.condBenchmarks = x}) (f (T.condBenchmarks s)) {-# INLINE condBenchmarks #-} allCondTrees :: Applicative f => ( forall a - . CondTree ConfVar [Dependency] a - -> f (CondTree ConfVar [Dependency] a) + . CondTree ConfVar Dependencies a + -> f (CondTree ConfVar Dependencies a) ) -> GenericPackageDescription -> f GenericPackageDescription diff --git a/Cabal-syntax/src/Distribution/Types/PackageDescription.hs b/Cabal-syntax/src/Distribution/Types/PackageDescription.hs index a3f1d0c33da..cec1014d222 100644 --- a/Cabal-syntax/src/Distribution/Types/PackageDescription.hs +++ b/Cabal-syntax/src/Distribution/Types/PackageDescription.hs @@ -60,8 +60,6 @@ module Distribution.Types.PackageDescription import Distribution.Compat.Prelude import Prelude () -import Control.Monad ((<=<)) - -- lens import Distribution.Types.Benchmark @@ -362,13 +360,20 @@ enabledBuildInfos pkg enabled = -- ------------------------------------------------------------ -- | Get the combined build-depends entries of all components. -allBuildDepends :: PackageDescription -> [Dependency] -allBuildDepends = targetBuildDepends <=< allBuildInfo +allBuildDepends :: PackageDescription -> [(Maybe PrivateAlias, Dependency)] +allBuildDepends pd = do + bi <- allBuildInfo pd + [(Nothing, d) | d <- targetBuildDepends bi] + ++ [(Just p, d) | PrivateDependency p ds <- targetPrivateBuildDepends bi, d <- ds] -- | Get the combined build-depends entries of all enabled components, per the -- given request spec. -enabledBuildDepends :: PackageDescription -> ComponentRequestedSpec -> [Dependency] -enabledBuildDepends spec pd = targetBuildDepends =<< enabledBuildInfos spec pd +enabledBuildDepends :: PackageDescription -> ComponentRequestedSpec -> [(Maybe PrivateAlias, Dependency)] +enabledBuildDepends spec pd = + do + bi <- enabledBuildInfos spec pd + [(Nothing, d) | d <- targetBuildDepends bi] + ++ [(Just p, d) | PrivateDependency p ds <- targetPrivateBuildDepends bi, d <- ds] updatePackageDescription :: HookedBuildInfo -> PackageDescription -> PackageDescription updatePackageDescription (mb_lib_bi, exe_bi) p = diff --git a/Cabal-tests/tests/NoThunks.hs b/Cabal-tests/tests/NoThunks.hs index 6a81475dc03..9bc45114694 100644 --- a/Cabal-tests/tests/NoThunks.hs +++ b/Cabal-tests/tests/NoThunks.hs @@ -79,6 +79,9 @@ instance NoThunks ModuleReexport instance NoThunks LibraryVisibility instance NoThunks ForeignLibType instance NoThunks GenericPackageDescription +instance NoThunks Dependencies +instance NoThunks PrivateDependency +instance NoThunks PrivateAlias instance NoThunks KnownRepoType instance NoThunks Library instance NoThunks LibraryName diff --git a/Cabal-tests/tests/ParserTests/regressions/Octree-0.5.expr b/Cabal-tests/tests/ParserTests/regressions/Octree-0.5.expr index 3d03421210b..14f8b716352 100644 --- a/Cabal-tests/tests/ParserTests/regressions/Octree-0.5.expr +++ b/Cabal-tests/tests/ParserTests/regressions/Octree-0.5.expr @@ -154,26 +154,30 @@ GenericPackageDescription { (OrLaterVersion (mkVersion [2, 4, 0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "base") - (IntersectVersionRanges + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "base") + (IntersectVersionRanges + (OrLaterVersion + (mkVersion [4, 0])) + (EarlierVersion + (mkVersion [4, 7]))) + mainLibSet, + Dependency + (PackageName "AC-Vector") (OrLaterVersion - (mkVersion [4, 0])) - (EarlierVersion - (mkVersion [4, 7]))) - mainLibSet, - Dependency - (PackageName "AC-Vector") - (OrLaterVersion - (mkVersion [2, 3, 0])) - mainLibSet, - Dependency - (PackageName "QuickCheck") - (OrLaterVersion - (mkVersion [2, 4, 0])) - mainLibSet], + (mkVersion [2, 3, 0])) + mainLibSet, + Dependency + (PackageName "QuickCheck") + (OrLaterVersion + (mkVersion [2, 4, 0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}, condSubLibraries = [], condForeignLibs = [], @@ -260,27 +264,31 @@ GenericPackageDescription { (OrLaterVersion (mkVersion [2, 4, 0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}, testCodeGenerators = []}, - condTreeConstraints = [ - Dependency - (PackageName "base") - (IntersectVersionRanges + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "base") + (IntersectVersionRanges + (OrLaterVersion + (mkVersion [4, 0])) + (EarlierVersion + (mkVersion [4, 7]))) + mainLibSet, + Dependency + (PackageName "AC-Vector") (OrLaterVersion - (mkVersion [4, 0])) - (EarlierVersion - (mkVersion [4, 7]))) - mainLibSet, - Dependency - (PackageName "AC-Vector") - (OrLaterVersion - (mkVersion [2, 3, 0])) - mainLibSet, - Dependency - (PackageName "QuickCheck") - (OrLaterVersion - (mkVersion [2, 4, 0])) - mainLibSet], + (mkVersion [2, 3, 0])) + mainLibSet, + Dependency + (PackageName "QuickCheck") + (OrLaterVersion + (mkVersion [2, 4, 0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}, _×_ (UnqualComponentName "readme") @@ -365,30 +373,34 @@ GenericPackageDescription { (PackageName "markdown-unlit") (OrLaterVersion (mkVersion [0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}, testCodeGenerators = []}, - condTreeConstraints = [ - Dependency - (PackageName "base") - (IntersectVersionRanges + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "base") + (IntersectVersionRanges + (OrLaterVersion + (mkVersion [4, 0])) + (EarlierVersion + (mkVersion [4, 7]))) + mainLibSet, + Dependency + (PackageName "AC-Vector") (OrLaterVersion - (mkVersion [4, 0])) - (EarlierVersion - (mkVersion [4, 7]))) - mainLibSet, - Dependency - (PackageName "AC-Vector") - (OrLaterVersion - (mkVersion [2, 3, 0])) - mainLibSet, - Dependency - (PackageName "QuickCheck") - (OrLaterVersion - (mkVersion [2, 4, 0])) - mainLibSet, - Dependency - (PackageName "markdown-unlit") - (OrLaterVersion (mkVersion [0])) - mainLibSet], + (mkVersion [2, 3, 0])) + mainLibSet, + Dependency + (PackageName "QuickCheck") + (OrLaterVersion + (mkVersion [2, 4, 0])) + mainLibSet, + Dependency + (PackageName "markdown-unlit") + (OrLaterVersion (mkVersion [0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}], condBenchmarks = []} diff --git a/Cabal-tests/tests/ParserTests/regressions/anynone.expr b/Cabal-tests/tests/ParserTests/regressions/anynone.expr index 3191425d609..c28388a521e 100644 --- a/Cabal-tests/tests/ParserTests/regressions/anynone.expr +++ b/Cabal-tests/tests/ParserTests/regressions/anynone.expr @@ -103,12 +103,16 @@ GenericPackageDescription { (PackageName "base") (OrLaterVersion (mkVersion [0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "base") - (OrLaterVersion (mkVersion [0])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "base") + (OrLaterVersion (mkVersion [0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}, condSubLibraries = [], condForeignLibs = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/big-version.expr b/Cabal-tests/tests/ParserTests/regressions/big-version.expr index e677de20626..baca580b38a 100644 --- a/Cabal-tests/tests/ParserTests/regressions/big-version.expr +++ b/Cabal-tests/tests/ParserTests/regressions/big-version.expr @@ -100,8 +100,12 @@ GenericPackageDescription { PerCompilerFlavor [] [], customFieldsBI = [], targetBuildDepends = [], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [], + condTreeConstraints = + Dependencies { + publicDependencies = [], + privateDependencies = []}, condTreeComponents = []}, condSubLibraries = [], condForeignLibs = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/common-conditional.expr b/Cabal-tests/tests/ParserTests/regressions/common-conditional.expr index f6ffe291e59..c9ba4e6eed2 100644 --- a/Cabal-tests/tests/ParserTests/regressions/common-conditional.expr +++ b/Cabal-tests/tests/ParserTests/regressions/common-conditional.expr @@ -120,12 +120,16 @@ GenericPackageDescription { (PackageName "ghc-prim") (OrLaterVersion (mkVersion [0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "ghc-prim") - (OrLaterVersion (mkVersion [0])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "ghc-prim") + (OrLaterVersion (mkVersion [0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = [ CondBranch { condBranchCondition = @@ -203,20 +207,24 @@ GenericPackageDescription { (PackageName "containers") (OrLaterVersion (mkVersion [0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "base") - (IntersectVersionRanges - (OrLaterVersion - (mkVersion [4, 10])) - (EarlierVersion - (mkVersion [4, 11]))) - mainLibSet, - Dependency - (PackageName "containers") - (OrLaterVersion (mkVersion [0])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "base") + (IntersectVersionRanges + (OrLaterVersion + (mkVersion [4, 10])) + (EarlierVersion + (mkVersion [4, 11]))) + mainLibSet, + Dependency + (PackageName "containers") + (OrLaterVersion (mkVersion [0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = [ CondBranch { condBranchCondition = @@ -286,12 +294,16 @@ GenericPackageDescription { (PackageName "Win32") (OrLaterVersion (mkVersion [0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "Win32") - (OrLaterVersion (mkVersion [0])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "Win32") + (OrLaterVersion (mkVersion [0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}, condBranchIfFalse = Nothing}]}, condBranchIfFalse = Nothing}]}, @@ -364,13 +376,17 @@ GenericPackageDescription { (PackageName "HUnit") (OrLaterVersion (mkVersion [0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}, testCodeGenerators = []}, - condTreeConstraints = [ - Dependency - (PackageName "HUnit") - (OrLaterVersion (mkVersion [0])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "HUnit") + (OrLaterVersion (mkVersion [0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = [ CondBranch { condBranchCondition = @@ -436,9 +452,13 @@ GenericPackageDescription { PerCompilerFlavor [] [], customFieldsBI = [], targetBuildDepends = [], + targetPrivateBuildDepends = [], mixins = []}, testCodeGenerators = []}, - condTreeConstraints = [], + condTreeConstraints = + Dependencies { + publicDependencies = [], + privateDependencies = []}, condTreeComponents = []}, condBranchIfFalse = Nothing}, CondBranch { @@ -517,21 +537,25 @@ GenericPackageDescription { (PackageName "containers") (OrLaterVersion (mkVersion [0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}, testCodeGenerators = []}, - condTreeConstraints = [ - Dependency - (PackageName "base") - (IntersectVersionRanges - (OrLaterVersion - (mkVersion [4, 10])) - (EarlierVersion - (mkVersion [4, 11]))) - mainLibSet, - Dependency - (PackageName "containers") - (OrLaterVersion (mkVersion [0])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "base") + (IntersectVersionRanges + (OrLaterVersion + (mkVersion [4, 10])) + (EarlierVersion + (mkVersion [4, 11]))) + mainLibSet, + Dependency + (PackageName "containers") + (OrLaterVersion (mkVersion [0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = [ CondBranch { condBranchCondition = @@ -601,13 +625,17 @@ GenericPackageDescription { (PackageName "Win32") (OrLaterVersion (mkVersion [0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}, testCodeGenerators = []}, - condTreeConstraints = [ - Dependency - (PackageName "Win32") - (OrLaterVersion (mkVersion [0])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "Win32") + (OrLaterVersion (mkVersion [0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}, condBranchIfFalse = Nothing}, CondBranch { @@ -678,13 +706,17 @@ GenericPackageDescription { (PackageName "Win32") (OrLaterVersion (mkVersion [0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}, testCodeGenerators = []}, - condTreeConstraints = [ - Dependency - (PackageName "Win32") - (OrLaterVersion (mkVersion [0])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "Win32") + (OrLaterVersion (mkVersion [0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}, condBranchIfFalse = Nothing}]}, condBranchIfFalse = Nothing}]}], diff --git a/Cabal-tests/tests/ParserTests/regressions/common.expr b/Cabal-tests/tests/ParserTests/regressions/common.expr index e0eb4a1dde7..955af0e2ca8 100644 --- a/Cabal-tests/tests/ParserTests/regressions/common.expr +++ b/Cabal-tests/tests/ParserTests/regressions/common.expr @@ -118,12 +118,16 @@ GenericPackageDescription { (PackageName "ghc-prim") (OrLaterVersion (mkVersion [0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "ghc-prim") - (OrLaterVersion (mkVersion [0])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "ghc-prim") + (OrLaterVersion (mkVersion [0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}, condSubLibraries = [], condForeignLibs = [], @@ -194,12 +198,16 @@ GenericPackageDescription { (PackageName "HUnit") (OrLaterVersion (mkVersion [0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}, testCodeGenerators = []}, - condTreeConstraints = [ - Dependency - (PackageName "HUnit") - (OrLaterVersion (mkVersion [0])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "HUnit") + (OrLaterVersion (mkVersion [0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}], condBenchmarks = []} diff --git a/Cabal-tests/tests/ParserTests/regressions/common2.expr b/Cabal-tests/tests/ParserTests/regressions/common2.expr index b3cb004eecb..83596f63a7b 100644 --- a/Cabal-tests/tests/ParserTests/regressions/common2.expr +++ b/Cabal-tests/tests/ParserTests/regressions/common2.expr @@ -126,24 +126,28 @@ GenericPackageDescription { (PackageName "ghc-prim") (OrLaterVersion (mkVersion [0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "base") - (IntersectVersionRanges - (OrLaterVersion - (mkVersion [4, 10])) - (EarlierVersion - (mkVersion [4, 11]))) - mainLibSet, - Dependency - (PackageName "containers") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "ghc-prim") - (OrLaterVersion (mkVersion [0])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "base") + (IntersectVersionRanges + (OrLaterVersion + (mkVersion [4, 10])) + (EarlierVersion + (mkVersion [4, 11]))) + mainLibSet, + Dependency + (PackageName "containers") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "ghc-prim") + (OrLaterVersion (mkVersion [0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = [ CondBranch { condBranchCondition = @@ -213,12 +217,16 @@ GenericPackageDescription { (PackageName "Win32") (OrLaterVersion (mkVersion [0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "Win32") - (OrLaterVersion (mkVersion [0])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "Win32") + (OrLaterVersion (mkVersion [0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}, condBranchIfFalse = Nothing}]}, condSubLibraries = [ @@ -305,24 +313,28 @@ GenericPackageDescription { (PackageName "ghc-prim") (OrLaterVersion (mkVersion [0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "base") - (IntersectVersionRanges - (OrLaterVersion - (mkVersion [4, 10])) - (EarlierVersion - (mkVersion [4, 11]))) - mainLibSet, - Dependency - (PackageName "containers") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "ghc-prim") - (OrLaterVersion (mkVersion [0])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "base") + (IntersectVersionRanges + (OrLaterVersion + (mkVersion [4, 10])) + (EarlierVersion + (mkVersion [4, 11]))) + mainLibSet, + Dependency + (PackageName "containers") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "ghc-prim") + (OrLaterVersion (mkVersion [0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = [ CondBranch { condBranchCondition = @@ -394,12 +406,16 @@ GenericPackageDescription { (PackageName "Win32") (OrLaterVersion (mkVersion [0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "Win32") - (OrLaterVersion (mkVersion [0])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "Win32") + (OrLaterVersion (mkVersion [0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}, condBranchIfFalse = Nothing}]}], condForeignLibs = [], @@ -482,25 +498,29 @@ GenericPackageDescription { (PackageName "HUnit") (OrLaterVersion (mkVersion [0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}, testCodeGenerators = []}, - condTreeConstraints = [ - Dependency - (PackageName "base") - (IntersectVersionRanges - (OrLaterVersion - (mkVersion [4, 10])) - (EarlierVersion - (mkVersion [4, 11]))) - mainLibSet, - Dependency - (PackageName "containers") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "HUnit") - (OrLaterVersion (mkVersion [0])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "base") + (IntersectVersionRanges + (OrLaterVersion + (mkVersion [4, 10])) + (EarlierVersion + (mkVersion [4, 11]))) + mainLibSet, + Dependency + (PackageName "containers") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "HUnit") + (OrLaterVersion (mkVersion [0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = [ CondBranch { condBranchCondition = @@ -570,13 +590,17 @@ GenericPackageDescription { (PackageName "Win32") (OrLaterVersion (mkVersion [0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}, testCodeGenerators = []}, - condTreeConstraints = [ - Dependency - (PackageName "Win32") - (OrLaterVersion (mkVersion [0])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "Win32") + (OrLaterVersion (mkVersion [0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}, condBranchIfFalse = Nothing}, CondBranch { @@ -647,13 +671,17 @@ GenericPackageDescription { (PackageName "Win32") (OrLaterVersion (mkVersion [0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}, testCodeGenerators = []}, - condTreeConstraints = [ - Dependency - (PackageName "Win32") - (OrLaterVersion (mkVersion [0])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "Win32") + (OrLaterVersion (mkVersion [0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}, condBranchIfFalse = Nothing}, CondBranch { @@ -720,9 +748,13 @@ GenericPackageDescription { PerCompilerFlavor [] [], customFieldsBI = [], targetBuildDepends = [], + targetPrivateBuildDepends = [], mixins = []}, testCodeGenerators = []}, - condTreeConstraints = [], + condTreeConstraints = + Dependencies { + publicDependencies = [], + privateDependencies = []}, condTreeComponents = []}, condBranchIfFalse = Nothing}]}], condBenchmarks = []} diff --git a/Cabal-tests/tests/ParserTests/regressions/common3.expr b/Cabal-tests/tests/ParserTests/regressions/common3.expr index 21b200baa7b..acad707bda7 100644 --- a/Cabal-tests/tests/ParserTests/regressions/common3.expr +++ b/Cabal-tests/tests/ParserTests/regressions/common3.expr @@ -118,12 +118,16 @@ GenericPackageDescription { (PackageName "ghc-prim") (OrLaterVersion (mkVersion [0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "ghc-prim") - (OrLaterVersion (mkVersion [0])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "ghc-prim") + (OrLaterVersion (mkVersion [0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}, condSubLibraries = [], condForeignLibs = [], @@ -206,24 +210,28 @@ GenericPackageDescription { (PackageName "HUnit") (OrLaterVersion (mkVersion [0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}, testCodeGenerators = []}, - condTreeConstraints = [ - Dependency - (PackageName "base") - (IntersectVersionRanges - (OrLaterVersion - (mkVersion [4, 10])) - (EarlierVersion - (mkVersion [4, 11]))) - mainLibSet, - Dependency - (PackageName "containers") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "HUnit") - (OrLaterVersion (mkVersion [0])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "base") + (IntersectVersionRanges + (OrLaterVersion + (mkVersion [4, 10])) + (EarlierVersion + (mkVersion [4, 11]))) + mainLibSet, + Dependency + (PackageName "containers") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "HUnit") + (OrLaterVersion (mkVersion [0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}], condBenchmarks = []} diff --git a/Cabal-tests/tests/ParserTests/regressions/elif.expr b/Cabal-tests/tests/ParserTests/regressions/elif.expr index 1315d689467..d22deddf324 100644 --- a/Cabal-tests/tests/ParserTests/regressions/elif.expr +++ b/Cabal-tests/tests/ParserTests/regressions/elif.expr @@ -109,8 +109,12 @@ GenericPackageDescription { PerCompilerFlavor [] [], customFieldsBI = [], targetBuildDepends = [], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [], + condTreeConstraints = + Dependencies { + publicDependencies = [], + privateDependencies = []}, condTreeComponents = [ CondBranch { condBranchCondition = @@ -180,12 +184,16 @@ GenericPackageDescription { (PackageName "unix") (OrLaterVersion (mkVersion [0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "unix") - (OrLaterVersion (mkVersion [0])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "unix") + (OrLaterVersion (mkVersion [0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}, condBranchIfFalse = Nothing}]}, condSubLibraries = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/elif2.expr b/Cabal-tests/tests/ParserTests/regressions/elif2.expr index 61f2177cbaa..ece3c44ab04 100644 --- a/Cabal-tests/tests/ParserTests/regressions/elif2.expr +++ b/Cabal-tests/tests/ParserTests/regressions/elif2.expr @@ -109,8 +109,12 @@ GenericPackageDescription { PerCompilerFlavor [] [], customFieldsBI = [], targetBuildDepends = [], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [], + condTreeConstraints = + Dependencies { + publicDependencies = [], + privateDependencies = []}, condTreeComponents = [ CondBranch { condBranchCondition = @@ -180,12 +184,16 @@ GenericPackageDescription { (PackageName "unix") (OrLaterVersion (mkVersion [0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "unix") - (OrLaterVersion (mkVersion [0])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "unix") + (OrLaterVersion (mkVersion [0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}, condBranchIfFalse = Just CondNode { @@ -249,8 +257,12 @@ GenericPackageDescription { PerCompilerFlavor [] [], customFieldsBI = [], targetBuildDepends = [], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [], + condTreeConstraints = + Dependencies { + publicDependencies = [], + privateDependencies = []}, condTreeComponents = [ CondBranch { condBranchCondition = @@ -320,12 +332,16 @@ GenericPackageDescription { (PackageName "Win32") (OrLaterVersion (mkVersion [0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "Win32") - (OrLaterVersion (mkVersion [0])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "Win32") + (OrLaterVersion (mkVersion [0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}, condBranchIfFalse = Just CondNode { @@ -389,8 +405,12 @@ GenericPackageDescription { PerCompilerFlavor [] [], customFieldsBI = [], targetBuildDepends = [], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [], + condTreeConstraints = + Dependencies { + publicDependencies = [], + privateDependencies = []}, condTreeComponents = []}}]}}]}, condSubLibraries = [], condForeignLibs = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/encoding-0.8.expr b/Cabal-tests/tests/ParserTests/regressions/encoding-0.8.expr index e1b125e7a32..681892c14e0 100644 --- a/Cabal-tests/tests/ParserTests/regressions/encoding-0.8.expr +++ b/Cabal-tests/tests/ParserTests/regressions/encoding-0.8.expr @@ -126,16 +126,20 @@ GenericPackageDescription { (ThisVersion (mkVersion [4, 4]))) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "base") - (UnionVersionRanges - (LaterVersion - (mkVersion [4, 4])) - (ThisVersion - (mkVersion [4, 4]))) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "base") + (UnionVersionRanges + (LaterVersion + (mkVersion [4, 4])) + (ThisVersion + (mkVersion [4, 4]))) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}, condSubLibraries = [], condForeignLibs = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/generics-sop.expr b/Cabal-tests/tests/ParserTests/regressions/generics-sop.expr index 9084371a614..9d721e24db8 100644 --- a/Cabal-tests/tests/ParserTests/regressions/generics-sop.expr +++ b/Cabal-tests/tests/ParserTests/regressions/generics-sop.expr @@ -278,40 +278,44 @@ GenericPackageDescription { (EarlierVersion (mkVersion [1, 5]))) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "base") - (IntersectVersionRanges - (OrLaterVersion - (mkVersion [4, 7])) - (EarlierVersion - (mkVersion [5]))) - mainLibSet, - Dependency - (PackageName "template-haskell") - (IntersectVersionRanges - (OrLaterVersion - (mkVersion [2, 8])) - (EarlierVersion - (mkVersion [2, 13]))) - mainLibSet, - Dependency - (PackageName "ghc-prim") - (IntersectVersionRanges - (OrLaterVersion - (mkVersion [0, 3])) - (EarlierVersion - (mkVersion [0, 6]))) - mainLibSet, - Dependency - (PackageName "deepseq") - (IntersectVersionRanges - (OrLaterVersion - (mkVersion [1, 3])) - (EarlierVersion - (mkVersion [1, 5]))) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "base") + (IntersectVersionRanges + (OrLaterVersion + (mkVersion [4, 7])) + (EarlierVersion + (mkVersion [5]))) + mainLibSet, + Dependency + (PackageName "template-haskell") + (IntersectVersionRanges + (OrLaterVersion + (mkVersion [2, 8])) + (EarlierVersion + (mkVersion [2, 13]))) + mainLibSet, + Dependency + (PackageName "ghc-prim") + (IntersectVersionRanges + (OrLaterVersion + (mkVersion [0, 3])) + (EarlierVersion + (mkVersion [0, 6]))) + mainLibSet, + Dependency + (PackageName "deepseq") + (IntersectVersionRanges + (OrLaterVersion + (mkVersion [1, 3])) + (EarlierVersion + (mkVersion [1, 5]))) + mainLibSet], + privateDependencies = []}, condTreeComponents = [ CondBranch { condBranchCondition = @@ -385,16 +389,20 @@ GenericPackageDescription { (EarlierVersion (mkVersion [0, 9]))) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "tagged") - (IntersectVersionRanges - (OrLaterVersion - (mkVersion [0, 7])) - (EarlierVersion - (mkVersion [0, 9]))) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "tagged") + (IntersectVersionRanges + (OrLaterVersion + (mkVersion [0, 7])) + (EarlierVersion + (mkVersion [0, 9]))) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}, condBranchIfFalse = Nothing}, CondBranch { @@ -478,25 +486,29 @@ GenericPackageDescription { (EarlierVersion (mkVersion [0, 6]))) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName - "transformers-compat") - (IntersectVersionRanges - (OrLaterVersion - (mkVersion [0, 3])) - (EarlierVersion - (mkVersion [0, 6]))) - mainLibSet, - Dependency - (PackageName "transformers") - (IntersectVersionRanges - (OrLaterVersion - (mkVersion [0, 3])) - (EarlierVersion - (mkVersion [0, 6]))) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName + "transformers-compat") + (IntersectVersionRanges + (OrLaterVersion + (mkVersion [0, 3])) + (EarlierVersion + (mkVersion [0, 6]))) + mainLibSet, + Dependency + (PackageName "transformers") + (IntersectVersionRanges + (OrLaterVersion + (mkVersion [0, 3])) + (EarlierVersion + (mkVersion [0, 6]))) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}, condBranchIfFalse = Nothing}, CondBranch { @@ -565,8 +577,12 @@ GenericPackageDescription { PerCompilerFlavor [] [], customFieldsBI = [], targetBuildDepends = [], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [], + condTreeConstraints = + Dependencies { + publicDependencies = [], + privateDependencies = []}, condTreeComponents = []}, condBranchIfFalse = Nothing}, CondBranch { @@ -635,8 +651,12 @@ GenericPackageDescription { PerCompilerFlavor [] [], customFieldsBI = [], targetBuildDepends = [], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [], + condTreeConstraints = + Dependencies { + publicDependencies = [], + privateDependencies = []}, condTreeComponents = []}, condBranchIfFalse = Nothing}]}, condSubLibraries = [], @@ -721,21 +741,25 @@ GenericPackageDescription { (EarlierVersion (mkVersion [0, 14]))) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}, testCodeGenerators = []}, - condTreeConstraints = [ - Dependency - (PackageName "base") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "doctest") - (IntersectVersionRanges - (OrLaterVersion - (mkVersion [0, 13])) - (EarlierVersion - (mkVersion [0, 14]))) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "base") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "doctest") + (IntersectVersionRanges + (OrLaterVersion + (mkVersion [0, 13])) + (EarlierVersion + (mkVersion [0, 14]))) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}, _×_ (UnqualComponentName @@ -814,20 +838,24 @@ GenericPackageDescription { (PackageName "generics-sop") (OrLaterVersion (mkVersion [0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}, testCodeGenerators = []}, - condTreeConstraints = [ - Dependency - (PackageName "base") - (IntersectVersionRanges - (OrLaterVersion - (mkVersion [4, 6])) - (EarlierVersion - (mkVersion [5]))) - mainLibSet, - Dependency - (PackageName "generics-sop") - (OrLaterVersion (mkVersion [0])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "base") + (IntersectVersionRanges + (OrLaterVersion + (mkVersion [4, 6])) + (EarlierVersion + (mkVersion [5]))) + mainLibSet, + Dependency + (PackageName "generics-sop") + (OrLaterVersion (mkVersion [0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}], condBenchmarks = []} diff --git a/Cabal-tests/tests/ParserTests/regressions/hasktorch.expr b/Cabal-tests/tests/ParserTests/regressions/hasktorch.expr index 346af927d1b..a2cdde88871 100644 --- a/Cabal-tests/tests/ParserTests/regressions/hasktorch.expr +++ b/Cabal-tests/tests/ParserTests/regressions/hasktorch.expr @@ -398,80 +398,84 @@ GenericPackageDescription { (EarlierVersion (mkVersion [0, 0, 2]))) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "base") - (IntersectVersionRanges + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "base") + (IntersectVersionRanges + (UnionVersionRanges + (ThisVersion (mkVersion [4, 7])) + (LaterVersion + (mkVersion [4, 7]))) + (EarlierVersion + (mkVersion [5]))) + mainLibSet, + Dependency + (PackageName "dimensions") (UnionVersionRanges - (ThisVersion (mkVersion [4, 7])) + (ThisVersion (mkVersion [1, 0])) (LaterVersion - (mkVersion [4, 7]))) - (EarlierVersion - (mkVersion [5]))) - mainLibSet, - Dependency - (PackageName "dimensions") - (UnionVersionRanges - (ThisVersion (mkVersion [1, 0])) - (LaterVersion - (mkVersion [1, 0]))) - mainLibSet, - Dependency - (PackageName "safe-exceptions") - (UnionVersionRanges - (ThisVersion - (mkVersion [0, 1, 0])) - (LaterVersion - (mkVersion [0, 1, 0]))) - mainLibSet, - Dependency - (PackageName "singletons") - (UnionVersionRanges - (ThisVersion (mkVersion [2, 2])) - (LaterVersion - (mkVersion [2, 2]))) - mainLibSet, - Dependency - (PackageName "text") - (UnionVersionRanges - (ThisVersion - (mkVersion [1, 2, 2])) - (LaterVersion - (mkVersion [1, 2, 2]))) - mainLibSet, - Dependency - (PackageName "hasktorch") - (OrLaterVersion (mkVersion [0])) - (NonEmptySet.fromNonEmpty - (NE.fromList - [ - LSubLibName - (UnqualComponentName - "hasktorch-cpu")])), - Dependency - (PackageName "hasktorch-ffi-th") - (IntersectVersionRanges + (mkVersion [1, 0]))) + mainLibSet, + Dependency + (PackageName "safe-exceptions") (UnionVersionRanges (ThisVersion - (mkVersion [0, 0, 1])) + (mkVersion [0, 1, 0])) + (LaterVersion + (mkVersion [0, 1, 0]))) + mainLibSet, + Dependency + (PackageName "singletons") + (UnionVersionRanges + (ThisVersion (mkVersion [2, 2])) (LaterVersion - (mkVersion [0, 0, 1]))) - (EarlierVersion - (mkVersion [0, 0, 2]))) - mainLibSet, - Dependency - (PackageName - "hasktorch-types-th") - (IntersectVersionRanges + (mkVersion [2, 2]))) + mainLibSet, + Dependency + (PackageName "text") (UnionVersionRanges (ThisVersion - (mkVersion [0, 0, 1])) + (mkVersion [1, 2, 2])) (LaterVersion - (mkVersion [0, 0, 1]))) - (EarlierVersion - (mkVersion [0, 0, 2]))) - mainLibSet], + (mkVersion [1, 2, 2]))) + mainLibSet, + Dependency + (PackageName "hasktorch") + (OrLaterVersion (mkVersion [0])) + (NonEmptySet.fromNonEmpty + (NE.fromList + [ + LSubLibName + (UnqualComponentName + "hasktorch-cpu")])), + Dependency + (PackageName "hasktorch-ffi-th") + (IntersectVersionRanges + (UnionVersionRanges + (ThisVersion + (mkVersion [0, 0, 1])) + (LaterVersion + (mkVersion [0, 0, 1]))) + (EarlierVersion + (mkVersion [0, 0, 2]))) + mainLibSet, + Dependency + (PackageName + "hasktorch-types-th") + (IntersectVersionRanges + (UnionVersionRanges + (ThisVersion + (mkVersion [0, 0, 1])) + (LaterVersion + (mkVersion [0, 0, 1]))) + (EarlierVersion + (mkVersion [0, 0, 2]))) + mainLibSet], + privateDependencies = []}, condTreeComponents = [ CondBranch { condBranchCondition = @@ -646,8 +650,12 @@ GenericPackageDescription { PerCompilerFlavor [] [], customFieldsBI = [], targetBuildDepends = [], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [], + condTreeConstraints = + Dependencies { + publicDependencies = [], + privateDependencies = []}, condTreeComponents = []}, condBranchIfFalse = Nothing}, CondBranch { @@ -897,17 +905,21 @@ GenericPackageDescription { LSubLibName (UnqualComponentName "hasktorch-gpu")]))], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "hasktorch") - (OrLaterVersion (mkVersion [0])) - (NonEmptySet.fromNonEmpty - (NE.fromList - [ - LSubLibName - (UnqualComponentName - "hasktorch-gpu")]))], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "hasktorch") + (OrLaterVersion (mkVersion [0])) + (NonEmptySet.fromNonEmpty + (NE.fromList + [ + LSubLibName + (UnqualComponentName + "hasktorch-gpu")]))], + privateDependencies = []}, condTreeComponents = [ CondBranch { condBranchCondition = @@ -1088,8 +1100,12 @@ GenericPackageDescription { PerCompilerFlavor [] [], customFieldsBI = [], targetBuildDepends = [], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [], + condTreeConstraints = + Dependencies { + publicDependencies = [], + privateDependencies = []}, condTreeComponents = []}, condBranchIfFalse = Nothing}]}, condBranchIfFalse = Nothing}]}, @@ -1535,6 +1551,7 @@ GenericPackageDescription { LSubLibName (UnqualComponentName "hasktorch-indef-signed")]))], + targetPrivateBuildDepends = [], mixins = [ Mixin { @@ -2582,100 +2599,103 @@ GenericPackageDescription { "Torch.Sig.Tensor.Random.THC") (ModuleName "Torch.Undefined.Double.Tensor.Random.THC")]}}]}}, - condTreeConstraints = [ - Dependency - (PackageName "base") - (IntersectVersionRanges + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "base") + (IntersectVersionRanges + (UnionVersionRanges + (ThisVersion (mkVersion [4, 7])) + (LaterVersion + (mkVersion [4, 7]))) + (EarlierVersion + (mkVersion [5]))) + mainLibSet, + Dependency + (PackageName + "hasktorch-types-th") + (IntersectVersionRanges + (UnionVersionRanges + (ThisVersion + (mkVersion [0, 0, 1])) + (LaterVersion + (mkVersion [0, 0, 1]))) + (EarlierVersion + (mkVersion [0, 0, 2]))) + mainLibSet, + Dependency + (PackageName "dimensions") (UnionVersionRanges - (ThisVersion (mkVersion [4, 7])) + (ThisVersion (mkVersion [1, 0])) (LaterVersion - (mkVersion [4, 7]))) - (EarlierVersion - (mkVersion [5]))) - mainLibSet, - Dependency - (PackageName - "hasktorch-types-th") - (IntersectVersionRanges + (mkVersion [1, 0]))) + mainLibSet, + Dependency + (PackageName "hasktorch-ffi-th") + (IntersectVersionRanges + (UnionVersionRanges + (ThisVersion + (mkVersion [0, 0, 1])) + (LaterVersion + (mkVersion [0, 0, 1]))) + (EarlierVersion + (mkVersion [0, 0, 2]))) + mainLibSet, + Dependency + (PackageName + "hasktorch-types-th") + (IntersectVersionRanges + (UnionVersionRanges + (ThisVersion + (mkVersion [0, 0, 1])) + (LaterVersion + (mkVersion [0, 0, 1]))) + (EarlierVersion + (mkVersion [0, 0, 2]))) + mainLibSet, + Dependency + (PackageName "safe-exceptions") (UnionVersionRanges (ThisVersion - (mkVersion [0, 0, 1])) + (mkVersion [0, 1, 0])) (LaterVersion - (mkVersion [0, 0, 1]))) - (EarlierVersion - (mkVersion [0, 0, 2]))) - mainLibSet, - Dependency - (PackageName "dimensions") - (UnionVersionRanges - (ThisVersion (mkVersion [1, 0])) - (LaterVersion - (mkVersion [1, 0]))) - mainLibSet, - Dependency - (PackageName "hasktorch-ffi-th") - (IntersectVersionRanges + (mkVersion [0, 1, 0]))) + mainLibSet, + Dependency + (PackageName "singletons") (UnionVersionRanges - (ThisVersion - (mkVersion [0, 0, 1])) + (ThisVersion (mkVersion [2, 2])) (LaterVersion - (mkVersion [0, 0, 1]))) - (EarlierVersion - (mkVersion [0, 0, 2]))) - mainLibSet, - Dependency - (PackageName - "hasktorch-types-th") - (IntersectVersionRanges + (mkVersion [2, 2]))) + mainLibSet, + Dependency + (PackageName "text") (UnionVersionRanges (ThisVersion - (mkVersion [0, 0, 1])) + (mkVersion [1, 2, 2])) (LaterVersion - (mkVersion [0, 0, 1]))) - (EarlierVersion - (mkVersion [0, 0, 2]))) - mainLibSet, - Dependency - (PackageName "safe-exceptions") - (UnionVersionRanges - (ThisVersion - (mkVersion [0, 1, 0])) - (LaterVersion - (mkVersion [0, 1, 0]))) - mainLibSet, - Dependency - (PackageName "singletons") - (UnionVersionRanges - (ThisVersion (mkVersion [2, 2])) - (LaterVersion - (mkVersion [2, 2]))) - mainLibSet, - Dependency - (PackageName "text") - (UnionVersionRanges - (ThisVersion - (mkVersion [1, 2, 2])) - (LaterVersion - (mkVersion [1, 2, 2]))) - mainLibSet, - Dependency - (PackageName "hasktorch") - (OrLaterVersion (mkVersion [0])) - (NonEmptySet.fromNonEmpty - (NE.fromList - [ - LSubLibName - (UnqualComponentName - "hasktorch-indef-floating")])), - Dependency - (PackageName "hasktorch") - (OrLaterVersion (mkVersion [0])) - (NonEmptySet.fromNonEmpty - (NE.fromList - [ - LSubLibName - (UnqualComponentName - "hasktorch-indef-signed")]))], + (mkVersion [1, 2, 2]))) + mainLibSet, + Dependency + (PackageName "hasktorch") + (OrLaterVersion (mkVersion [0])) + (NonEmptySet.fromNonEmpty + (NE.fromList + [ + LSubLibName + (UnqualComponentName + "hasktorch-indef-floating")])), + Dependency + (PackageName "hasktorch") + (OrLaterVersion (mkVersion [0])) + (NonEmptySet.fromNonEmpty + (NE.fromList + [ + LSubLibName + (UnqualComponentName + "hasktorch-indef-signed")]))], + privateDependencies = []}, condTreeComponents = [ CondBranch { @@ -2744,8 +2764,12 @@ GenericPackageDescription { PerCompilerFlavor [] [], customFieldsBI = [], targetBuildDepends = [], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [], + condTreeConstraints = + Dependencies { + publicDependencies = [], + privateDependencies = []}, condTreeComponents = []}, condBranchIfFalse = Just @@ -2842,6 +2866,7 @@ GenericPackageDescription { LSubLibName (UnqualComponentName "hasktorch-indef-unsigned")]))], + targetPrivateBuildDepends = [], mixins = [ Mixin { @@ -4840,16 +4865,19 @@ GenericPackageDescription { "Torch.Sig.Tensor.Random.THC") (ModuleName "Torch.Undefined.Float.Tensor.Random.THC")]}}]}}, - condTreeConstraints = [ - Dependency - (PackageName "hasktorch") - (OrLaterVersion (mkVersion [0])) - (NonEmptySet.fromNonEmpty - (NE.fromList - [ - LSubLibName - (UnqualComponentName - "hasktorch-indef-unsigned")]))], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "hasktorch") + (OrLaterVersion (mkVersion [0])) + (NonEmptySet.fromNonEmpty + (NE.fromList + [ + LSubLibName + (UnqualComponentName + "hasktorch-indef-unsigned")]))], + privateDependencies = []}, condTreeComponents = []}}]}, _×_ (UnqualComponentName @@ -5193,6 +5221,7 @@ GenericPackageDescription { (EarlierVersion (mkVersion [0, 0, 2]))) mainLibSet], + targetPrivateBuildDepends = [], mixins = [ Mixin { @@ -6242,124 +6271,127 @@ GenericPackageDescription { "Torch.Sig.Tensor.Random.THC") (ModuleName "Torch.FFI.THC.Double.TensorRandom")]}}]}}, - condTreeConstraints = [ - Dependency - (PackageName "base") - (IntersectVersionRanges - (UnionVersionRanges - (ThisVersion (mkVersion [4, 7])) - (LaterVersion - (mkVersion [4, 7]))) - (EarlierVersion - (mkVersion [5]))) - mainLibSet, - Dependency - (PackageName - "hasktorch-types-th") - (IntersectVersionRanges - (UnionVersionRanges - (ThisVersion - (mkVersion [0, 0, 1])) - (LaterVersion - (mkVersion [0, 0, 1]))) - (EarlierVersion - (mkVersion [0, 0, 2]))) - mainLibSet, - Dependency - (PackageName "dimensions") - (UnionVersionRanges - (ThisVersion (mkVersion [1, 0])) - (LaterVersion - (mkVersion [1, 0]))) - mainLibSet, - Dependency - (PackageName "hasktorch-ffi-th") - (IntersectVersionRanges + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "base") + (IntersectVersionRanges + (UnionVersionRanges + (ThisVersion (mkVersion [4, 7])) + (LaterVersion + (mkVersion [4, 7]))) + (EarlierVersion + (mkVersion [5]))) + mainLibSet, + Dependency + (PackageName + "hasktorch-types-th") + (IntersectVersionRanges + (UnionVersionRanges + (ThisVersion + (mkVersion [0, 0, 1])) + (LaterVersion + (mkVersion [0, 0, 1]))) + (EarlierVersion + (mkVersion [0, 0, 2]))) + mainLibSet, + Dependency + (PackageName "dimensions") (UnionVersionRanges - (ThisVersion - (mkVersion [0, 0, 1])) + (ThisVersion (mkVersion [1, 0])) (LaterVersion - (mkVersion [0, 0, 1]))) - (EarlierVersion - (mkVersion [0, 0, 2]))) - mainLibSet, - Dependency - (PackageName - "hasktorch-types-th") - (IntersectVersionRanges + (mkVersion [1, 0]))) + mainLibSet, + Dependency + (PackageName "hasktorch-ffi-th") + (IntersectVersionRanges + (UnionVersionRanges + (ThisVersion + (mkVersion [0, 0, 1])) + (LaterVersion + (mkVersion [0, 0, 1]))) + (EarlierVersion + (mkVersion [0, 0, 2]))) + mainLibSet, + Dependency + (PackageName + "hasktorch-types-th") + (IntersectVersionRanges + (UnionVersionRanges + (ThisVersion + (mkVersion [0, 0, 1])) + (LaterVersion + (mkVersion [0, 0, 1]))) + (EarlierVersion + (mkVersion [0, 0, 2]))) + mainLibSet, + Dependency + (PackageName "safe-exceptions") (UnionVersionRanges (ThisVersion - (mkVersion [0, 0, 1])) + (mkVersion [0, 1, 0])) (LaterVersion - (mkVersion [0, 0, 1]))) - (EarlierVersion - (mkVersion [0, 0, 2]))) - mainLibSet, - Dependency - (PackageName "safe-exceptions") - (UnionVersionRanges - (ThisVersion - (mkVersion [0, 1, 0])) - (LaterVersion - (mkVersion [0, 1, 0]))) - mainLibSet, - Dependency - (PackageName "singletons") - (UnionVersionRanges - (ThisVersion (mkVersion [2, 2])) - (LaterVersion - (mkVersion [2, 2]))) - mainLibSet, - Dependency - (PackageName "text") - (UnionVersionRanges - (ThisVersion - (mkVersion [1, 2, 2])) - (LaterVersion - (mkVersion [1, 2, 2]))) - mainLibSet, - Dependency - (PackageName "hasktorch") - (OrLaterVersion (mkVersion [0])) - (NonEmptySet.fromNonEmpty - (NE.fromList - [ - LSubLibName - (UnqualComponentName - "hasktorch-indef-floating")])), - Dependency - (PackageName "hasktorch") - (OrLaterVersion (mkVersion [0])) - (NonEmptySet.fromNonEmpty - (NE.fromList - [ - LSubLibName - (UnqualComponentName - "hasktorch-indef-signed")])), - Dependency - (PackageName - "hasktorch-ffi-thc") - (IntersectVersionRanges + (mkVersion [0, 1, 0]))) + mainLibSet, + Dependency + (PackageName "singletons") (UnionVersionRanges - (ThisVersion - (mkVersion [0, 0, 1])) + (ThisVersion (mkVersion [2, 2])) (LaterVersion - (mkVersion [0, 0, 1]))) - (EarlierVersion - (mkVersion [0, 0, 2]))) - mainLibSet, - Dependency - (PackageName - "hasktorch-types-thc") - (IntersectVersionRanges + (mkVersion [2, 2]))) + mainLibSet, + Dependency + (PackageName "text") (UnionVersionRanges (ThisVersion - (mkVersion [0, 0, 1])) + (mkVersion [1, 2, 2])) (LaterVersion - (mkVersion [0, 0, 1]))) - (EarlierVersion - (mkVersion [0, 0, 2]))) - mainLibSet], + (mkVersion [1, 2, 2]))) + mainLibSet, + Dependency + (PackageName "hasktorch") + (OrLaterVersion (mkVersion [0])) + (NonEmptySet.fromNonEmpty + (NE.fromList + [ + LSubLibName + (UnqualComponentName + "hasktorch-indef-floating")])), + Dependency + (PackageName "hasktorch") + (OrLaterVersion (mkVersion [0])) + (NonEmptySet.fromNonEmpty + (NE.fromList + [ + LSubLibName + (UnqualComponentName + "hasktorch-indef-signed")])), + Dependency + (PackageName + "hasktorch-ffi-thc") + (IntersectVersionRanges + (UnionVersionRanges + (ThisVersion + (mkVersion [0, 0, 1])) + (LaterVersion + (mkVersion [0, 0, 1]))) + (EarlierVersion + (mkVersion [0, 0, 2]))) + mainLibSet, + Dependency + (PackageName + "hasktorch-types-thc") + (IntersectVersionRanges + (UnionVersionRanges + (ThisVersion + (mkVersion [0, 0, 1])) + (LaterVersion + (mkVersion [0, 0, 1]))) + (EarlierVersion + (mkVersion [0, 0, 2]))) + mainLibSet], + privateDependencies = []}, condTreeComponents = [ CondBranch { @@ -6428,8 +6460,12 @@ GenericPackageDescription { PerCompilerFlavor [] [], customFieldsBI = [], targetBuildDepends = [], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [], + condTreeConstraints = + Dependencies { + publicDependencies = [], + privateDependencies = []}, condTreeComponents = []}, condBranchIfFalse = Just @@ -6527,6 +6563,7 @@ GenericPackageDescription { LSubLibName (UnqualComponentName "hasktorch-indef-unsigned")]))], + targetPrivateBuildDepends = [], mixins = [ Mixin { @@ -7823,16 +7860,19 @@ GenericPackageDescription { "Torch.Sig.Tensor.Math.Pointwise.Signed") (ModuleName "Torch.FFI.THC.Int.TensorMathPointwise")]}}]}}, - condTreeConstraints = [ - Dependency - (PackageName "hasktorch") - (OrLaterVersion (mkVersion [0])) - (NonEmptySet.fromNonEmpty - (NE.fromList - [ - LSubLibName - (UnqualComponentName - "hasktorch-indef-unsigned")]))], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "hasktorch") + (OrLaterVersion (mkVersion [0])) + (NonEmptySet.fromNonEmpty + (NE.fromList + [ + LSubLibName + (UnqualComponentName + "hasktorch-indef-unsigned")]))], + privateDependencies = []}, condTreeComponents = []}}]}, _×_ (UnqualComponentName @@ -8212,6 +8252,7 @@ GenericPackageDescription { (PackageName "hasktorch-indef") (OrLaterVersion (mkVersion [0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = [ Mixin { mixinPackageName = PackageName @@ -8278,33 +8319,36 @@ GenericPackageDescription { "Torch.Sig.Tensor.Random.THC") (ModuleName "Torch.Undefined.Tensor.Random.THC")]}}]}}, - condTreeConstraints = [ - Dependency - (PackageName "base") - (IntersectVersionRanges - (UnionVersionRanges - (ThisVersion (mkVersion [4, 7])) - (LaterVersion - (mkVersion [4, 7]))) - (EarlierVersion - (mkVersion [5]))) - mainLibSet, - Dependency - (PackageName - "hasktorch-signatures-partial") - (IntersectVersionRanges - (UnionVersionRanges - (ThisVersion - (mkVersion [0, 0, 1])) - (LaterVersion - (mkVersion [0, 0, 1]))) - (EarlierVersion - (mkVersion [0, 0, 2]))) - mainLibSet, - Dependency - (PackageName "hasktorch-indef") - (OrLaterVersion (mkVersion [0])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "base") + (IntersectVersionRanges + (UnionVersionRanges + (ThisVersion (mkVersion [4, 7])) + (LaterVersion + (mkVersion [4, 7]))) + (EarlierVersion + (mkVersion [5]))) + mainLibSet, + Dependency + (PackageName + "hasktorch-signatures-partial") + (IntersectVersionRanges + (UnionVersionRanges + (ThisVersion + (mkVersion [0, 0, 1])) + (LaterVersion + (mkVersion [0, 0, 1]))) + (EarlierVersion + (mkVersion [0, 0, 2]))) + mainLibSet, + Dependency + (PackageName "hasktorch-indef") + (OrLaterVersion (mkVersion [0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}, _×_ (UnqualComponentName @@ -8700,6 +8744,7 @@ GenericPackageDescription { (PackageName "hasktorch-indef") (OrLaterVersion (mkVersion [0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = [ Mixin { mixinPackageName = PackageName @@ -8761,33 +8806,36 @@ GenericPackageDescription { "Torch.Sig.Tensor.Random.THC") (ModuleName "Torch.Undefined.Tensor.Random.THC")]}}]}}, - condTreeConstraints = [ - Dependency - (PackageName "base") - (IntersectVersionRanges - (UnionVersionRanges - (ThisVersion (mkVersion [4, 7])) - (LaterVersion - (mkVersion [4, 7]))) - (EarlierVersion - (mkVersion [5]))) - mainLibSet, - Dependency - (PackageName - "hasktorch-signatures-partial") - (IntersectVersionRanges - (UnionVersionRanges - (ThisVersion - (mkVersion [0, 0, 1])) - (LaterVersion - (mkVersion [0, 0, 1]))) - (EarlierVersion - (mkVersion [0, 0, 2]))) - mainLibSet, - Dependency - (PackageName "hasktorch-indef") - (OrLaterVersion (mkVersion [0])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "base") + (IntersectVersionRanges + (UnionVersionRanges + (ThisVersion (mkVersion [4, 7])) + (LaterVersion + (mkVersion [4, 7]))) + (EarlierVersion + (mkVersion [5]))) + mainLibSet, + Dependency + (PackageName + "hasktorch-signatures-partial") + (IntersectVersionRanges + (UnionVersionRanges + (ThisVersion + (mkVersion [0, 0, 1])) + (LaterVersion + (mkVersion [0, 0, 1]))) + (EarlierVersion + (mkVersion [0, 0, 2]))) + mainLibSet, + Dependency + (PackageName "hasktorch-indef") + (OrLaterVersion (mkVersion [0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}, _×_ (UnqualComponentName @@ -9463,34 +9511,38 @@ GenericPackageDescription { (EarlierVersion (mkVersion [0, 0, 2]))) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "base") - (IntersectVersionRanges - (UnionVersionRanges - (ThisVersion (mkVersion [4, 7])) - (LaterVersion - (mkVersion [4, 7]))) - (EarlierVersion - (mkVersion [5]))) - mainLibSet, - Dependency - (PackageName "hasktorch-indef") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName - "hasktorch-signatures-partial") - (IntersectVersionRanges - (UnionVersionRanges - (ThisVersion - (mkVersion [0, 0, 1])) - (LaterVersion - (mkVersion [0, 0, 1]))) - (EarlierVersion - (mkVersion [0, 0, 2]))) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "base") + (IntersectVersionRanges + (UnionVersionRanges + (ThisVersion (mkVersion [4, 7])) + (LaterVersion + (mkVersion [4, 7]))) + (EarlierVersion + (mkVersion [5]))) + mainLibSet, + Dependency + (PackageName "hasktorch-indef") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName + "hasktorch-signatures-partial") + (IntersectVersionRanges + (UnionVersionRanges + (ThisVersion + (mkVersion [0, 0, 1])) + (LaterVersion + (mkVersion [0, 0, 1]))) + (EarlierVersion + (mkVersion [0, 0, 2]))) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}], condForeignLibs = [], condExecutables = [ @@ -9577,27 +9629,31 @@ GenericPackageDescription { LSubLibName (UnqualComponentName "hasktorch-cpu")]))], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "base") - (IntersectVersionRanges - (UnionVersionRanges - (ThisVersion (mkVersion [4, 7])) - (LaterVersion - (mkVersion [4, 7]))) - (EarlierVersion - (mkVersion [5]))) - mainLibSet, - Dependency - (PackageName "hasktorch") - (OrLaterVersion (mkVersion [0])) - (NonEmptySet.fromNonEmpty - (NE.fromList - [ - LSubLibName - (UnqualComponentName - "hasktorch-cpu")]))], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "base") + (IntersectVersionRanges + (UnionVersionRanges + (ThisVersion (mkVersion [4, 7])) + (LaterVersion + (mkVersion [4, 7]))) + (EarlierVersion + (mkVersion [5]))) + mainLibSet, + Dependency + (PackageName "hasktorch") + (OrLaterVersion (mkVersion [0])) + (NonEmptySet.fromNonEmpty + (NE.fromList + [ + LSubLibName + (UnqualComponentName + "hasktorch-cpu")]))], + privateDependencies = []}, condTreeComponents = []}, _×_ (UnqualComponentName @@ -9682,27 +9738,31 @@ GenericPackageDescription { LSubLibName (UnqualComponentName "hasktorch-gpu")]))], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "base") - (IntersectVersionRanges - (UnionVersionRanges - (ThisVersion (mkVersion [4, 7])) - (LaterVersion - (mkVersion [4, 7]))) - (EarlierVersion - (mkVersion [5]))) - mainLibSet, - Dependency - (PackageName "hasktorch") - (OrLaterVersion (mkVersion [0])) - (NonEmptySet.fromNonEmpty - (NE.fromList - [ - LSubLibName - (UnqualComponentName - "hasktorch-gpu")]))], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "base") + (IntersectVersionRanges + (UnionVersionRanges + (ThisVersion (mkVersion [4, 7])) + (LaterVersion + (mkVersion [4, 7]))) + (EarlierVersion + (mkVersion [5]))) + mainLibSet, + Dependency + (PackageName "hasktorch") + (OrLaterVersion (mkVersion [0])) + (NonEmptySet.fromNonEmpty + (NE.fromList + [ + LSubLibName + (UnqualComponentName + "hasktorch-gpu")]))], + privateDependencies = []}, condTreeComponents = []}, _×_ (UnqualComponentName @@ -9782,22 +9842,26 @@ GenericPackageDescription { (PackageName "hasktorch") (OrLaterVersion (mkVersion [0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "base") - (IntersectVersionRanges - (UnionVersionRanges - (ThisVersion (mkVersion [4, 7])) - (LaterVersion - (mkVersion [4, 7]))) - (EarlierVersion - (mkVersion [5]))) - mainLibSet, - Dependency - (PackageName "hasktorch") - (OrLaterVersion (mkVersion [0])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "base") + (IntersectVersionRanges + (UnionVersionRanges + (ThisVersion (mkVersion [4, 7])) + (LaterVersion + (mkVersion [4, 7]))) + (EarlierVersion + (mkVersion [5]))) + mainLibSet, + Dependency + (PackageName "hasktorch") + (OrLaterVersion (mkVersion [0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}, _×_ (UnqualComponentName "memcheck") @@ -9876,22 +9940,26 @@ GenericPackageDescription { (PackageName "hasktorch") (OrLaterVersion (mkVersion [0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "base") - (IntersectVersionRanges - (UnionVersionRanges - (ThisVersion (mkVersion [4, 7])) - (LaterVersion - (mkVersion [4, 7]))) - (EarlierVersion - (mkVersion [5]))) - mainLibSet, - Dependency - (PackageName "hasktorch") - (OrLaterVersion (mkVersion [0])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "base") + (IntersectVersionRanges + (UnionVersionRanges + (ThisVersion (mkVersion [4, 7])) + (LaterVersion + (mkVersion [4, 7]))) + (EarlierVersion + (mkVersion [5]))) + mainLibSet, + Dependency + (PackageName "hasktorch") + (OrLaterVersion (mkVersion [0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}], condTestSuites = [ _×_ @@ -10084,110 +10152,114 @@ GenericPackageDescription { (PackageName "generic-lens") (OrLaterVersion (mkVersion [0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}, testCodeGenerators = []}, - condTreeConstraints = [ - Dependency - (PackageName "QuickCheck") - (UnionVersionRanges - (ThisVersion - (mkVersion [2, 11])) - (LaterVersion - (mkVersion [2, 11]))) - mainLibSet, - Dependency - (PackageName "backprop") - (UnionVersionRanges - (ThisVersion - (mkVersion [0, 2, 5])) - (LaterVersion - (mkVersion [0, 2, 5]))) - mainLibSet, - Dependency - (PackageName "base") - (IntersectVersionRanges + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "QuickCheck") (UnionVersionRanges - (ThisVersion (mkVersion [4, 7])) + (ThisVersion + (mkVersion [2, 11])) (LaterVersion - (mkVersion [4, 7]))) - (EarlierVersion - (mkVersion [5]))) - mainLibSet, - Dependency - (PackageName "dimensions") - (UnionVersionRanges - (ThisVersion (mkVersion [1, 0])) - (LaterVersion - (mkVersion [1, 0]))) - mainLibSet, - Dependency - (PackageName - "ghc-typelits-natnormalise") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "hasktorch") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "hspec") - (UnionVersionRanges - (ThisVersion - (mkVersion [2, 4, 4])) - (LaterVersion - (mkVersion [2, 4, 4]))) - mainLibSet, - Dependency - (PackageName "singletons") - (UnionVersionRanges - (ThisVersion (mkVersion [2, 2])) - (LaterVersion - (mkVersion [2, 2]))) - mainLibSet, - Dependency - (PackageName "mtl") - (UnionVersionRanges - (ThisVersion - (mkVersion [2, 2, 2])) - (LaterVersion - (mkVersion [2, 2, 2]))) - mainLibSet, - Dependency - (PackageName - "microlens-platform") - (UnionVersionRanges - (ThisVersion - (mkVersion [0, 3, 10])) - (LaterVersion - (mkVersion [0, 3, 10]))) - mainLibSet, - Dependency - (PackageName "monad-loops") - (UnionVersionRanges - (ThisVersion - (mkVersion [0, 4, 3])) - (LaterVersion - (mkVersion [0, 4, 3]))) - mainLibSet, - Dependency - (PackageName "time") - (UnionVersionRanges - (ThisVersion - (mkVersion [1, 8, 0])) - (LaterVersion - (mkVersion [1, 8, 0]))) - mainLibSet, - Dependency - (PackageName "transformers") - (UnionVersionRanges - (ThisVersion - (mkVersion [0, 5, 5])) - (LaterVersion - (mkVersion [0, 5, 5]))) - mainLibSet, - Dependency - (PackageName "generic-lens") - (OrLaterVersion (mkVersion [0])) - mainLibSet], + (mkVersion [2, 11]))) + mainLibSet, + Dependency + (PackageName "backprop") + (UnionVersionRanges + (ThisVersion + (mkVersion [0, 2, 5])) + (LaterVersion + (mkVersion [0, 2, 5]))) + mainLibSet, + Dependency + (PackageName "base") + (IntersectVersionRanges + (UnionVersionRanges + (ThisVersion (mkVersion [4, 7])) + (LaterVersion + (mkVersion [4, 7]))) + (EarlierVersion + (mkVersion [5]))) + mainLibSet, + Dependency + (PackageName "dimensions") + (UnionVersionRanges + (ThisVersion (mkVersion [1, 0])) + (LaterVersion + (mkVersion [1, 0]))) + mainLibSet, + Dependency + (PackageName + "ghc-typelits-natnormalise") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "hasktorch") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "hspec") + (UnionVersionRanges + (ThisVersion + (mkVersion [2, 4, 4])) + (LaterVersion + (mkVersion [2, 4, 4]))) + mainLibSet, + Dependency + (PackageName "singletons") + (UnionVersionRanges + (ThisVersion (mkVersion [2, 2])) + (LaterVersion + (mkVersion [2, 2]))) + mainLibSet, + Dependency + (PackageName "mtl") + (UnionVersionRanges + (ThisVersion + (mkVersion [2, 2, 2])) + (LaterVersion + (mkVersion [2, 2, 2]))) + mainLibSet, + Dependency + (PackageName + "microlens-platform") + (UnionVersionRanges + (ThisVersion + (mkVersion [0, 3, 10])) + (LaterVersion + (mkVersion [0, 3, 10]))) + mainLibSet, + Dependency + (PackageName "monad-loops") + (UnionVersionRanges + (ThisVersion + (mkVersion [0, 4, 3])) + (LaterVersion + (mkVersion [0, 4, 3]))) + mainLibSet, + Dependency + (PackageName "time") + (UnionVersionRanges + (ThisVersion + (mkVersion [1, 8, 0])) + (LaterVersion + (mkVersion [1, 8, 0]))) + mainLibSet, + Dependency + (PackageName "transformers") + (UnionVersionRanges + (ThisVersion + (mkVersion [0, 5, 5])) + (LaterVersion + (mkVersion [0, 5, 5]))) + mainLibSet, + Dependency + (PackageName "generic-lens") + (OrLaterVersion (mkVersion [0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}], condBenchmarks = []} diff --git a/Cabal-tests/tests/ParserTests/regressions/hidden-main-lib.expr b/Cabal-tests/tests/ParserTests/regressions/hidden-main-lib.expr index fba99528b53..c341d178084 100644 --- a/Cabal-tests/tests/ParserTests/regressions/hidden-main-lib.expr +++ b/Cabal-tests/tests/ParserTests/regressions/hidden-main-lib.expr @@ -105,12 +105,16 @@ GenericPackageDescription { (PackageName "base") (OrLaterVersion (mkVersion [0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "base") - (OrLaterVersion (mkVersion [0])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "base") + (OrLaterVersion (mkVersion [0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}, condSubLibraries = [], condForeignLibs = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/indentation.expr b/Cabal-tests/tests/ParserTests/regressions/indentation.expr index e5b106dc5cd..88a6c09c396 100644 --- a/Cabal-tests/tests/ParserTests/regressions/indentation.expr +++ b/Cabal-tests/tests/ParserTests/regressions/indentation.expr @@ -110,8 +110,12 @@ GenericPackageDescription { PerCompilerFlavor [] [], customFieldsBI = [], targetBuildDepends = [], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [], + condTreeConstraints = + Dependencies { + publicDependencies = [], + privateDependencies = []}, condTreeComponents = []}, condSubLibraries = [], condForeignLibs = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/indentation2.expr b/Cabal-tests/tests/ParserTests/regressions/indentation2.expr index 46f24105f0f..755195fc848 100644 --- a/Cabal-tests/tests/ParserTests/regressions/indentation2.expr +++ b/Cabal-tests/tests/ParserTests/regressions/indentation2.expr @@ -103,8 +103,12 @@ GenericPackageDescription { PerCompilerFlavor [] [], customFieldsBI = [], targetBuildDepends = [], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [], + condTreeConstraints = + Dependencies { + publicDependencies = [], + privateDependencies = []}, condTreeComponents = []}, condSubLibraries = [], condForeignLibs = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/indentation3.expr b/Cabal-tests/tests/ParserTests/regressions/indentation3.expr index 0191d063f6e..db211c2be9c 100644 --- a/Cabal-tests/tests/ParserTests/regressions/indentation3.expr +++ b/Cabal-tests/tests/ParserTests/regressions/indentation3.expr @@ -105,8 +105,12 @@ GenericPackageDescription { PerCompilerFlavor [] [], customFieldsBI = [], targetBuildDepends = [], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [], + condTreeConstraints = + Dependencies { + publicDependencies = [], + privateDependencies = []}, condTreeComponents = []}, condSubLibraries = [], condForeignLibs = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/issue-5055.expr b/Cabal-tests/tests/ParserTests/regressions/issue-5055.expr index 07c04ec6cb9..ee3554212a0 100644 --- a/Cabal-tests/tests/ParserTests/regressions/issue-5055.expr +++ b/Cabal-tests/tests/ParserTests/regressions/issue-5055.expr @@ -112,16 +112,20 @@ GenericPackageDescription { (EarlierVersion (mkVersion [5]))) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "base") - (IntersectVersionRanges - (OrLaterVersion - (mkVersion [4, 8])) - (EarlierVersion - (mkVersion [5]))) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "base") + (IntersectVersionRanges + (OrLaterVersion + (mkVersion [4, 8])) + (EarlierVersion + (mkVersion [5]))) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}], condTestSuites = [ _×_ @@ -195,17 +199,21 @@ GenericPackageDescription { (EarlierVersion (mkVersion [5]))) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}, testCodeGenerators = []}, - condTreeConstraints = [ - Dependency - (PackageName "base") - (IntersectVersionRanges - (OrLaterVersion - (mkVersion [4, 8])) - (EarlierVersion - (mkVersion [5]))) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "base") + (IntersectVersionRanges + (OrLaterVersion + (mkVersion [4, 8])) + (EarlierVersion + (mkVersion [5]))) + mainLibSet], + privateDependencies = []}, condTreeComponents = [ CondBranch { condBranchCondition = @@ -271,9 +279,13 @@ GenericPackageDescription { PerCompilerFlavor [] [], customFieldsBI = [], targetBuildDepends = [], + targetPrivateBuildDepends = [], mixins = []}, testCodeGenerators = []}, - condTreeConstraints = [], + condTreeConstraints = + Dependencies { + publicDependencies = [], + privateDependencies = []}, condTreeComponents = []}, condBranchIfFalse = Nothing}]}], condBenchmarks = []} diff --git a/Cabal-tests/tests/ParserTests/regressions/issue-5846.expr b/Cabal-tests/tests/ParserTests/regressions/issue-5846.expr index 2ff7de7917e..86bdde11186 100644 --- a/Cabal-tests/tests/ParserTests/regressions/issue-5846.expr +++ b/Cabal-tests/tests/ParserTests/regressions/issue-5846.expr @@ -134,44 +134,48 @@ GenericPackageDescription { (UnqualComponentName "a"), LSubLibName (UnqualComponentName "b")]))], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "lib1") - (OrLaterVersion (mkVersion [0])) - (NonEmptySet.fromNonEmpty - (NE.fromList - [ - LSubLibName - (UnqualComponentName "a"), - LSubLibName - (UnqualComponentName "b")])), - Dependency - (PackageName "lib2") - (OrLaterVersion (mkVersion [0])) - (NonEmptySet.fromNonEmpty - (NE.fromList - [ - LSubLibName - (UnqualComponentName "c")])), - Dependency - (PackageName "lib3") - (OrLaterVersion (mkVersion [1])) - (NonEmptySet.fromNonEmpty - (NE.fromList - [ - LSubLibName - (UnqualComponentName "d")])), - Dependency - (PackageName "lib4") - (OrLaterVersion (mkVersion [1])) - (NonEmptySet.fromNonEmpty - (NE.fromList - [ - LSubLibName - (UnqualComponentName "a"), - LSubLibName - (UnqualComponentName "b")]))], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "lib1") + (OrLaterVersion (mkVersion [0])) + (NonEmptySet.fromNonEmpty + (NE.fromList + [ + LSubLibName + (UnqualComponentName "a"), + LSubLibName + (UnqualComponentName "b")])), + Dependency + (PackageName "lib2") + (OrLaterVersion (mkVersion [0])) + (NonEmptySet.fromNonEmpty + (NE.fromList + [ + LSubLibName + (UnqualComponentName "c")])), + Dependency + (PackageName "lib3") + (OrLaterVersion (mkVersion [1])) + (NonEmptySet.fromNonEmpty + (NE.fromList + [ + LSubLibName + (UnqualComponentName "d")])), + Dependency + (PackageName "lib4") + (OrLaterVersion (mkVersion [1])) + (NonEmptySet.fromNonEmpty + (NE.fromList + [ + LSubLibName + (UnqualComponentName "a"), + LSubLibName + (UnqualComponentName "b")]))], + privateDependencies = []}, condTreeComponents = []}, condSubLibraries = [], condForeignLibs = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/issue-6083-a.expr b/Cabal-tests/tests/ParserTests/regressions/issue-6083-a.expr index 43c345dd170..3d5861da196 100644 --- a/Cabal-tests/tests/ParserTests/regressions/issue-6083-a.expr +++ b/Cabal-tests/tests/ParserTests/regressions/issue-6083-a.expr @@ -111,21 +111,25 @@ GenericPackageDescription { LSubLibName (UnqualComponentName "sublib")]))], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "base") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "issue") - (OrLaterVersion (mkVersion [0])) - (NonEmptySet.fromNonEmpty - (NE.fromList - [ - LSubLibName - (UnqualComponentName - "sublib")]))], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "base") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "issue") + (OrLaterVersion (mkVersion [0])) + (NonEmptySet.fromNonEmpty + (NE.fromList + [ + LSubLibName + (UnqualComponentName + "sublib")]))], + privateDependencies = []}, condTreeComponents = []}, condSubLibraries = [ _×_ @@ -193,8 +197,12 @@ GenericPackageDescription { PerCompilerFlavor [] [], customFieldsBI = [], targetBuildDepends = [], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [], + condTreeConstraints = + Dependencies { + publicDependencies = [], + privateDependencies = []}, condTreeComponents = []}], condForeignLibs = [], condExecutables = [ @@ -267,16 +275,20 @@ GenericPackageDescription { (PackageName "sublib") (OrLaterVersion (mkVersion [0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "issue") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "sublib") - (OrLaterVersion (mkVersion [0])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "issue") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "sublib") + (OrLaterVersion (mkVersion [0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}, _×_ (UnqualComponentName "demo-b") @@ -352,21 +364,25 @@ GenericPackageDescription { LSubLibName (UnqualComponentName "sublib")]))], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "issue") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "issue") - (OrLaterVersion (mkVersion [0])) - (NonEmptySet.fromNonEmpty - (NE.fromList - [ - LSubLibName - (UnqualComponentName - "sublib")]))], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "issue") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "issue") + (OrLaterVersion (mkVersion [0])) + (NonEmptySet.fromNonEmpty + (NE.fromList + [ + LSubLibName + (UnqualComponentName + "sublib")]))], + privateDependencies = []}, condTreeComponents = []}], condTestSuites = [], condBenchmarks = []} diff --git a/Cabal-tests/tests/ParserTests/regressions/issue-6083-b.expr b/Cabal-tests/tests/ParserTests/regressions/issue-6083-b.expr index e6606851627..7de6fff480d 100644 --- a/Cabal-tests/tests/ParserTests/regressions/issue-6083-b.expr +++ b/Cabal-tests/tests/ParserTests/regressions/issue-6083-b.expr @@ -111,21 +111,25 @@ GenericPackageDescription { LSubLibName (UnqualComponentName "sublib")]))], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "base") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "issue") - (OrLaterVersion (mkVersion [0])) - (NonEmptySet.fromNonEmpty - (NE.fromList - [ - LSubLibName - (UnqualComponentName - "sublib")]))], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "base") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "issue") + (OrLaterVersion (mkVersion [0])) + (NonEmptySet.fromNonEmpty + (NE.fromList + [ + LSubLibName + (UnqualComponentName + "sublib")]))], + privateDependencies = []}, condTreeComponents = []}, condSubLibraries = [ _×_ @@ -193,8 +197,12 @@ GenericPackageDescription { PerCompilerFlavor [] [], customFieldsBI = [], targetBuildDepends = [], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [], + condTreeConstraints = + Dependencies { + publicDependencies = [], + privateDependencies = []}, condTreeComponents = []}], condForeignLibs = [], condExecutables = [ @@ -272,21 +280,25 @@ GenericPackageDescription { LSubLibName (UnqualComponentName "sublib")]))], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "issue") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "issue") - (OrLaterVersion (mkVersion [0])) - (NonEmptySet.fromNonEmpty - (NE.fromList - [ - LSubLibName - (UnqualComponentName - "sublib")]))], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "issue") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "issue") + (OrLaterVersion (mkVersion [0])) + (NonEmptySet.fromNonEmpty + (NE.fromList + [ + LSubLibName + (UnqualComponentName + "sublib")]))], + privateDependencies = []}, condTreeComponents = []}, _×_ (UnqualComponentName "demo-b") @@ -362,21 +374,25 @@ GenericPackageDescription { LSubLibName (UnqualComponentName "sublib")]))], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "issue") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "issue") - (OrLaterVersion (mkVersion [0])) - (NonEmptySet.fromNonEmpty - (NE.fromList - [ - LSubLibName - (UnqualComponentName - "sublib")]))], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "issue") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "issue") + (OrLaterVersion (mkVersion [0])) + (NonEmptySet.fromNonEmpty + (NE.fromList + [ + LSubLibName + (UnqualComponentName + "sublib")]))], + privateDependencies = []}, condTreeComponents = []}], condTestSuites = [], condBenchmarks = []} diff --git a/Cabal-tests/tests/ParserTests/regressions/issue-6083-c.expr b/Cabal-tests/tests/ParserTests/regressions/issue-6083-c.expr index 7435b0d59b4..aaafb65ceed 100644 --- a/Cabal-tests/tests/ParserTests/regressions/issue-6083-c.expr +++ b/Cabal-tests/tests/ParserTests/regressions/issue-6083-c.expr @@ -111,21 +111,25 @@ GenericPackageDescription { LSubLibName (UnqualComponentName "sublib")]))], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "base") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "issue") - (OrLaterVersion (mkVersion [0])) - (NonEmptySet.fromNonEmpty - (NE.fromList - [ - LSubLibName - (UnqualComponentName - "sublib")]))], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "base") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "issue") + (OrLaterVersion (mkVersion [0])) + (NonEmptySet.fromNonEmpty + (NE.fromList + [ + LSubLibName + (UnqualComponentName + "sublib")]))], + privateDependencies = []}, condTreeComponents = []}, condSubLibraries = [ _×_ @@ -193,8 +197,12 @@ GenericPackageDescription { PerCompilerFlavor [] [], customFieldsBI = [], targetBuildDepends = [], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [], + condTreeConstraints = + Dependencies { + publicDependencies = [], + privateDependencies = []}, condTreeComponents = []}], condForeignLibs = [], condExecutables = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/issue-6083-pkg-pkg.expr b/Cabal-tests/tests/ParserTests/regressions/issue-6083-pkg-pkg.expr index a221632efa4..bd946d92f0d 100644 --- a/Cabal-tests/tests/ParserTests/regressions/issue-6083-pkg-pkg.expr +++ b/Cabal-tests/tests/ParserTests/regressions/issue-6083-pkg-pkg.expr @@ -106,16 +106,20 @@ GenericPackageDescription { (PackageName "freetype") (OrLaterVersion (mkVersion [0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "freetype") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "freetype") - (OrLaterVersion (mkVersion [0])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "freetype") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "freetype") + (OrLaterVersion (mkVersion [0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}, condSubLibraries = [], condForeignLibs = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/issue-774.expr b/Cabal-tests/tests/ParserTests/regressions/issue-774.expr index e1ffb85dceb..eb23ebfb0b0 100644 --- a/Cabal-tests/tests/ParserTests/regressions/issue-774.expr +++ b/Cabal-tests/tests/ParserTests/regressions/issue-774.expr @@ -112,8 +112,12 @@ GenericPackageDescription { PerCompilerFlavor [] [], customFieldsBI = [], targetBuildDepends = [], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [], + condTreeConstraints = + Dependencies { + publicDependencies = [], + privateDependencies = []}, condTreeComponents = []}, condSubLibraries = [], condForeignLibs = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/jaeger-flamegraph.expr b/Cabal-tests/tests/ParserTests/regressions/jaeger-flamegraph.expr index c9e675ceb76..d4dacada3a3 100644 --- a/Cabal-tests/tests/ParserTests/regressions/jaeger-flamegraph.expr +++ b/Cabal-tests/tests/ParserTests/regressions/jaeger-flamegraph.expr @@ -156,21 +156,25 @@ GenericPackageDescription { (MajorBoundVersion (mkVersion [2, 12, 6, 1])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "base") - (UnionVersionRanges - (MajorBoundVersion - (mkVersion [4, 11, 1, 0])) + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "base") + (UnionVersionRanges + (MajorBoundVersion + (mkVersion [4, 11, 1, 0])) + (MajorBoundVersion + (mkVersion [4, 12, 0, 0]))) + mainLibSet, + Dependency + (PackageName "QuickCheck") (MajorBoundVersion - (mkVersion [4, 12, 0, 0]))) - mainLibSet, - Dependency - (PackageName "QuickCheck") - (MajorBoundVersion - (mkVersion [2, 12, 6, 1])) - mainLibSet], + (mkVersion [2, 12, 6, 1])) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}, condSubLibraries = [], condForeignLibs = [], @@ -286,52 +290,56 @@ GenericPackageDescription { (MajorBoundVersion (mkVersion [1, 2, 3, 1])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "base") - (UnionVersionRanges + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "base") + (UnionVersionRanges + (MajorBoundVersion + (mkVersion [4, 11, 1, 0])) + (MajorBoundVersion + (mkVersion [4, 12, 0, 0]))) + mainLibSet, + Dependency + (PackageName + "jaeger-flamegraph") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "bytestring") (MajorBoundVersion - (mkVersion [4, 11, 1, 0])) + (mkVersion [0, 10, 8, 2])) + mainLibSet, + Dependency + (PackageName "containers") (MajorBoundVersion - (mkVersion [4, 12, 0, 0]))) - mainLibSet, - Dependency - (PackageName - "jaeger-flamegraph") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "bytestring") - (MajorBoundVersion - (mkVersion [0, 10, 8, 2])) - mainLibSet, - Dependency - (PackageName "containers") - (MajorBoundVersion - (mkVersion [0, 6, 0, 1])) - mainLibSet, - Dependency - (PackageName "extra") - (MajorBoundVersion - (mkVersion [1, 6, 13])) - mainLibSet, - Dependency - (PackageName "aeson") - (MajorBoundVersion - (mkVersion [1, 4, 1, 0])) - mainLibSet, - Dependency - (PackageName - "optparse-applicative") - (MajorBoundVersion - (mkVersion [0, 14, 3, 0])) - mainLibSet, - Dependency - (PackageName "text") - (MajorBoundVersion - (mkVersion [1, 2, 3, 1])) - mainLibSet], + (mkVersion [0, 6, 0, 1])) + mainLibSet, + Dependency + (PackageName "extra") + (MajorBoundVersion + (mkVersion [1, 6, 13])) + mainLibSet, + Dependency + (PackageName "aeson") + (MajorBoundVersion + (mkVersion [1, 4, 1, 0])) + mainLibSet, + Dependency + (PackageName + "optparse-applicative") + (MajorBoundVersion + (mkVersion [0, 14, 3, 0])) + mainLibSet, + Dependency + (PackageName "text") + (MajorBoundVersion + (mkVersion [1, 2, 3, 1])) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}], condTestSuites = [ _×_ @@ -435,36 +443,40 @@ GenericPackageDescription { (MajorBoundVersion (mkVersion [0, 10])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}, testCodeGenerators = []}, - condTreeConstraints = [ - Dependency - (PackageName "base") - (UnionVersionRanges + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "base") + (UnionVersionRanges + (MajorBoundVersion + (mkVersion [4, 11, 1, 0])) + (MajorBoundVersion + (mkVersion [4, 12, 0, 0]))) + mainLibSet, + Dependency + (PackageName + "jaeger-flamegraph") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "tasty") (MajorBoundVersion - (mkVersion [4, 11, 1, 0])) + (mkVersion [1, 1, 0, 4])) + mainLibSet, + Dependency + (PackageName "tasty-hspec") (MajorBoundVersion - (mkVersion [4, 12, 0, 0]))) - mainLibSet, - Dependency - (PackageName - "jaeger-flamegraph") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "tasty") - (MajorBoundVersion - (mkVersion [1, 1, 0, 4])) - mainLibSet, - Dependency - (PackageName "tasty-hspec") - (MajorBoundVersion - (mkVersion [1, 1, 5])) - mainLibSet, - Dependency - (PackageName "tasty-quickcheck") - (MajorBoundVersion - (mkVersion [0, 10])) - mainLibSet], + (mkVersion [1, 1, 5])) + mainLibSet, + Dependency + (PackageName "tasty-quickcheck") + (MajorBoundVersion + (mkVersion [0, 10])) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}], condBenchmarks = []} diff --git a/Cabal-tests/tests/ParserTests/regressions/leading-comma-2.expr b/Cabal-tests/tests/ParserTests/regressions/leading-comma-2.expr index 0bb5556b2f4..d71b1d8604e 100644 --- a/Cabal-tests/tests/ParserTests/regressions/leading-comma-2.expr +++ b/Cabal-tests/tests/ParserTests/regressions/leading-comma-2.expr @@ -132,32 +132,36 @@ GenericPackageDescription { (PackageName "directory") (OrLaterVersion (mkVersion [0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "base") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "containers") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "deepseq") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "transformers") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "filepath") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "directory") - (OrLaterVersion (mkVersion [0])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "base") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "containers") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "deepseq") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "transformers") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "filepath") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "directory") + (OrLaterVersion (mkVersion [0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}, condSubLibraries = [], condForeignLibs = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/leading-comma.expr b/Cabal-tests/tests/ParserTests/regressions/leading-comma.expr index b1ba1b282f4..7a166677823 100644 --- a/Cabal-tests/tests/ParserTests/regressions/leading-comma.expr +++ b/Cabal-tests/tests/ParserTests/regressions/leading-comma.expr @@ -125,32 +125,36 @@ GenericPackageDescription { (PackageName "directory") (OrLaterVersion (mkVersion [0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "base") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "containers") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "deepseq") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "transformers") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "filepath") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "directory") - (OrLaterVersion (mkVersion [0])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "base") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "containers") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "deepseq") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "transformers") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "filepath") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "directory") + (OrLaterVersion (mkVersion [0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}, condSubLibraries = [], condForeignLibs = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/libpq1.expr b/Cabal-tests/tests/ParserTests/regressions/libpq1.expr index 8906a91f63b..8e097892041 100644 --- a/Cabal-tests/tests/ParserTests/regressions/libpq1.expr +++ b/Cabal-tests/tests/ParserTests/regressions/libpq1.expr @@ -210,24 +210,28 @@ GenericPackageDescription { (EarlierVersion (mkVersion [0, 11]))) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "base") - (IntersectVersionRanges - (OrLaterVersion - (mkVersion [4, 3])) - (EarlierVersion - (mkVersion [4, 13]))) - mainLibSet, - Dependency - (PackageName "bytestring") - (IntersectVersionRanges - (OrLaterVersion - (mkVersion [0, 9, 1, 0])) - (EarlierVersion - (mkVersion [0, 11]))) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "base") + (IntersectVersionRanges + (OrLaterVersion + (mkVersion [4, 3])) + (EarlierVersion + (mkVersion [4, 13]))) + mainLibSet, + Dependency + (PackageName "bytestring") + (IntersectVersionRanges + (OrLaterVersion + (mkVersion [0, 9, 1, 0])) + (EarlierVersion + (mkVersion [0, 11]))) + mainLibSet], + privateDependencies = []}, condTreeComponents = [ CondBranch { condBranchCondition = @@ -301,16 +305,20 @@ GenericPackageDescription { (EarlierVersion (mkVersion [2, 8]))) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "unix") - (IntersectVersionRanges - (OrLaterVersion - (mkVersion [2, 4, 2, 0])) - (EarlierVersion - (mkVersion [2, 8]))) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "unix") + (IntersectVersionRanges + (OrLaterVersion + (mkVersion [2, 4, 2, 0])) + (EarlierVersion + (mkVersion [2, 8]))) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}, condBranchIfFalse = Nothing}, CondBranch { @@ -385,16 +393,20 @@ GenericPackageDescription { (EarlierVersion (mkVersion [2, 7]))) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "Win32") - (IntersectVersionRanges - (OrLaterVersion - (mkVersion [2, 2, 0, 2])) - (EarlierVersion - (mkVersion [2, 7]))) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "Win32") + (IntersectVersionRanges + (OrLaterVersion + (mkVersion [2, 2, 0, 2])) + (EarlierVersion + (mkVersion [2, 7]))) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}, condBranchIfFalse = Nothing}, CondBranch { @@ -468,8 +480,12 @@ GenericPackageDescription { PerCompilerFlavor [] [], customFieldsBI = [], targetBuildDepends = [], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [], + condTreeConstraints = + Dependencies { + publicDependencies = [], + privateDependencies = []}, condTreeComponents = []}, condBranchIfFalse = Just CondNode { @@ -533,8 +549,12 @@ GenericPackageDescription { PerCompilerFlavor [] [], customFieldsBI = [], targetBuildDepends = [], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [], + condTreeConstraints = + Dependencies { + publicDependencies = [], + privateDependencies = []}, condTreeComponents = [ CondBranch { condBranchCondition = @@ -600,8 +620,12 @@ GenericPackageDescription { PerCompilerFlavor [] [], customFieldsBI = [], targetBuildDepends = [], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [], + condTreeConstraints = + Dependencies { + publicDependencies = [], + privateDependencies = []}, condTreeComponents = []}, condBranchIfFalse = Just CondNode { @@ -665,8 +689,12 @@ GenericPackageDescription { PerCompilerFlavor [] [], customFieldsBI = [], targetBuildDepends = [], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [], + condTreeConstraints = + Dependencies { + publicDependencies = [], + privateDependencies = []}, condTreeComponents = [ CondBranch { condBranchCondition = @@ -732,8 +760,12 @@ GenericPackageDescription { PerCompilerFlavor [] [], customFieldsBI = [], targetBuildDepends = [], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [], + condTreeConstraints = + Dependencies { + publicDependencies = [], + privateDependencies = []}, condTreeComponents = []}, condBranchIfFalse = Nothing}]}}]}}]}, diff --git a/Cabal-tests/tests/ParserTests/regressions/libpq2.expr b/Cabal-tests/tests/ParserTests/regressions/libpq2.expr index 3c26ece45ad..12539463cc4 100644 --- a/Cabal-tests/tests/ParserTests/regressions/libpq2.expr +++ b/Cabal-tests/tests/ParserTests/regressions/libpq2.expr @@ -215,24 +215,28 @@ GenericPackageDescription { (EarlierVersion (mkVersion [0, 11]))) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "base") - (IntersectVersionRanges - (OrLaterVersion - (mkVersion [4, 3])) - (EarlierVersion - (mkVersion [4, 13]))) - mainLibSet, - Dependency - (PackageName "bytestring") - (IntersectVersionRanges - (OrLaterVersion - (mkVersion [0, 9, 1, 0])) - (EarlierVersion - (mkVersion [0, 11]))) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "base") + (IntersectVersionRanges + (OrLaterVersion + (mkVersion [4, 3])) + (EarlierVersion + (mkVersion [4, 13]))) + mainLibSet, + Dependency + (PackageName "bytestring") + (IntersectVersionRanges + (OrLaterVersion + (mkVersion [0, 9, 1, 0])) + (EarlierVersion + (mkVersion [0, 11]))) + mainLibSet], + privateDependencies = []}, condTreeComponents = [ CondBranch { condBranchCondition = @@ -306,16 +310,20 @@ GenericPackageDescription { (EarlierVersion (mkVersion [2, 8]))) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "unix") - (IntersectVersionRanges - (OrLaterVersion - (mkVersion [2, 4, 2, 0])) - (EarlierVersion - (mkVersion [2, 8]))) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "unix") + (IntersectVersionRanges + (OrLaterVersion + (mkVersion [2, 4, 2, 0])) + (EarlierVersion + (mkVersion [2, 8]))) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}, condBranchIfFalse = Nothing}, CondBranch { @@ -390,16 +398,20 @@ GenericPackageDescription { (EarlierVersion (mkVersion [2, 7]))) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "Win32") - (IntersectVersionRanges - (OrLaterVersion - (mkVersion [2, 2, 0, 2])) - (EarlierVersion - (mkVersion [2, 7]))) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "Win32") + (IntersectVersionRanges + (OrLaterVersion + (mkVersion [2, 2, 0, 2])) + (EarlierVersion + (mkVersion [2, 7]))) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}, condBranchIfFalse = Nothing}, CondBranch { @@ -470,8 +482,12 @@ GenericPackageDescription { PerCompilerFlavor [] [], customFieldsBI = [], targetBuildDepends = [], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [], + condTreeConstraints = + Dependencies { + publicDependencies = [], + privateDependencies = []}, condTreeComponents = []}, condBranchIfFalse = Just CondNode { @@ -535,8 +551,12 @@ GenericPackageDescription { PerCompilerFlavor [] [], customFieldsBI = [], targetBuildDepends = [], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [], + condTreeConstraints = + Dependencies { + publicDependencies = [], + privateDependencies = []}, condTreeComponents = [ CondBranch { condBranchCondition = @@ -602,8 +622,12 @@ GenericPackageDescription { PerCompilerFlavor [] [], customFieldsBI = [], targetBuildDepends = [], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [], + condTreeConstraints = + Dependencies { + publicDependencies = [], + privateDependencies = []}, condTreeComponents = []}, condBranchIfFalse = Just CondNode { @@ -667,8 +691,12 @@ GenericPackageDescription { PerCompilerFlavor [] [], customFieldsBI = [], targetBuildDepends = [], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [], + condTreeConstraints = + Dependencies { + publicDependencies = [], + privateDependencies = []}, condTreeComponents = [ CondBranch { condBranchCondition = @@ -734,8 +762,12 @@ GenericPackageDescription { PerCompilerFlavor [] [], customFieldsBI = [], targetBuildDepends = [], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [], + condTreeConstraints = + Dependencies { + publicDependencies = [], + privateDependencies = []}, condTreeComponents = []}, condBranchIfFalse = Nothing}]}}]}}]}, diff --git a/Cabal-tests/tests/ParserTests/regressions/mixin-1.expr b/Cabal-tests/tests/ParserTests/regressions/mixin-1.expr index de8a15f04c0..27e23d6650f 100644 --- a/Cabal-tests/tests/ParserTests/regressions/mixin-1.expr +++ b/Cabal-tests/tests/ParserTests/regressions/mixin-1.expr @@ -114,6 +114,7 @@ GenericPackageDescription { (PackageName "str-bytestring") (OrLaterVersion (mkVersion [0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = [ Mixin { mixinPackageName = PackageName @@ -143,19 +144,22 @@ GenericPackageDescription { (ModuleName "Str.ByteString")], includeRequiresRn = DefaultRenaming}}]}}, - condTreeConstraints = [ - Dependency - (PackageName "base") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "str-string") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "str-bytestring") - (OrLaterVersion (mkVersion [0])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "base") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "str-string") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "str-bytestring") + (OrLaterVersion (mkVersion [0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}], condTestSuites = [], condBenchmarks = []} diff --git a/Cabal-tests/tests/ParserTests/regressions/mixin-2.expr b/Cabal-tests/tests/ParserTests/regressions/mixin-2.expr index 3bf06bc9c3b..e0ff2fcb192 100644 --- a/Cabal-tests/tests/ParserTests/regressions/mixin-2.expr +++ b/Cabal-tests/tests/ParserTests/regressions/mixin-2.expr @@ -114,6 +114,7 @@ GenericPackageDescription { (PackageName "str-bytestring") (OrLaterVersion (mkVersion [0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = [ Mixin { mixinPackageName = PackageName @@ -143,19 +144,22 @@ GenericPackageDescription { (ModuleName "Str.ByteString")], includeRequiresRn = DefaultRenaming}}]}}, - condTreeConstraints = [ - Dependency - (PackageName "base") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "str-string") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "str-bytestring") - (OrLaterVersion (mkVersion [0])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "base") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "str-string") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "str-bytestring") + (OrLaterVersion (mkVersion [0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}], condTestSuites = [], condBenchmarks = []} diff --git a/Cabal-tests/tests/ParserTests/regressions/mixin-3.expr b/Cabal-tests/tests/ParserTests/regressions/mixin-3.expr index 0c0fc57a8b8..d89df8b451d 100644 --- a/Cabal-tests/tests/ParserTests/regressions/mixin-3.expr +++ b/Cabal-tests/tests/ParserTests/regressions/mixin-3.expr @@ -114,6 +114,7 @@ GenericPackageDescription { (PackageName "str-bytestring") (OrLaterVersion (mkVersion [0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = [ Mixin { mixinPackageName = PackageName @@ -126,19 +127,22 @@ GenericPackageDescription { [ModuleName "Foo"], includeRequiresRn = DefaultRenaming}}]}}, - condTreeConstraints = [ - Dependency - (PackageName "base") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "str-string") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "str-bytestring") - (OrLaterVersion (mkVersion [0])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "base") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "str-string") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "str-bytestring") + (OrLaterVersion (mkVersion [0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}], condTestSuites = [], condBenchmarks = []} diff --git a/Cabal-tests/tests/ParserTests/regressions/monad-param.expr b/Cabal-tests/tests/ParserTests/regressions/monad-param.expr index 28d57c1e3b0..296104ef38b 100644 --- a/Cabal-tests/tests/ParserTests/regressions/monad-param.expr +++ b/Cabal-tests/tests/ParserTests/regressions/monad-param.expr @@ -136,20 +136,24 @@ GenericPackageDescription { (PackageName "stm") (OrLaterVersion (mkVersion [0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "base") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "mtl") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "stm") - (OrLaterVersion (mkVersion [0])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "base") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "mtl") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "stm") + (OrLaterVersion (mkVersion [0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}, condSubLibraries = [], condForeignLibs = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/multiple-libs-2.expr b/Cabal-tests/tests/ParserTests/regressions/multiple-libs-2.expr index a8c6b0c0c4a..48b5264673c 100644 --- a/Cabal-tests/tests/ParserTests/regressions/multiple-libs-2.expr +++ b/Cabal-tests/tests/ParserTests/regressions/multiple-libs-2.expr @@ -105,12 +105,16 @@ GenericPackageDescription { (PackageName "base") (OrLaterVersion (mkVersion [0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "base") - (OrLaterVersion (mkVersion [0])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "base") + (OrLaterVersion (mkVersion [0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}, condSubLibraries = [ _×_ @@ -183,12 +187,16 @@ GenericPackageDescription { (PackageName "base") (OrLaterVersion (mkVersion [0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "base") - (OrLaterVersion (mkVersion [0])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "base") + (OrLaterVersion (mkVersion [0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}], condForeignLibs = [], condExecutables = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/noVersion.expr b/Cabal-tests/tests/ParserTests/regressions/noVersion.expr index 8187272c2c0..f4f99c23bb3 100644 --- a/Cabal-tests/tests/ParserTests/regressions/noVersion.expr +++ b/Cabal-tests/tests/ParserTests/regressions/noVersion.expr @@ -105,12 +105,16 @@ GenericPackageDescription { (PackageName "bad-package") (EarlierVersion (mkVersion [0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "bad-package") - (EarlierVersion (mkVersion [0])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "bad-package") + (EarlierVersion (mkVersion [0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}, condSubLibraries = [], condForeignLibs = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/nothing-unicode.expr b/Cabal-tests/tests/ParserTests/regressions/nothing-unicode.expr index 2f2663733c6..74501fb3845 100644 --- a/Cabal-tests/tests/ParserTests/regressions/nothing-unicode.expr +++ b/Cabal-tests/tests/ParserTests/regressions/nothing-unicode.expr @@ -116,8 +116,12 @@ GenericPackageDescription { PerCompilerFlavor [] [], customFieldsBI = [], targetBuildDepends = [], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [], + condTreeConstraints = + Dependencies { + publicDependencies = [], + privateDependencies = []}, condTreeComponents = [ CondBranch { condBranchCondition = @@ -183,8 +187,12 @@ GenericPackageDescription { PerCompilerFlavor [] [], customFieldsBI = [], targetBuildDepends = [], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [], + condTreeConstraints = + Dependencies { + publicDependencies = [], + privateDependencies = []}, condTreeComponents = []}, condBranchIfFalse = Nothing}]}, condSubLibraries = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/shake.expr b/Cabal-tests/tests/ParserTests/regressions/shake.expr index 8dd849d75bd..5099b41c052 100644 --- a/Cabal-tests/tests/ParserTests/regressions/shake.expr +++ b/Cabal-tests/tests/ParserTests/regressions/shake.expr @@ -383,81 +383,85 @@ GenericPackageDescription { (OrLaterVersion (mkVersion [1, 1])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "base") - (OrLaterVersion - (mkVersion [4, 5])) - mainLibSet, - Dependency - (PackageName "directory") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "hashable") - (OrLaterVersion - (mkVersion [1, 1, 2, 3])) - mainLibSet, - Dependency - (PackageName "binary") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "filepath") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "process") - (OrLaterVersion - (mkVersion [1, 1])) - mainLibSet, - Dependency - (PackageName - "unordered-containers") - (OrLaterVersion - (mkVersion [0, 2, 1])) - mainLibSet, - Dependency - (PackageName "bytestring") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "utf8-string") - (OrLaterVersion - (mkVersion [0, 3])) - mainLibSet, - Dependency - (PackageName "time") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "random") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "js-jquery") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "js-flot") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "transformers") - (OrLaterVersion - (mkVersion [0, 2])) - mainLibSet, - Dependency - (PackageName "extra") - (OrLaterVersion - (mkVersion [1, 4, 8])) - mainLibSet, - Dependency - (PackageName "deepseq") - (OrLaterVersion - (mkVersion [1, 1])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "base") + (OrLaterVersion + (mkVersion [4, 5])) + mainLibSet, + Dependency + (PackageName "directory") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "hashable") + (OrLaterVersion + (mkVersion [1, 1, 2, 3])) + mainLibSet, + Dependency + (PackageName "binary") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "filepath") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "process") + (OrLaterVersion + (mkVersion [1, 1])) + mainLibSet, + Dependency + (PackageName + "unordered-containers") + (OrLaterVersion + (mkVersion [0, 2, 1])) + mainLibSet, + Dependency + (PackageName "bytestring") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "utf8-string") + (OrLaterVersion + (mkVersion [0, 3])) + mainLibSet, + Dependency + (PackageName "time") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "random") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "js-jquery") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "js-flot") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "transformers") + (OrLaterVersion + (mkVersion [0, 2])) + mainLibSet, + Dependency + (PackageName "extra") + (OrLaterVersion + (mkVersion [1, 4, 8])) + mainLibSet, + Dependency + (PackageName "deepseq") + (OrLaterVersion + (mkVersion [1, 1])) + mainLibSet], + privateDependencies = []}, condTreeComponents = [ CondBranch { condBranchCondition = @@ -523,8 +527,12 @@ GenericPackageDescription { PerCompilerFlavor [] [], customFieldsBI = [], targetBuildDepends = [], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [], + condTreeConstraints = + Dependencies { + publicDependencies = [], + privateDependencies = []}, condTreeComponents = [ CondBranch { condBranchCondition = @@ -594,12 +602,16 @@ GenericPackageDescription { (PackageName "old-time") (OrLaterVersion (mkVersion [0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "old-time") - (OrLaterVersion (mkVersion [0])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "old-time") + (OrLaterVersion (mkVersion [0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}, condBranchIfFalse = Nothing}]}, condBranchIfFalse = Just @@ -664,8 +676,12 @@ GenericPackageDescription { PerCompilerFlavor [] [], customFieldsBI = [], targetBuildDepends = [], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [], + condTreeConstraints = + Dependencies { + publicDependencies = [], + privateDependencies = []}, condTreeComponents = [ CondBranch { condBranchCondition = @@ -736,13 +752,17 @@ GenericPackageDescription { (OrLaterVersion (mkVersion [2, 5, 1])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "unix") - (OrLaterVersion - (mkVersion [2, 5, 1])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "unix") + (OrLaterVersion + (mkVersion [2, 5, 1])) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}, condBranchIfFalse = Nothing}]}}, CondBranch { @@ -813,12 +833,16 @@ GenericPackageDescription { (PackageName "unix") (OrLaterVersion (mkVersion [0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "unix") - (OrLaterVersion (mkVersion [0])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "unix") + (OrLaterVersion (mkVersion [0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}, condBranchIfFalse = Nothing}]}, condSubLibraries = [], @@ -1065,87 +1089,91 @@ GenericPackageDescription { (PackageName "primitive") (OrLaterVersion (mkVersion [0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "base") - (IntersectVersionRanges - (OrLaterVersion (mkVersion [4])) - (EarlierVersion - (mkVersion [5]))) - mainLibSet, - Dependency - (PackageName "directory") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "hashable") - (OrLaterVersion - (mkVersion [1, 1, 2, 3])) - mainLibSet, - Dependency - (PackageName "binary") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "filepath") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "process") - (OrLaterVersion - (mkVersion [1, 1])) - mainLibSet, - Dependency - (PackageName - "unordered-containers") - (OrLaterVersion - (mkVersion [0, 2, 1])) - mainLibSet, - Dependency - (PackageName "bytestring") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "utf8-string") - (OrLaterVersion - (mkVersion [0, 3])) - mainLibSet, - Dependency - (PackageName "time") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "random") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "js-jquery") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "js-flot") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "transformers") - (OrLaterVersion - (mkVersion [0, 2])) - mainLibSet, - Dependency - (PackageName "extra") - (OrLaterVersion - (mkVersion [1, 4, 8])) - mainLibSet, - Dependency - (PackageName "deepseq") - (OrLaterVersion - (mkVersion [1, 1])) - mainLibSet, - Dependency - (PackageName "primitive") - (OrLaterVersion (mkVersion [0])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "base") + (IntersectVersionRanges + (OrLaterVersion (mkVersion [4])) + (EarlierVersion + (mkVersion [5]))) + mainLibSet, + Dependency + (PackageName "directory") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "hashable") + (OrLaterVersion + (mkVersion [1, 1, 2, 3])) + mainLibSet, + Dependency + (PackageName "binary") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "filepath") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "process") + (OrLaterVersion + (mkVersion [1, 1])) + mainLibSet, + Dependency + (PackageName + "unordered-containers") + (OrLaterVersion + (mkVersion [0, 2, 1])) + mainLibSet, + Dependency + (PackageName "bytestring") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "utf8-string") + (OrLaterVersion + (mkVersion [0, 3])) + mainLibSet, + Dependency + (PackageName "time") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "random") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "js-jquery") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "js-flot") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "transformers") + (OrLaterVersion + (mkVersion [0, 2])) + mainLibSet, + Dependency + (PackageName "extra") + (OrLaterVersion + (mkVersion [1, 4, 8])) + mainLibSet, + Dependency + (PackageName "deepseq") + (OrLaterVersion + (mkVersion [1, 1])) + mainLibSet, + Dependency + (PackageName "primitive") + (OrLaterVersion (mkVersion [0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = [ CondBranch { condBranchCondition = @@ -1210,8 +1238,12 @@ GenericPackageDescription { PerCompilerFlavor [] [], customFieldsBI = [], targetBuildDepends = [], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [], + condTreeConstraints = + Dependencies { + publicDependencies = [], + privateDependencies = []}, condTreeComponents = []}, condBranchIfFalse = Nothing}, CondBranch { @@ -1275,8 +1307,12 @@ GenericPackageDescription { PerCompilerFlavor [] [], customFieldsBI = [], targetBuildDepends = [], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [], + condTreeConstraints = + Dependencies { + publicDependencies = [], + privateDependencies = []}, condTreeComponents = [ CondBranch { condBranchCondition = @@ -1343,12 +1379,16 @@ GenericPackageDescription { (PackageName "old-time") (OrLaterVersion (mkVersion [0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "old-time") - (OrLaterVersion (mkVersion [0])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "old-time") + (OrLaterVersion (mkVersion [0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}, condBranchIfFalse = Nothing}]}, condBranchIfFalse = Just @@ -1410,8 +1450,12 @@ GenericPackageDescription { PerCompilerFlavor [] [], customFieldsBI = [], targetBuildDepends = [], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [], + condTreeConstraints = + Dependencies { + publicDependencies = [], + privateDependencies = []}, condTreeComponents = [ CondBranch { condBranchCondition = @@ -1479,13 +1523,17 @@ GenericPackageDescription { (OrLaterVersion (mkVersion [2, 5, 1])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "unix") - (OrLaterVersion - (mkVersion [2, 5, 1])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "unix") + (OrLaterVersion + (mkVersion [2, 5, 1])) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}, condBranchIfFalse = Nothing}]}}, CondBranch { @@ -1553,12 +1601,16 @@ GenericPackageDescription { (PackageName "unix") (OrLaterVersion (mkVersion [0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "unix") - (OrLaterVersion (mkVersion [0])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "unix") + (OrLaterVersion (mkVersion [0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}, condBranchIfFalse = Nothing}]}], condTestSuites = [ @@ -1848,89 +1900,93 @@ GenericPackageDescription { (OrLaterVersion (mkVersion [2, 0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}, testCodeGenerators = []}, - condTreeConstraints = [ - Dependency - (PackageName "base") - (IntersectVersionRanges - (OrLaterVersion (mkVersion [4])) - (EarlierVersion - (mkVersion [5]))) - mainLibSet, - Dependency - (PackageName "directory") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "hashable") - (OrLaterVersion - (mkVersion [1, 1, 2, 3])) - mainLibSet, - Dependency - (PackageName "binary") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "filepath") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "process") - (OrLaterVersion - (mkVersion [1, 1])) - mainLibSet, - Dependency - (PackageName - "unordered-containers") - (OrLaterVersion - (mkVersion [0, 2, 1])) - mainLibSet, - Dependency - (PackageName "bytestring") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "utf8-string") - (OrLaterVersion - (mkVersion [0, 3])) - mainLibSet, - Dependency - (PackageName "time") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "random") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "js-jquery") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "js-flot") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "transformers") - (OrLaterVersion - (mkVersion [0, 2])) - mainLibSet, - Dependency - (PackageName "deepseq") - (OrLaterVersion - (mkVersion [1, 1])) - mainLibSet, - Dependency - (PackageName "extra") - (OrLaterVersion - (mkVersion [1, 4, 8])) - mainLibSet, - Dependency - (PackageName "QuickCheck") - (OrLaterVersion - (mkVersion [2, 0])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "base") + (IntersectVersionRanges + (OrLaterVersion (mkVersion [4])) + (EarlierVersion + (mkVersion [5]))) + mainLibSet, + Dependency + (PackageName "directory") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "hashable") + (OrLaterVersion + (mkVersion [1, 1, 2, 3])) + mainLibSet, + Dependency + (PackageName "binary") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "filepath") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "process") + (OrLaterVersion + (mkVersion [1, 1])) + mainLibSet, + Dependency + (PackageName + "unordered-containers") + (OrLaterVersion + (mkVersion [0, 2, 1])) + mainLibSet, + Dependency + (PackageName "bytestring") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "utf8-string") + (OrLaterVersion + (mkVersion [0, 3])) + mainLibSet, + Dependency + (PackageName "time") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "random") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "js-jquery") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "js-flot") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "transformers") + (OrLaterVersion + (mkVersion [0, 2])) + mainLibSet, + Dependency + (PackageName "deepseq") + (OrLaterVersion + (mkVersion [1, 1])) + mainLibSet, + Dependency + (PackageName "extra") + (OrLaterVersion + (mkVersion [1, 4, 8])) + mainLibSet, + Dependency + (PackageName "QuickCheck") + (OrLaterVersion + (mkVersion [2, 0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = [ CondBranch { condBranchCondition = @@ -1996,9 +2052,13 @@ GenericPackageDescription { PerCompilerFlavor [] [], customFieldsBI = [], targetBuildDepends = [], + targetPrivateBuildDepends = [], mixins = []}, testCodeGenerators = []}, - condTreeConstraints = [], + condTreeConstraints = + Dependencies { + publicDependencies = [], + privateDependencies = []}, condTreeComponents = []}, condBranchIfFalse = Nothing}, CondBranch { @@ -2065,9 +2125,13 @@ GenericPackageDescription { PerCompilerFlavor [] [], customFieldsBI = [], targetBuildDepends = [], + targetPrivateBuildDepends = [], mixins = []}, testCodeGenerators = []}, - condTreeConstraints = [], + condTreeConstraints = + Dependencies { + publicDependencies = [], + privateDependencies = []}, condTreeComponents = []}, condBranchIfFalse = Nothing}, CondBranch { @@ -2134,9 +2198,13 @@ GenericPackageDescription { PerCompilerFlavor [] [], customFieldsBI = [], targetBuildDepends = [], + targetPrivateBuildDepends = [], mixins = []}, testCodeGenerators = []}, - condTreeConstraints = [], + condTreeConstraints = + Dependencies { + publicDependencies = [], + privateDependencies = []}, condTreeComponents = [ CondBranch { condBranchCondition = @@ -2206,13 +2274,17 @@ GenericPackageDescription { (PackageName "old-time") (OrLaterVersion (mkVersion [0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}, testCodeGenerators = []}, - condTreeConstraints = [ - Dependency - (PackageName "old-time") - (OrLaterVersion (mkVersion [0])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "old-time") + (OrLaterVersion (mkVersion [0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}, condBranchIfFalse = Nothing}]}, condBranchIfFalse = Just @@ -2277,9 +2349,13 @@ GenericPackageDescription { PerCompilerFlavor [] [], customFieldsBI = [], targetBuildDepends = [], + targetPrivateBuildDepends = [], mixins = []}, testCodeGenerators = []}, - condTreeConstraints = [], + condTreeConstraints = + Dependencies { + publicDependencies = [], + privateDependencies = []}, condTreeComponents = [ CondBranch { condBranchCondition = @@ -2350,14 +2426,18 @@ GenericPackageDescription { (OrLaterVersion (mkVersion [2, 5, 1])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}, testCodeGenerators = []}, - condTreeConstraints = [ - Dependency - (PackageName "unix") - (OrLaterVersion - (mkVersion [2, 5, 1])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "unix") + (OrLaterVersion + (mkVersion [2, 5, 1])) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}, condBranchIfFalse = Nothing}]}}, CondBranch { @@ -2428,13 +2508,17 @@ GenericPackageDescription { (PackageName "unix") (OrLaterVersion (mkVersion [0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}, testCodeGenerators = []}, - condTreeConstraints = [ - Dependency - (PackageName "unix") - (OrLaterVersion (mkVersion [0])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "unix") + (OrLaterVersion (mkVersion [0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}, condBranchIfFalse = Nothing}]}], condBenchmarks = []} diff --git a/Cabal-tests/tests/ParserTests/regressions/spdx-1.expr b/Cabal-tests/tests/ParserTests/regressions/spdx-1.expr index 2ca07bf2322..a4b5453730b 100644 --- a/Cabal-tests/tests/ParserTests/regressions/spdx-1.expr +++ b/Cabal-tests/tests/ParserTests/regressions/spdx-1.expr @@ -99,8 +99,12 @@ GenericPackageDescription { PerCompilerFlavor [] [], customFieldsBI = [], targetBuildDepends = [], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [], + condTreeConstraints = + Dependencies { + publicDependencies = [], + privateDependencies = []}, condTreeComponents = []}, condSubLibraries = [], condForeignLibs = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/spdx-2.expr b/Cabal-tests/tests/ParserTests/regressions/spdx-2.expr index 9c50edd4864..c4bdcfb0c1c 100644 --- a/Cabal-tests/tests/ParserTests/regressions/spdx-2.expr +++ b/Cabal-tests/tests/ParserTests/regressions/spdx-2.expr @@ -103,8 +103,12 @@ GenericPackageDescription { PerCompilerFlavor [] [], customFieldsBI = [], targetBuildDepends = [], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [], + condTreeConstraints = + Dependencies { + publicDependencies = [], + privateDependencies = []}, condTreeComponents = []}, condSubLibraries = [], condForeignLibs = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/spdx-3.expr b/Cabal-tests/tests/ParserTests/regressions/spdx-3.expr index 944faa4c0c0..53abd4ed448 100644 --- a/Cabal-tests/tests/ParserTests/regressions/spdx-3.expr +++ b/Cabal-tests/tests/ParserTests/regressions/spdx-3.expr @@ -103,8 +103,12 @@ GenericPackageDescription { PerCompilerFlavor [] [], customFieldsBI = [], targetBuildDepends = [], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [], + condTreeConstraints = + Dependencies { + publicDependencies = [], + privateDependencies = []}, condTreeComponents = []}, condSubLibraries = [], condForeignLibs = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/th-lift-instances.expr b/Cabal-tests/tests/ParserTests/regressions/th-lift-instances.expr index 8f2edf09a36..dd59047de84 100644 --- a/Cabal-tests/tests/ParserTests/regressions/th-lift-instances.expr +++ b/Cabal-tests/tests/ParserTests/regressions/th-lift-instances.expr @@ -180,57 +180,61 @@ GenericPackageDescription { (EarlierVersion (mkVersion [0, 11]))) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "base") - (IntersectVersionRanges - (OrLaterVersion - (mkVersion [4, 4])) - (EarlierVersion - (mkVersion [5]))) - mainLibSet, - Dependency - (PackageName "template-haskell") - (EarlierVersion - (mkVersion [2, 10])) - mainLibSet, - Dependency - (PackageName "th-lift") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "containers") - (IntersectVersionRanges - (OrLaterVersion - (mkVersion [0, 4])) - (EarlierVersion - (mkVersion [0, 6]))) - mainLibSet, - Dependency - (PackageName "vector") - (IntersectVersionRanges - (OrLaterVersion - (mkVersion [0, 9])) - (EarlierVersion - (mkVersion [0, 11]))) - mainLibSet, - Dependency - (PackageName "text") - (IntersectVersionRanges - (OrLaterVersion - (mkVersion [0, 11])) - (EarlierVersion - (mkVersion [1, 3]))) - mainLibSet, - Dependency - (PackageName "bytestring") - (IntersectVersionRanges - (OrLaterVersion - (mkVersion [0, 9])) + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "base") + (IntersectVersionRanges + (OrLaterVersion + (mkVersion [4, 4])) + (EarlierVersion + (mkVersion [5]))) + mainLibSet, + Dependency + (PackageName "template-haskell") (EarlierVersion - (mkVersion [0, 11]))) - mainLibSet], + (mkVersion [2, 10])) + mainLibSet, + Dependency + (PackageName "th-lift") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "containers") + (IntersectVersionRanges + (OrLaterVersion + (mkVersion [0, 4])) + (EarlierVersion + (mkVersion [0, 6]))) + mainLibSet, + Dependency + (PackageName "vector") + (IntersectVersionRanges + (OrLaterVersion + (mkVersion [0, 9])) + (EarlierVersion + (mkVersion [0, 11]))) + mainLibSet, + Dependency + (PackageName "text") + (IntersectVersionRanges + (OrLaterVersion + (mkVersion [0, 11])) + (EarlierVersion + (mkVersion [1, 3]))) + mainLibSet, + Dependency + (PackageName "bytestring") + (IntersectVersionRanges + (OrLaterVersion + (mkVersion [0, 9])) + (EarlierVersion + (mkVersion [0, 11]))) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}, condSubLibraries = [], condForeignLibs = [], @@ -356,63 +360,67 @@ GenericPackageDescription { (EarlierVersion (mkVersion [2, 8]))) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}, testCodeGenerators = []}, - condTreeConstraints = [ - Dependency - (PackageName "base") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "template-haskell") - (EarlierVersion - (mkVersion [2, 10])) - mainLibSet, - Dependency - (PackageName "containers") - (IntersectVersionRanges - (OrLaterVersion - (mkVersion [0, 4])) - (EarlierVersion - (mkVersion [0, 6]))) - mainLibSet, - Dependency - (PackageName "vector") - (IntersectVersionRanges - (OrLaterVersion - (mkVersion [0, 9])) - (EarlierVersion - (mkVersion [0, 11]))) - mainLibSet, - Dependency - (PackageName "text") - (IntersectVersionRanges - (OrLaterVersion - (mkVersion [0, 11])) - (EarlierVersion - (mkVersion [1, 2]))) - mainLibSet, - Dependency - (PackageName "bytestring") - (IntersectVersionRanges - (OrLaterVersion - (mkVersion [0, 9])) - (EarlierVersion - (mkVersion [0, 11]))) - mainLibSet, - Dependency - (PackageName - "th-lift-instances") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "QuickCheck") - (IntersectVersionRanges - (OrLaterVersion - (mkVersion [2, 6])) + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "base") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "template-haskell") (EarlierVersion - (mkVersion [2, 8]))) - mainLibSet], + (mkVersion [2, 10])) + mainLibSet, + Dependency + (PackageName "containers") + (IntersectVersionRanges + (OrLaterVersion + (mkVersion [0, 4])) + (EarlierVersion + (mkVersion [0, 6]))) + mainLibSet, + Dependency + (PackageName "vector") + (IntersectVersionRanges + (OrLaterVersion + (mkVersion [0, 9])) + (EarlierVersion + (mkVersion [0, 11]))) + mainLibSet, + Dependency + (PackageName "text") + (IntersectVersionRanges + (OrLaterVersion + (mkVersion [0, 11])) + (EarlierVersion + (mkVersion [1, 2]))) + mainLibSet, + Dependency + (PackageName "bytestring") + (IntersectVersionRanges + (OrLaterVersion + (mkVersion [0, 9])) + (EarlierVersion + (mkVersion [0, 11]))) + mainLibSet, + Dependency + (PackageName + "th-lift-instances") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "QuickCheck") + (IntersectVersionRanges + (OrLaterVersion + (mkVersion [2, 6])) + (EarlierVersion + (mkVersion [2, 8]))) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}, _×_ (UnqualComponentName "doctests") @@ -495,27 +503,31 @@ GenericPackageDescription { (PackageName "filepath") (OrLaterVersion (mkVersion [0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}, testCodeGenerators = []}, - condTreeConstraints = [ - Dependency - (PackageName "base") - (OrLaterVersion (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "directory") - (OrLaterVersion - (mkVersion [1, 0])) - mainLibSet, - Dependency - (PackageName "doctest") - (OrLaterVersion - (mkVersion [0, 9, 1])) - mainLibSet, - Dependency - (PackageName "filepath") - (OrLaterVersion (mkVersion [0])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "base") + (OrLaterVersion (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "directory") + (OrLaterVersion + (mkVersion [1, 0])) + mainLibSet, + Dependency + (PackageName "doctest") + (OrLaterVersion + (mkVersion [0, 9, 1])) + mainLibSet, + Dependency + (PackageName "filepath") + (OrLaterVersion (mkVersion [0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = [ CondBranch { condBranchCondition = @@ -581,9 +593,13 @@ GenericPackageDescription { PerCompilerFlavor [] [], customFieldsBI = [], targetBuildDepends = [], + targetPrivateBuildDepends = [], mixins = []}, testCodeGenerators = []}, - condTreeConstraints = [], + condTreeConstraints = + Dependencies { + publicDependencies = [], + privateDependencies = []}, condTreeComponents = []}, condBranchIfFalse = Nothing}]}], condBenchmarks = []} diff --git a/Cabal-tests/tests/ParserTests/regressions/version-sets.expr b/Cabal-tests/tests/ParserTests/regressions/version-sets.expr index b134e4584ad..1d3277c8b33 100644 --- a/Cabal-tests/tests/ParserTests/regressions/version-sets.expr +++ b/Cabal-tests/tests/ParserTests/regressions/version-sets.expr @@ -189,72 +189,76 @@ GenericPackageDescription { (MajorBoundVersion (mkVersion [2, 2, 0, 0]))) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "network") - (MajorBoundVersion - (mkVersion [0])) - mainLibSet, - Dependency - (PackageName "base") - (ThisVersion (mkVersion [1])) - mainLibSet, - Dependency - (PackageName "base") - (ThisVersion (mkVersion [1])) - mainLibSet, - Dependency - (PackageName "base") - (UnionVersionRanges + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "network") + (MajorBoundVersion + (mkVersion [0])) + mainLibSet, + Dependency + (PackageName "base") (ThisVersion (mkVersion [1])) - (ThisVersion (mkVersion [2]))) - mainLibSet, - Dependency - (PackageName "base") - (ThisVersion (mkVersion [1, 2])) - mainLibSet, - Dependency - (PackageName "base") - (UnionVersionRanges + mainLibSet, + Dependency + (PackageName "base") + (ThisVersion (mkVersion [1])) + mainLibSet, + Dependency + (PackageName "base") + (UnionVersionRanges + (ThisVersion (mkVersion [1])) + (ThisVersion (mkVersion [2]))) + mainLibSet, + Dependency + (PackageName "base") (ThisVersion (mkVersion [1, 2])) - (ThisVersion - (mkVersion [3, 4]))) - mainLibSet, - Dependency - (PackageName "ghc") - (UnionVersionRanges - (ThisVersion - (mkVersion [8, 6, 3])) + mainLibSet, + Dependency + (PackageName "base") + (UnionVersionRanges + (ThisVersion (mkVersion [1, 2])) + (ThisVersion + (mkVersion [3, 4]))) + mainLibSet, + Dependency + (PackageName "ghc") (UnionVersionRanges (ThisVersion - (mkVersion [8, 4, 4])) + (mkVersion [8, 6, 3])) (UnionVersionRanges (ThisVersion - (mkVersion [8, 2, 2])) + (mkVersion [8, 4, 4])) (UnionVersionRanges (ThisVersion - (mkVersion [8, 0, 2])) + (mkVersion [8, 2, 2])) (UnionVersionRanges (ThisVersion - (mkVersion [7, 10, 3])) + (mkVersion [8, 0, 2])) (UnionVersionRanges (ThisVersion - (mkVersion [7, 8, 4])) + (mkVersion [7, 10, 3])) (UnionVersionRanges (ThisVersion - (mkVersion [7, 6, 3])) - (ThisVersion - (mkVersion [7, 4, 2]))))))))) - mainLibSet, - Dependency - (PackageName "Cabal") - (UnionVersionRanges - (MajorBoundVersion - (mkVersion [2, 4, 1, 1])) - (MajorBoundVersion - (mkVersion [2, 2, 0, 0]))) - mainLibSet], + (mkVersion [7, 8, 4])) + (UnionVersionRanges + (ThisVersion + (mkVersion [7, 6, 3])) + (ThisVersion + (mkVersion [7, 4, 2]))))))))) + mainLibSet, + Dependency + (PackageName "Cabal") + (UnionVersionRanges + (MajorBoundVersion + (mkVersion [2, 4, 1, 1])) + (MajorBoundVersion + (mkVersion [2, 2, 0, 0]))) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}, condSubLibraries = [], condForeignLibs = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/wl-pprint-indef.expr b/Cabal-tests/tests/ParserTests/regressions/wl-pprint-indef.expr index 03959b195c0..ebd5e41d199 100644 --- a/Cabal-tests/tests/ParserTests/regressions/wl-pprint-indef.expr +++ b/Cabal-tests/tests/ParserTests/regressions/wl-pprint-indef.expr @@ -127,17 +127,21 @@ GenericPackageDescription { (OrLaterVersion (mkVersion [0, 1, 0, 0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "base") - (EarlierVersion (mkVersion [5])) - mainLibSet, - Dependency - (PackageName "str-sig") - (OrLaterVersion - (mkVersion [0, 1, 0, 0])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "base") + (EarlierVersion (mkVersion [5])) + mainLibSet, + Dependency + (PackageName "str-sig") + (OrLaterVersion + (mkVersion [0, 1, 0, 0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}, condSubLibraries = [], condForeignLibs = [], @@ -219,21 +223,25 @@ GenericPackageDescription { (PackageName "wl-pprint-indef") (OrLaterVersion (mkVersion [0])) mainLibSet], + targetPrivateBuildDepends = [], mixins = []}}, - condTreeConstraints = [ - Dependency - (PackageName "base") - (EarlierVersion (mkVersion [5])) - mainLibSet, - Dependency - (PackageName "str-string") - (OrLaterVersion - (mkVersion [0, 1, 0, 0])) - mainLibSet, - Dependency - (PackageName "wl-pprint-indef") - (OrLaterVersion (mkVersion [0])) - mainLibSet], + condTreeConstraints = + Dependencies { + publicDependencies = [ + Dependency + (PackageName "base") + (EarlierVersion (mkVersion [5])) + mainLibSet, + Dependency + (PackageName "str-string") + (OrLaterVersion + (mkVersion [0, 1, 0, 0])) + mainLibSet, + Dependency + (PackageName "wl-pprint-indef") + (OrLaterVersion (mkVersion [0])) + mainLibSet], + privateDependencies = []}, condTreeComponents = []}], condTestSuites = [], condBenchmarks = []} diff --git a/Cabal-tests/tests/UnitTests/Distribution/Described.hs b/Cabal-tests/tests/UnitTests/Distribution/Described.hs index 2c73c805c71..4e041c6d380 100644 --- a/Cabal-tests/tests/UnitTests/Distribution/Described.hs +++ b/Cabal-tests/tests/UnitTests/Distribution/Described.hs @@ -12,7 +12,7 @@ import Test.Tasty (TestTree, testGroup) import Distribution.Compiler (CompilerFlavor, CompilerId) import Distribution.ModuleName (ModuleName) import Distribution.System (Arch, OS) -import Distribution.Types.Dependency (Dependency) +import Distribution.Types.Dependency (Dependency, PrivateDependency) import Distribution.Types.Flag (FlagAssignment, FlagName) import Distribution.Types.IncludeRenaming (IncludeRenaming) import Distribution.Types.Mixin (Mixin) @@ -30,6 +30,7 @@ import Test.QuickCheck.Instances.Cabal () tests :: TestTree tests = testGroup "Described" [ testDescribed (Proxy :: Proxy Dependency) + , testDescribed (Proxy :: Proxy PrivateDependency) , testDescribed (Proxy :: Proxy PackageName) , testDescribed (Proxy :: Proxy PackageIdentifier) , testDescribed (Proxy :: Proxy PackageVersionConstraint) diff --git a/Cabal-tests/tests/UnitTests/Distribution/Utils/Structured.hs b/Cabal-tests/tests/UnitTests/Distribution/Utils/Structured.hs index 9b36dd9d7ce..c59f83e69f3 100644 --- a/Cabal-tests/tests/UnitTests/Distribution/Utils/Structured.hs +++ b/Cabal-tests/tests/UnitTests/Distribution/Utils/Structured.hs @@ -33,15 +33,15 @@ md5Check proxy md5Int = structureHash proxy @?= md5FromInteger md5Int md5CheckGenericPackageDescription :: Proxy GenericPackageDescription -> Assertion md5CheckGenericPackageDescription proxy = md5Check proxy #if MIN_VERSION_base(4,19,0) - 0x4acd7857947385180d814f36dc1a759e + 0x4e7925b423973107ea2f615c3eb6e207 #else - 0x3ff3fa6c3c570bcafa10b457b1208cc8 + 0x5e28eb7641ac5fd9574068ed7743f58f #endif md5CheckLocalBuildInfo :: Proxy LocalBuildInfo -> Assertion md5CheckLocalBuildInfo proxy = md5Check proxy #if MIN_VERSION_base(4,19,0) - 0x5f774efdb0aedcbf5263d3d99e38d50b + 0x3f7451c297d58669475d5f2782f6c9b9 #else - 0x0f53d756836a410f72b31feb7d9f7b09 + 0x8e8d315d525d3ec36cfd4e0ba0095f1c #endif diff --git a/Cabal-tree-diff/src/Data/TreeDiff/Instances/Cabal.hs b/Cabal-tree-diff/src/Data/TreeDiff/Instances/Cabal.hs index 15fae62649e..863eaac1fb4 100644 --- a/Cabal-tree-diff/src/Data/TreeDiff/Instances/Cabal.hs +++ b/Cabal-tree-diff/src/Data/TreeDiff/Instances/Cabal.hs @@ -71,6 +71,8 @@ instance ToExpr CabalSpecVersion instance ToExpr CompilerFlavor instance ToExpr CompilerId instance ToExpr ComponentId +instance ToExpr ComponentName +instance ToExpr NotLibComponentName instance ToExpr DebugInfoLevel instance ToExpr DefUnitId instance ToExpr DumpBuildInfo @@ -127,5 +129,8 @@ instance ToExpr UnqualComponentName instance ToExpr Verbosity instance ToExpr VerbosityFlag instance ToExpr VerbosityLevel +instance ToExpr Dependencies +instance ToExpr PrivateDependency +instance ToExpr PrivateAlias instance ToExpr ShortText where toExpr = toExpr . fromShortText diff --git a/Cabal/src/Distribution/Backpack/ComponentsGraph.hs b/Cabal/src/Distribution/Backpack/ComponentsGraph.hs index aef3db817c6..0c7cb6a18ca 100644 --- a/Cabal/src/Distribution/Backpack/ComponentsGraph.hs +++ b/Cabal/src/Distribution/Backpack/ComponentsGraph.hs @@ -73,7 +73,7 @@ mkComponentsGraph enabled pkg_descr = toolDependencies = CExeName <$> getAllInternalToolDependencies pkg_descr bi libDependencies = do - Dependency pkgname _ lns <- targetBuildDepends bi + Dependency pkgname _ lns <- (targetBuildDepends bi ++ concatMap private_depends (targetPrivateBuildDepends bi)) guard (pkgname == packageName pkg_descr) ln <- NES.toList lns diff --git a/Cabal/src/Distribution/Backpack/Configure.hs b/Cabal/src/Distribution/Backpack/Configure.hs index 8e9eb18ae6a..43b75db0408 100644 --- a/Cabal/src/Distribution/Backpack/Configure.hs +++ b/Cabal/src/Distribution/Backpack/Configure.hs @@ -103,7 +103,7 @@ configureComponentLocalBuildInfos let conf_pkg_map = Map.fromListWith Map.union - [ ( pc_pkgname pkg + [ ( (pc_pkgname pkg, pc_alias pkg) , Map.singleton (pc_compname pkg) ( AnnotatedId @@ -117,8 +117,10 @@ configureComponentLocalBuildInfos ] `Map.union` Map.fromListWith Map.union - [ (pkg, Map.singleton (ann_cname aid) aid) - | PromisedComponent pkg aid <- promisedPkgDeps + [ ( (pkg, alias) + , Map.singleton (ann_cname aid) aid + ) + | PromisedComponent pkg aid alias <- promisedPkgDeps ] graph1 <- toConfiguredComponents @@ -151,7 +153,7 @@ configureComponentLocalBuildInfos , emptyModuleShape ) ) - | PromisedComponent _ aid <- promisedPkgDeps + | PromisedComponent _ aid _ <- promisedPkgDeps ] uid_lookup def_uid | Just pkg <- PackageIndex.lookupUnitId installedPackageSet uid = diff --git a/Cabal/src/Distribution/Backpack/ConfiguredComponent.hs b/Cabal/src/Distribution/Backpack/ConfiguredComponent.hs index 9bfaefb7e0b..a542bc98dcb 100644 --- a/Cabal/src/Distribution/Backpack/ConfiguredComponent.hs +++ b/Cabal/src/Distribution/Backpack/ConfiguredComponent.hs @@ -100,7 +100,7 @@ dispConfiguredComponent cc = mkConfiguredComponent :: PackageDescription -> ComponentId - -> [AnnotatedId ComponentId] -- lib deps + -> [(AnnotatedId ComponentId, Maybe PrivateAlias)] -- lib deps -> [AnnotatedId ComponentId] -- exe deps -> Component -> LogProgress ConfiguredComponent @@ -120,6 +120,8 @@ mkConfiguredComponent pkg_descr this_cid lib_deps exe_deps component = do { ci_ann_id = aid , ci_renaming = rns , ci_implicit = False + , -- Mixins can't be private + ci_alias = Nothing } -- Any @build-depends@ which is not explicitly mentioned in @@ -127,14 +129,15 @@ mkConfiguredComponent pkg_descr this_cid lib_deps exe_deps component = do let used_explicitly = Set.fromList (map ci_id explicit_includes) implicit_includes = map - ( \aid -> + ( \(aid, alias) -> ComponentInclude { ci_ann_id = aid , ci_renaming = defaultIncludeRenaming , ci_implicit = True + , ci_alias = alias } ) - $ filter (flip Set.notMember used_explicitly . ann_id) lib_deps + $ filter (flip Set.notMember used_explicitly . ann_id . fst) lib_deps return ConfiguredComponent @@ -161,13 +164,14 @@ mkConfiguredComponent pkg_descr this_cid lib_deps exe_deps component = do deps_map = Map.fromList [ ((packageName dep, ann_cname dep), dep) - | dep <- lib_deps + | (dep, _) <- lib_deps ] is_public = componentName component == CLibName LMainLibName +-- A function from PackageName -> Maybe PrivateQualifier -> ComponentName -> ResolvedComponentId type ConfiguredComponentMap = - Map PackageName (Map ComponentName (AnnotatedId ComponentId)) + Map (PackageName, Maybe PrivateAlias) (Map ComponentName ((AnnotatedId ComponentId))) toConfiguredComponent :: PackageDescription @@ -180,14 +184,16 @@ toConfiguredComponent pkg_descr this_cid lib_dep_map exe_dep_map component = do lib_deps <- if newPackageDepsBehaviour pkg_descr then fmap concat $ - forM (targetBuildDepends bi) $ - \(Dependency name _ sublibs) -> do - case Map.lookup name lib_dep_map of + forM ([(d, Nothing) | d <- targetBuildDepends bi] ++ [(d, Just alias) | (PrivateDependency alias ds) <- targetPrivateBuildDepends bi, d <- ds]) $ + \((Dependency name _ sublibs), alias) -> do + case Map.lookup (name, alias) lib_dep_map of Nothing -> dieProgress $ text "Dependency on unbuildable" <+> text "package" <+> pretty name + <+> maybe mempty pretty alias + <+> text (show lib_dep_map) Just pkg -> do -- Return all library components forM (NonEmptySet.toList sublibs) $ \lib -> @@ -199,7 +205,8 @@ toConfiguredComponent pkg_descr this_cid lib_dep_map exe_dep_map component = do <+> text (showLibraryName lib) <+> text "from" <+> pretty name - Just v -> return v + <+> maybe mempty pretty alias + Just v -> return (v, alias) else return old_style_lib_deps mkConfiguredComponent pkg_descr @@ -217,8 +224,8 @@ toConfiguredComponent pkg_descr this_cid lib_dep_map exe_dep_map component = do -- because it would imply a cyclic dependency for the -- library itself. old_style_lib_deps = - [ e - | (pn, comp_map) <- Map.toList lib_dep_map + [ (e, alias) + | ((pn, alias), comp_map) <- Map.toList lib_dep_map , pn /= packageName pkg_descr , (cn, e) <- Map.toList comp_map , cn == CLibName LMainLibName @@ -236,7 +243,7 @@ toConfiguredComponent pkg_descr this_cid lib_dep_map exe_dep_map component = do -- which the package is attempting to use (those deps are only -- fed in when cabal-install uses this codepath.) -- TODO: Let cabal-install request errors here - Just exe <- [Map.lookup (CExeName cn) =<< Map.lookup pn exe_dep_map] + Just exe <- [Map.lookup (CExeName cn) =<< Map.lookup (pn, Nothing) exe_dep_map] ] -- | Also computes the 'ComponentId', and sets cc_public if necessary. @@ -292,7 +299,7 @@ extendConfiguredComponentMap extendConfiguredComponentMap cc = Map.insertWith Map.union - (pkgName (cc_pkgid cc)) + ((pkgName (cc_pkgid cc)), Nothing) (Map.singleton (cc_name cc) (cc_ann_id cc)) -- Compute the 'ComponentId's for a graph of 'Component's. The diff --git a/Cabal/src/Distribution/Backpack/LinkedComponent.hs b/Cabal/src/Distribution/Backpack/LinkedComponent.hs index b2d2bc25066..98b2a1f8493 100644 --- a/Cabal/src/Distribution/Backpack/LinkedComponent.hs +++ b/Cabal/src/Distribution/Backpack/LinkedComponent.hs @@ -155,8 +155,8 @@ toLinkedComponent -- on the ModuleShape) to resolve these into linked identities. unlinked_includes :: [ComponentInclude (OpenUnitId, ModuleShape) IncludeRenaming] unlinked_includes = - [ ComponentInclude (fmap lookupUid dep_aid) rns i - | ComponentInclude dep_aid rns i <- cid_includes + [ ComponentInclude (fmap lookupUid dep_aid) rns i alias + | ComponentInclude dep_aid rns i alias <- cid_includes ] lookupUid :: ComponentId -> (OpenUnitId, ModuleShape) @@ -184,7 +184,7 @@ toLinkedComponent , preModShapeRequires = Set.fromList src_reqs } : [ renamePreModuleShape (toPreModuleShape sh) rns - | ComponentInclude (AnnotatedId{ann_id = (_, sh)}) rns _ <- unlinked_includes + | ComponentInclude (AnnotatedId{ann_id = (_, sh)}) rns _ _ <- unlinked_includes ] reqs = preModShapeRequires pre_shape insts = @@ -236,7 +236,7 @@ toLinkedComponent -- src_reqs_u <- traverse convertReq src_reqs -- Read out all the final results by converting back -- into a pure representation. - let convertIncludeU (ComponentInclude dep_aid rns i) = do + let convertIncludeU (ComponentInclude dep_aid rns i alias) = do let component_name = pretty $ ann_cname dep_aid uid <- convertUnitIdU (ann_id dep_aid) component_name return @@ -244,6 +244,7 @@ toLinkedComponent { ci_ann_id = dep_aid{ann_id = uid} , ci_renaming = rns , ci_implicit = i + , ci_alias = alias } ) diff --git a/Cabal/src/Distribution/Backpack/ModuleScope.hs b/Cabal/src/Distribution/Backpack/ModuleScope.hs index 5e18766a15d..40b68513149 100644 --- a/Cabal/src/Distribution/Backpack/ModuleScope.hs +++ b/Cabal/src/Distribution/Backpack/ModuleScope.hs @@ -70,6 +70,7 @@ data ModuleScope = ModuleScope { modScopeProvides :: ModuleProvides , modScopeRequires :: ModuleRequires } + deriving (Show) -- | An empty 'ModuleScope'. emptyModuleScope :: ModuleScope @@ -92,6 +93,7 @@ data ModuleSource | FromExposedModules ModuleName | FromOtherModules ModuleName | FromSignatures ModuleName + deriving (Show) -- We don't have line numbers, but if we did, we'd want to record that -- too @@ -123,7 +125,7 @@ dispComponent pn cn = -- | An 'OpenModule', annotated with where it came from in a Cabal file. data WithSource a = WithSource ModuleSource a - deriving (Functor, Foldable, Traversable) + deriving (Show, Functor, Foldable, Traversable) unWithSource :: WithSource a -> a unWithSource (WithSource _ x) = x diff --git a/Cabal/src/Distribution/Backpack/PreExistingComponent.hs b/Cabal/src/Distribution/Backpack/PreExistingComponent.hs index 5f937de9062..aeca962b299 100644 --- a/Cabal/src/Distribution/Backpack/PreExistingComponent.hs +++ b/Cabal/src/Distribution/Backpack/PreExistingComponent.hs @@ -27,6 +27,7 @@ import Distribution.Types.AnnotatedId data PromisedComponent = PromisedComponent { pr_pkgname :: PackageName , pr_cid :: AnnotatedId ComponentId + , pr_alias :: Maybe PrivateAlias } instance Package PromisedComponent where @@ -47,13 +48,14 @@ data PreExistingComponent = PreExistingComponent , pc_cid :: ComponentId , pc_open_uid :: OpenUnitId , pc_shape :: ModuleShape + , pc_alias :: Maybe PrivateAlias } -- | Convert an 'InstalledPackageInfo' into a 'PreExistingComponent', -- which was brought into scope under the 'PackageName' (important for -- a package qualified reference.) -ipiToPreExistingComponent :: InstalledPackageInfo -> PreExistingComponent -ipiToPreExistingComponent ipi = +ipiToPreExistingComponent :: Maybe PrivateAlias -> InstalledPackageInfo -> PreExistingComponent +ipiToPreExistingComponent alias ipi = PreExistingComponent { pc_pkgname = packageName ipi , pc_compname = CLibName $ Installed.sourceLibName ipi @@ -65,6 +67,7 @@ ipiToPreExistingComponent ipi = (Installed.installedComponentId ipi) (Map.fromList (Installed.instantiatedWith ipi)) , pc_shape = shapeInstalledPackage ipi + , pc_alias = alias } instance HasMungedPackageId PreExistingComponent where diff --git a/Cabal/src/Distribution/Backpack/UnifyM.hs b/Cabal/src/Distribution/Backpack/UnifyM.hs index 6e0f00d9f63..11c82b65751 100644 --- a/Cabal/src/Distribution/Backpack/UnifyM.hs +++ b/Cabal/src/Distribution/Backpack/UnifyM.hs @@ -481,6 +481,7 @@ convertInclude } , ci_renaming = incl@(IncludeRenaming prov_rns req_rns) , ci_implicit = implicit + , ci_alias = alias } ) = addErrContext (text "In" <+> ci_msg ci) $ do let pn = packageName pid @@ -619,12 +620,31 @@ convertInclude | (from, to) <- rns ] return (r, prov_rns) + + -- TODO: Test hiding and private depends to check that works + + -- Expand the alias + let prepend_alias mn = case alias of + Just (PrivateAlias alias_mn) -> combineModuleName alias_mn mn + Nothing -> mn + + let pre_prov_scope' = map (first prepend_alias) pre_prov_scope + + let prov_rns'' = + case prov_rns' of + DefaultRenaming -> case alias of + Nothing -> DefaultRenaming + Just{} -> ModuleRenaming (map ((\x -> (x, prepend_alias x)) . fst) (pre_prov_scope)) + ModuleRenaming rn -> ModuleRenaming (map (\(x, y) -> (x, prepend_alias y)) rn) + -- Can't happen, expanded above + HidingRenaming{} -> error "unreachable" + let prov_scope = modSubst req_subst $ Map.fromListWith (++) [ (k, [source v]) - | (k, v) <- pre_prov_scope + | (k, v) <- pre_prov_scope' ] provs_u <- convertModuleProvides prov_scope @@ -646,8 +666,9 @@ convertInclude , ann_pid = pid , ann_cname = compname } - , ci_renaming = prov_rns' + , ci_renaming = prov_rns'' , ci_implicit = ci_implicit ci + , ci_alias = alias } ) ) diff --git a/Cabal/src/Distribution/PackageDescription/Check.hs b/Cabal/src/Distribution/PackageDescription/Check.hs index ef97b0d23be..79123f7f9df 100644 --- a/Cabal/src/Distribution/PackageDescription/Check.hs +++ b/Cabal/src/Distribution/PackageDescription/Check.hs @@ -909,14 +909,15 @@ wrapParseWarning fp pw = PackageDistSuspicious (ParseWarning fp pw) -- each of those branch will be checked one by one. extractAssocDeps :: UnqualComponentName -- Name of the target library - -> CondTree ConfVar [Dependency] Library + -> CondTree ConfVar Dependencies Library -> AssocDep extractAssocDeps n ct = let a = ignoreConditions ct in -- Merging is fine here, remember the specific -- library dependencies will be checked branch -- by branch. - (n, snd a) + -- MP: TOOD: WRONG + (n, publicDependencies (snd a)) -- | August 2022: this function is an oddity due to the historical -- GenericPackageDescription/PackageDescription split (check @@ -952,8 +953,8 @@ pd2gpd pd = gpd } -- From target to simple, unconditional CondTree. - t2c :: a -> CondTree ConfVar [Dependency] a - t2c a = CondNode a [] [] + t2c :: a -> CondTree ConfVar Dependencies a + t2c a = CondNode a mempty [] -- From named target to unconditional CondTree. Notice we have -- a function to extract the name *and* a function to modify @@ -963,7 +964,7 @@ pd2gpd pd = gpd :: (a -> UnqualComponentName) -> (a -> a) -> a - -> (UnqualComponentName, CondTree ConfVar [Dependency] a) + -> (UnqualComponentName, CondTree ConfVar Dependencies a) t2cName nf mf a = (nf a, t2c . mf $ a) ln :: Library -> UnqualComponentName diff --git a/Cabal/src/Distribution/PackageDescription/Check/Conditional.hs b/Cabal/src/Distribution/PackageDescription/Check/Conditional.hs index da05b2c80b9..60ffd13477a 100644 --- a/Cabal/src/Distribution/PackageDescription/Check/Conditional.hs +++ b/Cabal/src/Distribution/PackageDescription/Check/Conditional.hs @@ -61,8 +61,8 @@ annotateCondTree . (Eq a, Monoid a) => [PackageFlag] -- User flags. -> TargetAnnotation a - -> CondTree ConfVar [Dependency] a - -> CondTree ConfVar [Dependency] (TargetAnnotation a) + -> CondTree ConfVar Dependencies a + -> CondTree ConfVar Dependencies (TargetAnnotation a) annotateCondTree fs ta (CondNode a c bs) = let ta' = updateTargetAnnotation a ta bs' = map (annotateBranch ta') bs @@ -71,10 +71,10 @@ annotateCondTree fs ta (CondNode a c bs) = where annotateBranch :: TargetAnnotation a - -> CondBranch ConfVar [Dependency] a + -> CondBranch ConfVar Dependencies a -> CondBranch ConfVar - [Dependency] + Dependencies (TargetAnnotation a) annotateBranch wta (CondBranch k t mf) = let uf = isPkgFlagCond k @@ -117,13 +117,13 @@ crossAnnotateBranches :: forall a . (Eq a, Monoid a) => [PackageFlag] -- `default: true` flags. - -> [CondBranch ConfVar [Dependency] (TargetAnnotation a)] - -> [CondBranch ConfVar [Dependency] (TargetAnnotation a)] + -> [CondBranch ConfVar Dependencies (TargetAnnotation a)] + -> [CondBranch ConfVar Dependencies (TargetAnnotation a)] crossAnnotateBranches fs bs = map crossAnnBranch bs where crossAnnBranch - :: CondBranch ConfVar [Dependency] (TargetAnnotation a) - -> CondBranch ConfVar [Dependency] (TargetAnnotation a) + :: CondBranch ConfVar Dependencies (TargetAnnotation a) + -> CondBranch ConfVar Dependencies (TargetAnnotation a) crossAnnBranch wr = let rs = filter (/= wr) bs @@ -131,7 +131,7 @@ crossAnnotateBranches fs bs = map crossAnnBranch bs in updateTargetAnnBranch (mconcat ts) wr - realiseBranch :: CondBranch ConfVar [Dependency] (TargetAnnotation a) -> Maybe a + realiseBranch :: CondBranch ConfVar Dependencies (TargetAnnotation a) -> Maybe a realiseBranch b = let -- We are only interested in True by default package flags. @@ -144,8 +144,8 @@ crossAnnotateBranches fs bs = map crossAnnBranch bs updateTargetAnnBranch :: a - -> CondBranch ConfVar [Dependency] (TargetAnnotation a) - -> CondBranch ConfVar [Dependency] (TargetAnnotation a) + -> CondBranch ConfVar Dependencies (TargetAnnotation a) + -> CondBranch ConfVar Dependencies (TargetAnnotation a) updateTargetAnnBranch a (CondBranch k t mt) = let updateTargetAnnTree (CondNode ka c wbs) = (CondNode (updateTargetAnnotation a ka) c wbs) @@ -163,7 +163,7 @@ checkCondTarget -- Naming function (some targets -- need to have their name -- spoonfed to them. - -> (UnqualComponentName, CondTree ConfVar [Dependency] a) + -> (UnqualComponentName, CondTree ConfVar Dependencies a) -- Target name/condtree. -> CheckM m () checkCondTarget fs cf nf (unqualName, ct) = @@ -172,7 +172,7 @@ checkCondTarget fs cf nf (unqualName, ct) = -- Walking the tree. Remember that CondTree is not a binary -- tree but a /rose/tree. wTree - :: CondTree ConfVar [Dependency] (TargetAnnotation a) + :: CondTree ConfVar Dependencies (TargetAnnotation a) -> CheckM m () wTree (CondNode ta _ bs) -- There are no branches ([] == True) *or* every branch @@ -190,13 +190,13 @@ checkCondTarget fs cf nf (unqualName, ct) = mapM_ wBranch bs isSimple - :: CondBranch ConfVar [Dependency] (TargetAnnotation a) + :: CondBranch ConfVar Dependencies (TargetAnnotation a) -> Bool isSimple (CondBranch _ _ Nothing) = True isSimple (CondBranch _ _ (Just _)) = False wBranch - :: CondBranch ConfVar [Dependency] (TargetAnnotation a) + :: CondBranch ConfVar Dependencies (TargetAnnotation a) -> CheckM m () wBranch (CondBranch k t mf) = do checkCondVars k diff --git a/Cabal/src/Distribution/Simple/Configure.hs b/Cabal/src/Distribution/Simple/Configure.hs index 3dfe0b7e0be..c927c8974e4 100644 --- a/Cabal/src/Distribution/Simple/Configure.hs +++ b/Cabal/src/Distribution/Simple/Configure.hs @@ -6,6 +6,7 @@ {-# LANGUAGE RankNTypes #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE TupleSections #-} ----------------------------------------------------------------------------- @@ -818,9 +819,9 @@ computeLocalBuildConfig cfg comp programDb = do data PackageInfo = PackageInfo { internalPackageSet :: Set LibraryName - , promisedDepsSet :: Map (PackageName, ComponentName) ComponentId + , promisedDepsSet :: Map (PackageName, ComponentName, Maybe PrivateAlias) ComponentId , installedPackageSet :: InstalledPackageIndex - , requiredDepsMap :: Map (PackageName, ComponentName) InstalledPackageInfo + , requiredDepsMap :: Map (PackageName, ComponentName, Maybe PrivateAlias) InstalledPackageInfo } configurePackage @@ -973,12 +974,12 @@ finalizeAndConfigurePackage cfg lbc0 g_pkg_descr comp platform enabled = do -- NB: The fact that we bundle all the constraints together means -- that is not possible to configure a test-suite to use one -- version of a dependency, and the executable to use another. - ( allConstraints :: [PackageVersionConstraint] - , requiredDepsMap :: Map (PackageName, ComponentName) InstalledPackageInfo + ( allConstraints :: [(IsPrivate, PackageVersionConstraint)] + , requiredDepsMap :: Map (PackageName, ComponentName, Maybe PrivateAlias) InstalledPackageInfo ) <- either (dieWithException verbosity) return $ combinedConstraints - (configConstraints cfg) + (map (Public,) $ configConstraints cfg) -- configConstraints are per package and can't specify private aliases (configDependencies cfg) installedPackageSet @@ -1354,8 +1355,8 @@ configureComponents return lbi -mkPromisedDepsSet :: [GivenComponent] -> Map (PackageName, ComponentName) ComponentId -mkPromisedDepsSet comps = Map.fromList [((pn, CLibName ln), cid) | GivenComponent pn ln cid <- comps] +mkPromisedDepsSet :: [GivenComponent] -> Map (PackageName, ComponentName, Maybe PrivateAlias) ComponentId +mkPromisedDepsSet comps = Map.fromList [((pn, CLibName ln, alias), cid) | GivenComponent pn ln cid alias <- comps] -- | Adds the extra program paths from the flags provided to @configure@ as -- well as specified locations for certain known programs and their default @@ -1458,10 +1459,10 @@ dependencySatisfiable -- ^ installed set -> Set LibraryName -- ^ library components - -> Map (PackageName, ComponentName) ComponentId - -> Map (PackageName, ComponentName) InstalledPackageInfo + -> Map (PackageName, ComponentName, Maybe PrivateAlias) ComponentId + -> Map (PackageName, ComponentName, Maybe PrivateAlias) InstalledPackageInfo -- ^ required dependencies - -> (Dependency -> Bool) + -> (Maybe PrivateAlias -> Dependency -> Bool) dependencySatisfiable use_external_internal_deps exact_config @@ -1471,6 +1472,7 @@ dependencySatisfiable packageLibraries promisedDeps requiredDepsMap + alias (Dependency depName vr sublibs) | exact_config = -- When we're given '--exact-configuration', we assume that all @@ -1493,6 +1495,7 @@ dependencySatisfiable , CLibName $ LSubLibName $ packageNameToUnqualComponentName depName + , alias ) requiredDepsMap ) @@ -1542,8 +1545,8 @@ dependencySatisfiable -- Don't check if it's visible, we promise to build it before we need it. || promised where - maybeIPI = Map.lookup (depName, CLibName lib) requiredDepsMap - promised = isJust $ Map.lookup (depName, CLibName lib) promisedDeps + maybeIPI = Map.lookup (depName, CLibName lib, alias) requiredDepsMap + promised = isJust $ Map.lookup (depName, CLibName lib, alias) promisedDeps -- | Finalize a generic package description. -- @@ -1552,8 +1555,8 @@ configureFinalizedPackage :: Verbosity -> ConfigFlags -> ComponentRequestedSpec - -> [PackageVersionConstraint] - -> (Dependency -> Bool) + -> [(IsPrivate, PackageVersionConstraint)] + -> (Maybe PrivateAlias -> Dependency -> Bool) -- ^ tests if a dependency is satisfiable. -- Might say it's satisfiable even when not. -> Compiler @@ -1620,10 +1623,10 @@ configureDependencies :: Verbosity -> UseExternalInternalDeps -> Set LibraryName - -> Map (PackageName, ComponentName) ComponentId + -> Map (PackageName, ComponentName, Maybe PrivateAlias) ComponentId -> InstalledPackageIndex -- ^ installed packages - -> Map (PackageName, ComponentName) InstalledPackageInfo + -> Map (PackageName, ComponentName, Maybe PrivateAlias) InstalledPackageInfo -- ^ required deps -> PackageDescription -> ComponentRequestedSpec @@ -1643,7 +1646,7 @@ configureDependencies partitionEithers $ concat [ fmap (\s -> (dep, s)) <$> status - | dep <- enabledBuildDepends pkg_descr enableSpec + | (alias, dep) <- enabledBuildDepends pkg_descr enableSpec , let status = selectDependency (package pkg_descr) @@ -1652,6 +1655,7 @@ configureDependencies installedPackageSet requiredDepsMap use_external_internal_deps + alias dep ] @@ -1874,16 +1878,17 @@ selectDependency -- ^ Package id of current package -> Set LibraryName -- ^ package libraries - -> Map (PackageName, ComponentName) ComponentId + -> Map (PackageName, ComponentName, Maybe PrivateAlias) ComponentId -- ^ Set of components that are promised, i.e. are not installed already. See 'PromisedDependency' for more details. -> InstalledPackageIndex -- ^ Installed packages - -> Map (PackageName, ComponentName) InstalledPackageInfo + -> Map (PackageName, ComponentName, Maybe PrivateAlias) InstalledPackageInfo -- ^ Packages for which we have been given specific deps to -- use -> UseExternalInternalDeps -- ^ Are we configuring a -- single component? + -> Maybe PrivateAlias -> Dependency -> [Either FailedDependency DependencyResolution] selectDependency @@ -1893,6 +1898,7 @@ selectDependency installedIndex requiredDepsMap use_external_internal_deps + alias (Dependency dep_pkgname vr libs) = -- If the dependency specification matches anything in the internal package -- index, then we prefer that match to anything in the second. @@ -1926,31 +1932,31 @@ selectDependency -- We have to look it up externally do_external_external :: LibraryName -> Either FailedDependency DependencyResolution do_external_external lib - | Just cid <- Map.lookup (dep_pkgname, CLibName lib) promisedIndex = - return $ PromisedDependency (PromisedComponent dep_pkgname (AnnotatedId currentCabalId (CLibName lib) cid)) + | Just cid <- Map.lookup (dep_pkgname, CLibName lib, alias) promisedIndex = + return $ PromisedDependency (PromisedComponent dep_pkgname (AnnotatedId currentCabalId (CLibName lib) cid) alias) do_external_external lib = do - ipi <- case Map.lookup (dep_pkgname, CLibName lib) requiredDepsMap of + ipi <- case Map.lookup (dep_pkgname, CLibName lib, alias) requiredDepsMap of -- If we know the exact pkg to use, then use it. Just pkginstance -> Right pkginstance -- Otherwise we just pick an arbitrary instance of the latest version. Nothing -> case pickLastIPI $ PackageIndex.lookupInternalDependency installedIndex dep_pkgname vr lib of Nothing -> Left (DependencyNotExists dep_pkgname) Just pkg -> Right pkg - return $ ExternalDependency $ ipiToPreExistingComponent ipi + return $ ExternalDependency $ ipiToPreExistingComponent alias ipi do_external_internal :: LibraryName -> Either FailedDependency DependencyResolution do_external_internal lib - | Just cid <- Map.lookup (dep_pkgname, CLibName lib) promisedIndex = - return $ PromisedDependency (PromisedComponent dep_pkgname (AnnotatedId currentCabalId (CLibName lib) cid)) + | Just cid <- Map.lookup (dep_pkgname, CLibName lib, alias) promisedIndex = + return $ PromisedDependency (PromisedComponent dep_pkgname (AnnotatedId currentCabalId (CLibName lib) cid) alias) do_external_internal lib = do - ipi <- case Map.lookup (dep_pkgname, CLibName lib) requiredDepsMap of + ipi <- case Map.lookup (dep_pkgname, CLibName lib, alias) requiredDepsMap of -- If we know the exact pkg to use, then use it. Just pkginstance -> Right pkginstance Nothing -> case pickLastIPI $ PackageIndex.lookupInternalDependency installedIndex pn vr lib of -- It's an internal library, being looked up externally Nothing -> Left (DependencyMissingInternal dep_pkgname lib) Just pkg -> Right pkg - return $ ExternalDependency $ ipiToPreExistingComponent ipi + return $ ExternalDependency $ ipiToPreExistingComponent alias ipi pickLastIPI :: [(Version, [InstalledPackageInfo])] -> Maybe InstalledPackageInfo pickLastIPI pkgs = safeHead . snd . last =<< nonEmpty pkgs @@ -2116,14 +2122,14 @@ interpretPackageDbFlags userInstall specificDBs = -- deps in the end. So we still need to remember which installed packages to -- pick. combinedConstraints - :: [PackageVersionConstraint] + :: [(IsPrivate, PackageVersionConstraint)] -> [GivenComponent] -- ^ installed dependencies -> InstalledPackageIndex -> Either CabalException - ( [PackageVersionConstraint] - , Map (PackageName, ComponentName) InstalledPackageInfo + ( [(IsPrivate, PackageVersionConstraint)] + , Map (PackageName, ComponentName, Maybe PrivateAlias) InstalledPackageInfo ) combinedConstraints constraints dependencies installedPackages = do when (not (null badComponentIds)) $ @@ -2134,27 +2140,27 @@ combinedConstraints constraints dependencies installedPackages = do return (allConstraints, idConstraintMap) where - allConstraints :: [PackageVersionConstraint] + allConstraints :: [(IsPrivate, PackageVersionConstraint)] allConstraints = constraints - ++ [ thisPackageVersionConstraint (packageId pkg) - | (_, _, _, Just pkg) <- dependenciesPkgInfo + ++ [ (case mAlias of Nothing -> Public; Just a -> Private a, thisPackageVersionConstraint (packageId pkg)) + | (_, _, mAlias, _, Just pkg) <- dependenciesPkgInfo ] - idConstraintMap :: Map (PackageName, ComponentName) InstalledPackageInfo + idConstraintMap :: Map (PackageName, ComponentName, Maybe PrivateAlias) InstalledPackageInfo idConstraintMap = Map.fromList -- NB: do NOT use the packageName from -- dependenciesPkgInfo! - [ ((pn, cname), pkg) - | (pn, cname, _, Just pkg) <- dependenciesPkgInfo + [ ((pn, cname, alias), pkg) + | (pn, cname, alias, _, Just pkg) <- dependenciesPkgInfo ] -- The dependencies along with the installed package info, if it exists - dependenciesPkgInfo :: [(PackageName, ComponentName, ComponentId, Maybe InstalledPackageInfo)] + dependenciesPkgInfo :: [(PackageName, ComponentName, Maybe PrivateAlias, ComponentId, Maybe InstalledPackageInfo)] dependenciesPkgInfo = - [ (pkgname, CLibName lname, cid, mpkg) - | GivenComponent pkgname lname cid <- dependencies + [ (pkgname, CLibName lname, alias, cid, mpkg) + | GivenComponent pkgname lname cid alias <- dependencies , let mpkg = PackageIndex.lookupComponentId installedPackages @@ -2165,8 +2171,8 @@ combinedConstraints constraints dependencies installedPackages = do -- (i.e. someone has written a hash) and didn't find it then it's -- an error. badComponentIds = - [ (pkgname, cname, cid) - | (pkgname, cname, cid, Nothing) <- dependenciesPkgInfo + [ (pkgname, cname, alias, cid) + | (pkgname, cname, alias, cid, Nothing) <- dependenciesPkgInfo ] dispDependencies deps = @@ -2180,8 +2186,9 @@ combinedConstraints constraints dependencies installedPackages = do _ -> ":" <<>> pretty cname <<>> char '=' <<>> pretty cid + <<>> maybe "" (\a -> "=" <<>> pretty a) alias ) - | (pkgname, cname, cid) <- deps + | (pkgname, cname, alias, cid) <- deps ] -- ----------------------------------------------------------------------------- diff --git a/Cabal/src/Distribution/Simple/Errors.hs b/Cabal/src/Distribution/Simple/Errors.hs index 45029565e99..23602c92f64 100644 --- a/Cabal/src/Distribution/Simple/Errors.hs +++ b/Cabal/src/Distribution/Simple/Errors.hs @@ -125,7 +125,7 @@ data CabalException | CantFindForeignLibraries [String] | ExpectedAbsoluteDirectory FilePath | FlagsNotSpecified [FlagName] - | EncounteredMissingDependency [Dependency] + | EncounteredMissingDependency Dependencies | CompilerDoesn'tSupportThinning | CompilerDoesn'tSupportReexports | CompilerDoesn'tSupportBackpack @@ -553,8 +553,11 @@ exceptionMessage e = case e of . sep . punctuate comma . map (pretty . simplifyDependency) + . allDependencies $ missing ) + where + allDependencies (Dependencies pub priv) = pub ++ concatMap private_depends priv CompilerDoesn'tSupportThinning -> "Your compiler does not support thinning and renaming on " ++ "package flags. To use this feature you must use " diff --git a/Cabal/src/Distribution/Simple/GHC/Internal.hs b/Cabal/src/Distribution/Simple/GHC/Internal.hs index a4b75cdb6d3..108bba30250 100644 --- a/Cabal/src/Distribution/Simple/GHC/Internal.hs +++ b/Cabal/src/Distribution/Simple/GHC/Internal.hs @@ -672,7 +672,7 @@ getHaskellObjects _implInfo lib lbi clbi pref wanted_obj_ext allow_split_objs -- and is a hack to avoid passing bogus `-package` arguments to GHC. The assumption being that -- in 99% of cases we will include the right `-package` so that the C file finds the right headers. mkGhcOptPackages - :: Map (PackageName, ComponentName) ComponentId + :: Map (PackageName, ComponentName, Maybe PrivateAlias) ComponentId -> ComponentLocalBuildInfo -> [(OpenUnitId, ModuleRenaming)] mkGhcOptPackages promisedPkgsMap clbi = diff --git a/Cabal/src/Distribution/Simple/Setup/Config.hs b/Cabal/src/Distribution/Simple/Setup/Config.hs index 14e76c7d769..3e75880946e 100644 --- a/Cabal/src/Distribution/Simple/Setup/Config.hs +++ b/Cabal/src/Distribution/Simple/Setup/Config.hs @@ -756,7 +756,7 @@ configureOptions showOrParseArgs = configDependencies (\v flags -> flags{configDependencies = v}) ( reqArg - "NAME[:COMPONENT_NAME]=CID" + "NAME[:COMPONENT_NAME]=CID[=ALIAS]" (parsecToReadE (const "dependency expected") ((\x -> [x]) `fmap` parsecGivenComponent)) (map prettyGivenComponent) ) @@ -767,7 +767,7 @@ configureOptions showOrParseArgs = configPromisedDependencies (\v flags -> flags{configPromisedDependencies = v}) ( reqArg - "NAME[:COMPONENT_NAME]=CID" + "NAME[:COMPONENT_NAME]=CID[=ALIAS]" (parsecToReadE (const "dependency expected") ((\x -> [x]) `fmap` parsecGivenComponent)) (map prettyGivenComponent) ) @@ -910,16 +910,20 @@ parsecGivenComponent = do else LSubLibName ucn _ <- P.char '=' cid <- parsec - return $ GivenComponent pn ln cid + alias <- P.option Nothing $ do + _ <- P.char '=' + Just <$> parsec + return $ GivenComponent pn ln cid alias prettyGivenComponent :: GivenComponent -> String -prettyGivenComponent (GivenComponent pn cn cid) = +prettyGivenComponent (GivenComponent pn cn cid alias) = prettyShow pn ++ case cn of LMainLibName -> "" LSubLibName n -> ":" ++ prettyShow n ++ "=" ++ prettyShow cid + ++ maybe "" (\a -> "=" ++ prettyShow a) alias installDirsOptions :: [OptionField (InstallDirs (Flag PathTemplate))] installDirsOptions = diff --git a/Cabal/src/Distribution/Types/ComponentInclude.hs b/Cabal/src/Distribution/Types/ComponentInclude.hs index 6999b6544d7..e2e4057a042 100644 --- a/Cabal/src/Distribution/Types/ComponentInclude.hs +++ b/Cabal/src/Distribution/Types/ComponentInclude.hs @@ -7,6 +7,7 @@ module Distribution.Types.ComponentInclude import Distribution.Types.AnnotatedId import Distribution.Types.ComponentName +import Distribution.Types.Dependency (PrivateAlias) import Distribution.Types.PackageId -- Once ci_id is refined to an 'OpenUnitId' or 'DefUnitId', @@ -19,7 +20,9 @@ data ComponentInclude id rn = ComponentInclude , ci_implicit :: Bool -- ^ Did this come from an entry in @mixins@, or -- was implicitly generated by @build-depends@? + , ci_alias :: Maybe PrivateAlias } + deriving (Show) ci_id :: ComponentInclude id rn -> id ci_id = ann_id . ci_ann_id diff --git a/Cabal/src/Distribution/Types/GivenComponent.hs b/Cabal/src/Distribution/Types/GivenComponent.hs index c8314311d89..eaab3e8e713 100644 --- a/Cabal/src/Distribution/Types/GivenComponent.hs +++ b/Cabal/src/Distribution/Types/GivenComponent.hs @@ -8,6 +8,7 @@ module Distribution.Types.GivenComponent import Distribution.Compat.Prelude import Distribution.Types.ComponentId +import Distribution.Types.Dependency import Distribution.Types.LibraryName import Distribution.Types.PackageName @@ -22,6 +23,7 @@ data GivenComponent = GivenComponent , givenComponentName :: LibraryName -- --dependency is for libraries -- only, not for any component , givenComponentId :: ComponentId + , givenComponentAlias :: Maybe PrivateAlias } deriving (Generic, Read, Show, Eq, Typeable) diff --git a/Cabal/src/Distribution/Types/LocalBuildConfig.hs b/Cabal/src/Distribution/Types/LocalBuildConfig.hs index 9126d92f1eb..4fd700d83e4 100644 --- a/Cabal/src/Distribution/Types/LocalBuildConfig.hs +++ b/Cabal/src/Distribution/Types/LocalBuildConfig.hs @@ -101,7 +101,7 @@ data ComponentBuildDescr = ComponentBuildDescr -- ^ A map from component name to all matching -- components. These coincide with 'componentGraph' -- There may be more than one matching component because of backpack instantiations - , promisedPkgs :: Map (PackageName, ComponentName) ComponentId + , promisedPkgs :: Map (PackageName, ComponentName, Maybe PrivateAlias) ComponentId -- ^ The packages we were promised, but aren't already installed. -- MP: Perhaps this just needs to be a Set UnitId at this stage. , installedPkgs :: InstalledPackageIndex diff --git a/Cabal/src/Distribution/Types/LocalBuildInfo.hs b/Cabal/src/Distribution/Types/LocalBuildInfo.hs index a5706fff09a..e0e3d58da79 100644 --- a/Cabal/src/Distribution/Types/LocalBuildInfo.hs +++ b/Cabal/src/Distribution/Types/LocalBuildInfo.hs @@ -156,7 +156,7 @@ pattern LocalBuildInfo -> Maybe (SymbolicPath Pkg File) -> Graph ComponentLocalBuildInfo -> Map ComponentName [ComponentLocalBuildInfo] - -> Map (PackageName, ComponentName) ComponentId + -> Map (PackageName, ComponentName, Maybe PrivateAlias) ComponentId -> InstalledPackageIndex -> PackageDescription -> ProgramDb diff --git a/cabal-install-solver/cabal-install-solver.cabal b/cabal-install-solver/cabal-install-solver.cabal index a531ef12635..151f46fa09a 100644 --- a/cabal-install-solver/cabal-install-solver.cabal +++ b/cabal-install-solver/cabal-install-solver.cabal @@ -66,6 +66,7 @@ library Distribution.Solver.Modular.MessageUtils Distribution.Solver.Modular.Package Distribution.Solver.Modular.Preference + Distribution.Solver.Modular.PrivateScopeClosure Distribution.Solver.Modular.PSQ Distribution.Solver.Modular.RetryLog Distribution.Solver.Modular.Solver diff --git a/cabal-install-solver/src/Distribution/Solver/Modular/Builder.hs b/cabal-install-solver/src/Distribution/Solver/Modular/Builder.hs index 5d196f4fd9f..95373cbd473 100644 --- a/cabal-install-solver/src/Distribution/Solver/Modular/Builder.hs +++ b/cabal-install-solver/src/Distribution/Solver/Modular/Builder.hs @@ -73,7 +73,7 @@ extendOpen qpn' gs s@(BS { rdeps = gs', open = o' }) = go gs' o' gs -- the later addition will have better dependency information. go g o ((Stanza sn@(SN qpn _) t) : ngs) = go g (StanzaGoal sn t (flagGR qpn) : o) ngs - go g o ((Simple (LDep dr (Dep (PkgComponent qpn _) _)) c) : ngs) + go g o ((Simple (LDep dr (Dep (PkgComponent qpn _) _is_private _)) c) : ngs) | qpn == qpn' = -- We currently only add a self-dependency to the graph if it is -- between a package and its setup script. The edge creates a cycle @@ -100,12 +100,12 @@ extendOpen qpn' gs s@(BS { rdeps = gs', open = o' }) = go gs' o' gs -- | Given the current scope, qualify all the package names in the given set of -- dependencies and then extend the set of open goals accordingly. -scopedExtendOpen :: QPN -> FlaggedDeps PN -> FlagInfo -> +scopedExtendOpen :: RevDepMap -> QPN -> FlaggedDeps PN -> FlagInfo -> BuildState -> BuildState -scopedExtendOpen qpn fdeps fdefs s = extendOpen qpn gs s +scopedExtendOpen rdm qpn fdeps fdefs s = extendOpen qpn gs s where -- Qualify all package names - qfdeps = qualifyDeps (qualifyOptions s) qpn fdeps + qfdeps = qualifyDeps (qualifyOptions s) rdm qpn fdeps -- Introduce all package flags qfdefs = L.map (\ (fn, b) -> Flagged (FN qpn fn) b [] []) $ M.toList fdefs -- Combine new package and flag goals @@ -179,8 +179,8 @@ addChildren bs@(BS { rdeps = rdm, next = OneGoal (StanzaGoal qsn@(SN qpn _) t gr -- and furthermore we update the set of goals. -- -- TODO: We could inline this above. -addChildren bs@(BS { next = Instance qpn (PInfo fdeps _ fdefs _) }) = - addChildren ((scopedExtendOpen qpn fdeps fdefs bs) +addChildren bs@(BS { rdeps = rdm, next = Instance qpn (PInfo fdeps _ fdefs _) }) = + addChildren ((scopedExtendOpen rdm qpn fdeps fdefs bs) { next = Goals }) {------------------------------------------------------------------------------- @@ -263,7 +263,7 @@ buildTree idx (IndependentGoals ind) igs = topLevelGoal qpn = PkgGoal qpn UserGoal qpns | ind = L.map makeIndependent igs - | otherwise = L.map (Q (PackagePath DefaultNamespace QualToplevel)) igs + | otherwise = L.map (Q (PackagePath DefaultNamespace QualToplevel) ) igs {------------------------------------------------------------------------------- Goals diff --git a/cabal-install-solver/src/Distribution/Solver/Modular/ConfiguredConversion.hs b/cabal-install-solver/src/Distribution/Solver/Modular/ConfiguredConversion.hs index 0e2e8ad5baa..86928083faf 100644 --- a/cabal-install-solver/src/Distribution/Solver/Modular/ConfiguredConversion.hs +++ b/cabal-install-solver/src/Distribution/Solver/Modular/ConfiguredConversion.hs @@ -4,9 +4,8 @@ module Distribution.Solver.Modular.ConfiguredConversion import Data.Maybe import Prelude hiding (pi) -import Data.Either (partitionEithers) -import Distribution.Package (UnitId, packageId) +import Distribution.Package (UnitId) import qualified Distribution.Simple.PackageIndex as SI @@ -21,6 +20,7 @@ import Distribution.Solver.Types.SolverId import Distribution.Solver.Types.SolverPackage import Distribution.Solver.Types.InstSolverPackage import Distribution.Solver.Types.SourcePackage +import Distribution.Types.Dependency (PrivateAlias) -- | Converts from the solver specific result @CP QPN@ into -- a 'ResolverPackage', which can then be converted into @@ -33,40 +33,69 @@ convCP iidx sidx (CP qpi fa es ds) = Left pi -> PreExisting $ InstSolverPackage { instSolverPkgIPI = fromJust $ SI.lookupUnitId iidx pi, - instSolverPkgLibDeps = fmap fst ds', - instSolverPkgExeDeps = fmap snd ds' + instSolverPkgLibDeps = fmap fst (ds' Nothing), + instSolverPkgExeDeps = fmap snd (ds' Nothing) } Right pi -> Configured $ - SolverPackage { + let libAndExeDeps = ds' (Just (pkgName pi)) + in SolverPackage { solverPkgSource = srcpkg, solverPkgFlags = fa, solverPkgStanzas = es, - solverPkgLibDeps = fmap fst ds', - solverPkgExeDeps = fmap snd ds' + solverPkgLibDeps = fmap fst libAndExeDeps, + solverPkgExeDeps = fmap snd libAndExeDeps } where srcpkg = fromMaybe (error "convCP: lookupPackageId failed") $ CI.lookupPackageId sidx pi where - ds' :: ComponentDeps ([SolverId] {- lib -}, [SolverId] {- exe -}) - ds' = fmap (partitionEithers . map convConfId) ds + + ds' :: Maybe PackageName -> ComponentDeps (([(SolverId, Maybe PrivateAlias)] {- lib -}, [SolverId] {- exe -})) + ds' pn = fmap (partitionDeps . map (convConfId pn)) ds + +partitionDeps :: [Converted] -> (([(SolverId, Maybe PrivateAlias)], [SolverId])) +partitionDeps [] = ([], []) +partitionDeps (dep:deps) = + let (p, e) = partitionDeps deps + in case dep of + AliasPkg sid pn -> ((sid, Just pn) : p, e) + NormalPkg sid -> ((sid, Nothing) :p, e) + NormalExe sid -> (p, sid:e) convPI :: PI QPN -> Either UnitId PackageId convPI (PI _ (I _ (Inst pi))) = Left pi -convPI pi = Right (packageId (either id id (convConfId pi))) +convPI (PI (Q _ pn) (I v _)) = Right (PackageIdentifier pn v) + +data Converted = NormalPkg SolverId | NormalExe SolverId | AliasPkg SolverId PrivateAlias + deriving Show -convConfId :: PI QPN -> Either SolverId {- is lib -} SolverId {- is exe -} -convConfId (PI (Q (PackagePath _ q) pn) (I v loc)) = +convConfId :: Maybe PackageName -> PI QPN -> Converted +convConfId parent (PI (Q (PackagePath ns qn) pn) (I v loc)) = case loc of - Inst pi -> Left (PreExistingId sourceId pi) + Inst pi + -- As below, we need to identify where `AliasPkg` applies. This is + -- needed to qualify `solverPkgLibDeps` since we may have multiple + -- instances of the same package qualified. + | QualAlias pn' _ alias <- qn + , parent == Just pn' -> AliasPkg (PreExistingId sourceId pi) alias + + | otherwise + -> NormalPkg (PreExistingId sourceId pi) _otherwise - | QualExe _ pn' <- q + -- Same reasoning as for exes, the "top" qualified goal is the one + -- which is private and needs to be aliased, but there might be other goals underneath which + -- are solved in the same scope (but are not private) + | QualAlias pn' _ alias <- qn + , parent == Just pn' -> AliasPkg (PlannedId sourceId) alias + + | IndependentBuildTool _ pn' <- ns -- NB: the dependencies of the executable are also -- qualified. So the way to tell if this is an executable -- dependency is to make sure the qualifier is pointing -- at the actual thing. Fortunately for us, I was -- silly and didn't allow arbitrarily nested build-tools -- dependencies, so a shallow check works. - , pn == pn' -> Right (PlannedId sourceId) - | otherwise -> Left (PlannedId sourceId) + , pn == pn' -> NormalExe (PlannedId sourceId) + + | otherwise -> NormalPkg (PlannedId sourceId) where sourceId = PackageIdentifier pn v diff --git a/cabal-install-solver/src/Distribution/Solver/Modular/ConflictSet.hs b/cabal-install-solver/src/Distribution/Solver/Modular/ConflictSet.hs index 00cf15b466f..6c9b4280986 100644 --- a/cabal-install-solver/src/Distribution/Solver/Modular/ConflictSet.hs +++ b/cabal-install-solver/src/Distribution/Solver/Modular/ConflictSet.hs @@ -74,6 +74,15 @@ data Conflict = -- means that package y's constraint 'x >= 2.0' excluded some version of x. | VersionConflict QPN OrderedVersionRange + -- | The conflict set variable represents a package that was excluded for + -- violating the closure property of a private-scope, because that package is part of + -- the closure of the private scope, but it itself is not + -- included in it. For example, the conflict set entry '(P pkgC, + -- PrivateScopeClosureConflict pkgA:lib:G0:pkgB pkgA:lib:G0:pkgD)' means + -- that pkgC is in the (private-deps) closure from pkgA:lib:G0:pkgB to + -- pkgA:lib:G0:pkgD, but pkgC is not included in the private scope pkgA:lib:G0. + | PrivateScopeClosureConflict QPN QPN + -- | Any other conflict. | OtherConflict deriving (Eq, Ord, Show) diff --git a/cabal-install-solver/src/Distribution/Solver/Modular/Dependency.hs b/cabal-install-solver/src/Distribution/Solver/Modular/Dependency.hs index 27debc9c6f0..195c9b71646 100644 --- a/cabal-install-solver/src/Distribution/Solver/Modular/Dependency.hs +++ b/cabal-install-solver/src/Distribution/Solver/Modular/Dependency.hs @@ -58,6 +58,7 @@ import Distribution.Solver.Types.PackagePath import Distribution.Types.LibraryName import Distribution.Types.PkgconfigVersionRange import Distribution.Types.UnqualComponentName +import Distribution.Types.Dependency {------------------------------------------------------------------------------- Constrained instances @@ -119,11 +120,11 @@ data LDep qpn = LDep (DependencyReason qpn) (Dep qpn) -- | A dependency (constraint) associates a package name with a constrained -- instance. It can also represent other types of dependencies, such as -- dependencies on language extensions. -data Dep qpn = Dep (PkgComponent qpn) CI -- ^ dependency on a package component +data Dep qpn = Dep (PkgComponent qpn) IsPrivate CI -- ^ dependency on a package component | Ext Extension -- ^ dependency on a language extension | Lang Language -- ^ dependency on a language version | Pkg PkgconfigName PkgconfigVersionRange -- ^ dependency on a pkg-config package - deriving Functor + deriving (Functor) -- | An exposed component within a package. This type is used to represent -- build-depends and build-tool-depends dependencies. @@ -174,15 +175,15 @@ data QualifyOptions = QO { -- -- NOTE: It's the _dependencies_ of a package that may or may not be independent -- from the package itself. Package flag choices must of course be consistent. -qualifyDeps :: QualifyOptions -> QPN -> FlaggedDeps PN -> FlaggedDeps QPN -qualifyDeps QO{..} (Q pp@(PackagePath ns q) pn) = go +qualifyDeps :: QualifyOptions -> RevDepMap -> QPN -> FlaggedDeps PN -> FlaggedDeps QPN +qualifyDeps QO{..} rdm (Q pp@(PackagePath ns q) pn) = go where go :: FlaggedDeps PN -> FlaggedDeps QPN go = map go1 go1 :: FlaggedDep PN -> FlaggedDep QPN - go1 (Flagged fn nfo t f) = Flagged (fmap (Q pp) fn) nfo (go t) (go f) - go1 (Stanza sn t) = Stanza (fmap (Q pp) sn) (go t) + go1 (Flagged fn nfo t f) = Flagged (fmap (Q pp ) fn) nfo (go t) (go f) + go1 (Stanza sn t) = Stanza (fmap (Q pp ) sn) (go t) go1 (Simple dep comp) = Simple (goLDep dep comp) comp -- Suppose package B has a setup dependency on package A. @@ -194,18 +195,19 @@ qualifyDeps QO{..} (Q pp@(PackagePath ns q) pn) = go -- @"A"@ into @"B-setup.A"@, but we should not apply that same qualifier -- to the DependencyReason. goLDep :: LDep PN -> Component -> LDep QPN - goLDep (LDep dr dep) comp = LDep (fmap (Q pp) dr) (goD dep comp) + goLDep (LDep dr dep) comp = LDep (fmap (Q pp ) dr) (goD dep comp) goD :: Dep PN -> Component -> Dep QPN goD (Ext ext) _ = Ext ext goD (Lang lang) _ = Lang lang goD (Pkg pkn vr) _ = Pkg pkn vr - goD (Dep dep@(PkgComponent qpn (ExposedExe _)) ci) _ = - Dep (Q (PackagePath ns (QualExe pn qpn)) <$> dep) ci - goD (Dep dep@(PkgComponent qpn (ExposedLib _)) ci) comp - | qBase qpn = Dep (Q (PackagePath ns (QualBase pn)) <$> dep) ci - | qSetup comp = Dep (Q (PackagePath ns (QualSetup pn)) <$> dep) ci - | otherwise = Dep (Q (PackagePath ns inheritedQ ) <$> dep) ci + goD (Dep dep@(PkgComponent qpn (ExposedExe _)) is_private ci) _ = + Dep (Q (PackagePath (IndependentBuildTool pn qpn) QualToplevel) <$> dep) is_private ci + goD (Dep dep@(PkgComponent qpn (ExposedLib _)) is_private ci) comp + | Private pq <- is_private = Dep (Q (PackagePath ns (QualAlias pn comp pq)) <$> dep) is_private ci + | qBase qpn = Dep (Q (PackagePath ns (QualBase pn)) <$> dep) is_private ci + | qSetup comp = Dep (Q (PackagePath (IndependentComponent pn ComponentSetup) QualToplevel) <$> dep) is_private ci + | otherwise = Dep (Q (PackagePath ns (inheritedQ qpn) ) <$> dep) is_private ci -- If P has a setup dependency on Q, and Q has a regular dependency on R, then -- we say that the 'Setup' qualifier is inherited: P has an (indirect) setup @@ -214,12 +216,19 @@ qualifyDeps QO{..} (Q pp@(PackagePath ns q) pn) = go -- The inherited qualifier is only used for regular dependencies; for setup -- and base dependencies we override the existing qualifier. See #3160 for -- a detailed discussion. - inheritedQ :: Qualifier - inheritedQ = case q of - QualSetup _ -> q - QualExe _ _ -> q - QualToplevel -> q - QualBase _ -> QualToplevel + inheritedQ :: PackageName -> Qualifier + inheritedQ pnx = case q of + QualToplevel -> QualToplevel + QualBase {} -> QualToplevel + -- check if package name is in same private scope (if so, persist) + QualAlias {} -> + -- Lookup this dependency in the reverse dependency map + -- with the package-path of the package that introduced + -- this dependency, which will match if this dependency is + -- included in the same private scope. + case M.lookup (Q pp pnx) rdm of + Just _x -> q -- found, use same private qualifier + Nothing -> QualToplevel -- not found, use top level qual -- Should we qualify this goal with the 'Base' package path? qBase :: PN -> Bool diff --git a/cabal-install-solver/src/Distribution/Solver/Modular/Explore.hs b/cabal-install-solver/src/Distribution/Solver/Modular/Explore.hs index 90038a28f5c..fe54752771d 100644 --- a/cabal-install-solver/src/Distribution/Solver/Modular/Explore.hs +++ b/cabal-install-solver/src/Distribution/Solver/Modular/Explore.hs @@ -220,9 +220,9 @@ exploreLog mbj enableBj fineGrainedConflicts (CountConflicts countConflicts) idx let es' = es { esConflictMap = updateCM c (esConflictMap es) } in failWith (Failure c fr) (NoSolution c es') go (DoneF rdm a) = \ _ -> succeedWith Success (a, rdm) - go (PChoiceF qpn _ gr ts) = + go (PChoiceF qpn rdm gr ts) = backjump mbj enableBj fineGrainedConflicts - (couldResolveConflicts qpn) + (couldResolveConflicts rdm qpn) (logSkippedPackage qpn) (P qpn) (avoidSet (P qpn) gr) $ -- try children in order, W.mapWithKey -- when descending ... @@ -267,23 +267,24 @@ exploreLog mbj enableBj fineGrainedConflicts (CountConflicts countConflicts) idx -- is true, because it is always safe to explore a package instance. -- Skipping it is an optimization. If false, it returns a new conflict set -- to be merged with the previous one. - couldResolveConflicts :: QPN -> POption -> S.Set CS.Conflict -> Maybe ConflictSet - couldResolveConflicts currentQPN@(Q _ pn) (POption i@(I v _) _) conflicts = + couldResolveConflicts :: RevDepMap -> QPN -> POption -> S.Set CS.Conflict -> Maybe ConflictSet + couldResolveConflicts rdm currentQPN@(Q _ pn) (POption i@(I v _) _) conflicts = let (PInfo deps _ _ _) = idx M.! pn M.! i - qdeps = qualifyDeps (defaultQualifyOptions idx) currentQPN deps + qdeps = qualifyDeps (defaultQualifyOptions idx) rdm currentQPN deps couldBeResolved :: CS.Conflict -> Maybe ConflictSet couldBeResolved CS.OtherConflict = Nothing + couldBeResolved (CS.PrivateScopeClosureConflict _ _) = Nothing -- Could we optimise here? couldBeResolved (CS.GoalConflict conflictingDep) = -- Check whether this package instance also has 'conflictingDep' -- as a dependency (ignoring flag and stanza choices). - if null [() | Simple (LDep _ (Dep (PkgComponent qpn _) _)) _ <- qdeps, qpn == conflictingDep] + if null [() | Simple (LDep _ (Dep (PkgComponent qpn _) _is_private _)) _ <- qdeps, qpn == conflictingDep] then Nothing else Just CS.empty couldBeResolved (CS.VersionConstraintConflict dep excludedVersion) = -- Check whether this package instance also excludes version -- 'excludedVersion' of 'dep' (ignoring flag and stanza choices). - let vrs = [vr | Simple (LDep _ (Dep (PkgComponent qpn _) (Constrained vr))) _ <- qdeps, qpn == dep ] + let vrs = [vr | Simple (LDep _ (Dep (PkgComponent qpn _) _is_private (Constrained vr))) _ <- qdeps, qpn == dep ] vrIntersection = L.foldl' (.&&.) anyVersion vrs in if checkVR vrIntersection excludedVersion then Nothing diff --git a/cabal-install-solver/src/Distribution/Solver/Modular/Index.hs b/cabal-install-solver/src/Distribution/Solver/Modular/Index.hs index 2f28d12de85..0c17ff731e3 100644 --- a/cabal-install-solver/src/Distribution/Solver/Modular/Index.hs +++ b/cabal-install-solver/src/Distribution/Solver/Modular/Index.hs @@ -60,13 +60,13 @@ groupMap xs = M.fromListWith (flip (++)) (L.map (\ (x, y) -> (x, [y])) xs) defaultQualifyOptions :: Index -> QualifyOptions defaultQualifyOptions idx = QO { - qoBaseShim = or [ dep == base + qoBaseShim = or [ dep == base | -- Find all versions of base .. Just is <- [M.lookup base idx] -- .. which are installed .. , (I _ver (Inst _), PInfo deps _comps _flagNfo _fr) <- M.toList is -- .. and flatten all their dependencies .. - , (LDep _ (Dep (PkgComponent dep _) _ci), _comp) <- flattenFlaggedDeps deps + , (LDep _ (Dep (PkgComponent dep _) _ _ci), _comp) <- flattenFlaggedDeps deps ] , qoSetupIndependent = True } diff --git a/cabal-install-solver/src/Distribution/Solver/Modular/IndexConversion.hs b/cabal-install-solver/src/Distribution/Solver/Modular/IndexConversion.hs index 72d0b8193e3..fc5b15f33d1 100644 --- a/cabal-install-solver/src/Distribution/Solver/Modular/IndexConversion.hs +++ b/cabal-install-solver/src/Distribution/Solver/Modular/IndexConversion.hs @@ -147,7 +147,7 @@ convIPId dr comp idx ipid = Nothing -> Left ipid Just ipi -> let (pn, i) = convId ipi name = ExposedLib LMainLibName -- TODO: Handle sub-libraries. - in Right (D.Simple (LDep dr (Dep (PkgComponent pn name) (Fixed i))) comp) + in Right (D.Simple (LDep dr (Dep (PkgComponent pn name) Public (Fixed i))) comp) -- NB: something we pick up from the -- InstalledPackageIndex is NEVER an executable @@ -172,6 +172,7 @@ convSP os arch cinfo constraints strfl solveExes (SourcePackage (PackageIdentifi -- want to keep the condition tree, but simplify much of the test. -- | Convert a generic package description to a solver-specific 'PInfo'. +-- Key function for private dependencies convGPD :: OS -> Arch -> CompilerInfo -> [LabeledPackageConstraint] -> StrongFlags -> SolveExecutables -> PN -> GenericPackageDescription -> PInfo @@ -182,7 +183,7 @@ convGPD os arch cinfo constraints strfl solveExes pn conv :: Monoid a => Component -> (a -> BuildInfo) -> DependencyReason PN -> - CondTree ConfVar [Dependency] a -> FlaggedDeps PN + CondTree ConfVar Dependencies a -> FlaggedDeps PN conv comp getInfo dr = convCondTree M.empty dr pkg os arch cinfo pn fds comp getInfo solveExes . addBuildableCondition getInfo @@ -251,7 +252,7 @@ testConditionForComponent :: OS -> CompilerInfo -> [LabeledPackageConstraint] -> (a -> Bool) - -> CondTree ConfVar [Dependency] a + -> CondTree ConfVar Dependencies a -> Maybe Bool testConditionForComponent os arch cinfo constraints p tree = case go $ extractCondition p tree of @@ -329,17 +330,20 @@ convCondTree :: Map FlagName Bool -> DependencyReason PN -> PackageDescription - Component -> (a -> BuildInfo) -> SolveExecutables -> - CondTree ConfVar [Dependency] a -> FlaggedDeps PN + CondTree ConfVar Dependencies a -> FlaggedDeps PN convCondTree flags dr pkg os arch cinfo pn fds comp getInfo solveExes@(SolveExecutables solveExes') (CondNode info ds branches) = -- Merge all library and build-tool dependencies at every level in -- the tree of flagged dependencies. Otherwise 'extractCommon' -- could create duplicate dependencies, and the number of -- duplicates could grow exponentially from the leaves to the root -- of the tree. - mergeSimpleDeps $ - [ D.Simple singleDep comp - | dep <- ds - , singleDep <- convLibDeps dr dep ] -- unconditional package dependencies + mergeSimpleDeps $ ([ D.Simple singleDep comp + | dep <- publicDependencies ds + , singleDep <- convLibDeps dr dep ]) -- unconditional package dependencies + + ++ [ D.Simple singleDep comp + | dep <- privateDependencies ds + , singleDep <- convLibDepsAs dr dep ] -- unconditional package dependencies ++ L.map (\e -> D.Simple (LDep dr (Ext e)) comp) (allExtensions bi) -- unconditional extension dependencies ++ L.map (\l -> D.Simple (LDep dr (Lang l)) comp) (allLanguages bi) -- unconditional language dependencies @@ -390,7 +394,7 @@ mergeSimpleDeps deps = L.map (uncurry toFlaggedDep) (M.toList merged) ++ unmerge => (Map (SimpleFlaggedDepKey qpn) (SimpleFlaggedDepValue qpn), FlaggedDeps qpn) -> FlaggedDep qpn -> (Map (SimpleFlaggedDepKey qpn) (SimpleFlaggedDepValue qpn), FlaggedDeps qpn) - f (merged', unmerged') (D.Simple (LDep dr (Dep dep (Constrained vr))) comp) = + f (merged', unmerged') (D.Simple (LDep dr (Dep dep Public (Constrained vr))) comp) = ( M.insertWith mergeValues (SimpleFlaggedDepKey dep comp) (SimpleFlaggedDepValue dr vr) @@ -408,7 +412,7 @@ mergeSimpleDeps deps = L.map (uncurry toFlaggedDep) (M.toList merged) ++ unmerge -> SimpleFlaggedDepValue qpn -> FlaggedDep qpn toFlaggedDep (SimpleFlaggedDepKey dep comp) (SimpleFlaggedDepValue dr vr) = - D.Simple (LDep dr (Dep dep (Constrained vr))) comp + D.Simple (LDep dr (Dep dep Public (Constrained vr))) comp -- | Branch interpreter. Mutually recursive with 'convCondTree'. -- @@ -461,7 +465,7 @@ convBranch :: Map FlagName Bool -> Component -> (a -> BuildInfo) -> SolveExecutables - -> CondBranch ConfVar [Dependency] a + -> CondBranch ConfVar Dependencies a -> FlaggedDeps PN convBranch flags dr pkg os arch cinfo pn fds comp getInfo solveExes (CondBranch c' t' mf') = go c' @@ -532,10 +536,10 @@ convBranch flags dr pkg os arch cinfo pn fds comp getInfo solveExes (CondBranch -- Union the DependencyReasons, because the extracted dependency can be -- avoided by removing the dependency from either side of the -- conditional. - [ D.Simple (LDep (unionDRs vs1 vs2) (Dep dep1 (Constrained $ vr1 .||. vr2))) comp - | D.Simple (LDep vs1 (Dep dep1 (Constrained vr1))) _ <- ps - , D.Simple (LDep vs2 (Dep dep2 (Constrained vr2))) _ <- ps' - , dep1 == dep2 + [ D.Simple (LDep (unionDRs vs1 vs2) (Dep dep1 is_private1 (Constrained $ vr1 .||. vr2))) comp + | D.Simple (LDep vs1 (Dep dep1 is_private1 (Constrained vr1))) _ <- ps + , D.Simple (LDep vs2 (Dep dep2 is_private2 (Constrained vr2))) _ <- ps' + , dep1 == dep2 && is_private1 == is_private2 ] -- | Merge DependencyReasons by unioning their variables. @@ -547,12 +551,17 @@ unionDRs (DependencyReason pn' fs1 ss1) (DependencyReason _ fs2 ss2) = -- package) to solver-specific dependencies. convLibDeps :: DependencyReason PN -> Dependency -> [LDep PN] convLibDeps dr (Dependency pn vr libs) = - [ LDep dr $ Dep (PkgComponent pn (ExposedLib lib)) (Constrained vr) + [ LDep dr $ Dep (PkgComponent pn (ExposedLib lib)) Public (Constrained vr) | lib <- NonEmptySet.toList libs ] +convLibDepsAs :: DependencyReason PN -> PrivateDependency -> [LDep PN] +convLibDepsAs dr (PrivateDependency alias deps) = + [ LDep dr $ Dep (PkgComponent pn (ExposedLib lib)) (Private alias) (Constrained vr) + | Dependency pn vr libs <- deps, lib <- NonEmptySet.toList libs ] + -- | Convert a Cabal dependency on an executable (build-tools) to a solver-specific dependency. convExeDep :: DependencyReason PN -> ExeDependency -> LDep PN -convExeDep dr (ExeDependency pn exe vr) = LDep dr $ Dep (PkgComponent pn (ExposedExe exe)) (Constrained vr) +convExeDep dr (ExeDependency pn exe vr) = LDep dr $ Dep (PkgComponent pn (ExposedExe exe)) Public (Constrained vr) -- | Convert setup dependencies convSetupBuildInfo :: PN -> SetupBuildInfo -> FlaggedDeps PN diff --git a/cabal-install-solver/src/Distribution/Solver/Modular/Linking.hs b/cabal-install-solver/src/Distribution/Solver/Modular/Linking.hs index 3e4e2de3ee6..6e9b2f3ae86 100644 --- a/cabal-install-solver/src/Distribution/Solver/Modular/Linking.hs +++ b/cabal-install-solver/src/Distribution/Solver/Modular/Linking.hs @@ -85,11 +85,11 @@ validateLinking index = (`runReader` initVS) . go go :: Tree d c -> Validate (Tree d c) go (PChoice qpn rdm gr cs) = - PChoice qpn rdm gr <$> W.traverseWithKey (goP qpn) (fmap go cs) + PChoice qpn rdm gr <$> W.traverseWithKey (goP rdm qpn) (fmap go cs) go (FChoice qfn rdm gr t m d cs) = - FChoice qfn rdm gr t m d <$> W.traverseWithKey (goF qfn) (fmap go cs) + FChoice qfn rdm gr t m d <$> W.traverseWithKey (goF rdm qfn) (fmap go cs) go (SChoice qsn rdm gr t cs) = - SChoice qsn rdm gr t <$> W.traverseWithKey (goS qsn) (fmap go cs) + SChoice qsn rdm gr t <$> W.traverseWithKey (goS rdm qsn) (fmap go cs) -- For the other nodes we just recurse go (GoalChoice rdm cs) = GoalChoice rdm <$> T.traverse go cs @@ -97,29 +97,29 @@ validateLinking index = (`runReader` initVS) . go go (Fail conflictSet failReason) = return $ Fail conflictSet failReason -- Package choices - goP :: QPN -> POption -> Validate (Tree d c) -> Validate (Tree d c) - goP qpn@(Q _pp pn) opt@(POption i _) r = do + goP :: RevDepMap -> QPN -> POption -> Validate (Tree d c) -> Validate (Tree d c) + goP rdm qpn@(Q _pp pn) opt@(POption i _) r = do vs <- ask let PInfo deps _ _ _ = vsIndex vs ! pn ! i - qdeps = qualifyDeps (vsQualifyOptions vs) qpn deps + qdeps = qualifyDeps (vsQualifyOptions vs) rdm qpn deps newSaved = M.insert qpn qdeps (vsSaved vs) - case execUpdateState (pickPOption qpn opt qdeps) vs of + case execUpdateState (pickPOption rdm qpn opt qdeps) vs of Left (cs, err) -> return $ Fail cs (DependenciesNotLinked err) Right vs' -> local (const vs' { vsSaved = newSaved }) r -- Flag choices - goF :: QFN -> Bool -> Validate (Tree d c) -> Validate (Tree d c) - goF qfn b r = do + goF :: RevDepMap -> QFN -> Bool -> Validate (Tree d c) -> Validate (Tree d c) + goF rdm qfn b r = do vs <- ask - case execUpdateState (pickFlag qfn b) vs of + case execUpdateState (pickFlag rdm qfn b) vs of Left (cs, err) -> return $ Fail cs (DependenciesNotLinked err) Right vs' -> local (const vs') r -- Stanza choices (much the same as flag choices) - goS :: QSN -> Bool -> Validate (Tree d c) -> Validate (Tree d c) - goS qsn b r = do + goS :: RevDepMap -> QSN -> Bool -> Validate (Tree d c) -> Validate (Tree d c) + goS rdm qsn b r = do vs <- ask - case execUpdateState (pickStanza qsn b) vs of + case execUpdateState (pickStanza rdm qsn b) vs of Left (cs, err) -> return $ Fail cs (DependenciesNotLinked err) Right vs' -> local (const vs') r @@ -159,9 +159,9 @@ conflict = lift' . Left execUpdateState :: UpdateState () -> ValidateState -> Either Conflict ValidateState execUpdateState = execStateT . unUpdateState -pickPOption :: QPN -> POption -> FlaggedDeps QPN -> UpdateState () -pickPOption qpn (POption i Nothing) _deps = pickConcrete qpn i -pickPOption qpn (POption i (Just pp')) deps = pickLink qpn i pp' deps +pickPOption :: RevDepMap -> QPN -> POption -> FlaggedDeps QPN -> UpdateState () +pickPOption _rdm qpn (POption i Nothing) _deps = pickConcrete qpn i +pickPOption rdm qpn (POption i (Just pp')) deps = pickLink rdm qpn i pp' deps pickConcrete :: QPN -> I -> UpdateState () pickConcrete qpn@(Q pp _) i = do @@ -177,8 +177,8 @@ pickConcrete qpn@(Q pp _) i = do Just lg -> makeCanonical lg qpn i -pickLink :: QPN -> I -> PackagePath -> FlaggedDeps QPN -> UpdateState () -pickLink qpn@(Q _pp pn) i pp' deps = do +pickLink :: RevDepMap -> QPN -> I -> PackagePath -> FlaggedDeps QPN -> UpdateState () +pickLink rdm qpn@(Q _pp pn) i pp' deps = do vs <- get -- The package might already be in a link group @@ -209,7 +209,7 @@ pickLink qpn@(Q _pp pn) i pp' deps = do updateLinkGroup lgTarget' -- Make sure all dependencies are linked as well - linkDeps target deps + linkDeps rdm target deps makeCanonical :: LinkGroup -> QPN -> I -> UpdateState () makeCanonical lg qpn@(Q pp _) i = @@ -233,8 +233,8 @@ makeCanonical lg qpn@(Q pp _) i = -- because having the direct dependencies in a link group means that we must -- have already made or will make sooner or later a link choice for one of these -- as well, and cover their dependencies at that point. -linkDeps :: QPN -> FlaggedDeps QPN -> UpdateState () -linkDeps target = \deps -> do +linkDeps :: RevDepMap -> QPN -> FlaggedDeps QPN -> UpdateState () +linkDeps rdm target = \deps -> do -- linkDeps is called in two places: when we first link one package to -- another, and when we discover more dependencies of an already linked -- package after doing some flag assignment. It is therefore important that @@ -248,7 +248,7 @@ linkDeps target = \deps -> do go1 :: FlaggedDep QPN -> FlaggedDep QPN -> UpdateState () go1 dep rdep = case (dep, rdep) of - (Simple (LDep dr1 (Dep (PkgComponent qpn _) _)) _, ~(Simple (LDep dr2 (Dep (PkgComponent qpn' _) _)) _)) -> do + (Simple (LDep dr1 (Dep (PkgComponent qpn _) _is_private1 _)) _, ~(Simple (LDep dr2 (Dep (PkgComponent qpn' _) _is_private2 _)) _)) -> do vs <- get let lg = M.findWithDefault (lgSingleton qpn Nothing) qpn $ vsLinks vs lg' = M.findWithDefault (lgSingleton qpn' Nothing) qpn' $ vsLinks vs @@ -276,19 +276,19 @@ linkDeps target = \deps -> do requalify :: FlaggedDeps QPN -> UpdateState (FlaggedDeps QPN) requalify deps = do vs <- get - return $ qualifyDeps (vsQualifyOptions vs) target (unqualifyDeps deps) + return $ qualifyDeps (vsQualifyOptions vs) rdm target (unqualifyDeps deps) -pickFlag :: QFN -> Bool -> UpdateState () -pickFlag qfn b = do +pickFlag :: RevDepMap -> QFN -> Bool -> UpdateState () +pickFlag rdm qfn b = do modify $ \vs -> vs { vsFlags = M.insert qfn b (vsFlags vs) } verifyFlag qfn - linkNewDeps (F qfn) b + linkNewDeps rdm (F qfn) b -pickStanza :: QSN -> Bool -> UpdateState () -pickStanza qsn b = do +pickStanza :: RevDepMap -> QSN -> Bool -> UpdateState () +pickStanza rdm qsn b = do modify $ \vs -> vs { vsStanzas = M.insert qsn b (vsStanzas vs) } verifyStanza qsn - linkNewDeps (S qsn) b + linkNewDeps rdm (S qsn) b -- | Link dependencies that we discover after making a flag or stanza choice. -- @@ -297,15 +297,15 @@ pickStanza qsn b = do -- non-trivial link group, then these new dependencies have to be linked as -- well. In linkNewDeps, we compute such new dependencies and make sure they are -- linked. -linkNewDeps :: Var QPN -> Bool -> UpdateState () -linkNewDeps var b = do +linkNewDeps :: RevDepMap -> Var QPN -> Bool -> UpdateState () +linkNewDeps rdm var b = do vs <- get let qpn@(Q pp pn) = varPN var qdeps = vsSaved vs ! qpn lg = vsLinks vs ! qpn newDeps = findNewDeps vs qdeps linkedTo = S.delete pp (lgMembers lg) - forM_ (S.toList linkedTo) $ \pp' -> linkDeps (Q pp' pn) newDeps + forM_ (S.toList linkedTo) $ \pp' -> linkDeps rdm (Q pp' pn) newDeps where findNewDeps :: ValidateState -> FlaggedDeps QPN -> FlaggedDeps QPN findNewDeps vs = concatMap (findNewDeps' vs) diff --git a/cabal-install-solver/src/Distribution/Solver/Modular/Message.hs b/cabal-install-solver/src/Distribution/Solver/Modular/Message.hs index e097d3e081c..8f1b05c23e9 100644 --- a/cabal-install-solver/src/Distribution/Solver/Modular/Message.hs +++ b/cabal-install-solver/src/Distribution/Solver/Modular/Message.hs @@ -181,6 +181,7 @@ showConflicts conflicts = Just (qpn, MergedPackageConflict False [v] Nothing) toMergedConflict (CS.VersionConflict qpn (CS.OrderedVersionRange vr)) = Just (qpn, MergedPackageConflict False [] (Just vr)) + toMergedConflict (CS.PrivateScopeClosureConflict _ _) = Nothing toMergedConflict CS.OtherConflict = Nothing showConflict :: QPN -> MergedPackageConflict -> String @@ -302,6 +303,7 @@ showFR c Backjump = " (backjumping, conflict set: " ++ s showFR _ MultipleInstances = " (multiple instances)" showFR c (DependenciesNotLinked msg) = " (dependencies not linked: " ++ msg ++ "; conflict set: " ++ showConflictSet c ++ ")" showFR c CyclicDependencies = " (cyclic dependencies; conflict set: " ++ showConflictSet c ++ ")" +showFR c (InvalidPrivateScope qual) = " (private scopes must contain its closure, but package " ++ showConflictSet c ++ " is not included in the private scope " ++ prettyShow qual ++ ")" showFR _ (UnsupportedSpecVer ver) = " (unsupported spec-version " ++ prettyShow ver ++ ")" -- The following are internal failures. They should not occur. In the -- interest of not crashing unnecessarily, we still just print an error diff --git a/cabal-install-solver/src/Distribution/Solver/Modular/Package.hs b/cabal-install-solver/src/Distribution/Solver/Modular/Package.hs index ccd0e4d4a70..6b35808902a 100644 --- a/cabal-install-solver/src/Distribution/Solver/Modular/Package.hs +++ b/cabal-install-solver/src/Distribution/Solver/Modular/Package.hs @@ -11,8 +11,6 @@ module Distribution.Solver.Modular.Package , QPV , instI , makeIndependent - , primaryPP - , setupPP , showI , showPI , unPN @@ -77,29 +75,6 @@ instI :: I -> Bool instI (I _ (Inst _)) = True instI _ = False --- | Is the package in the primary group of packages. This is used to --- determine (1) if we should try to establish stanza preferences --- for this goal, and (2) whether or not a user specified @--constraint@ --- should apply to this dependency (grep 'primaryPP' to see the --- use sites). In particular this does not include packages pulled in --- as setup deps. --- -primaryPP :: PackagePath -> Bool -primaryPP (PackagePath _ns q) = go q - where - go QualToplevel = True - go (QualBase _) = True - go (QualSetup _) = False - go (QualExe _ _) = False - --- | Is the package a dependency of a setup script. This is used to --- establish whether or not certain constraints should apply to this --- dependency (grep 'setupPP' to see the use sites). --- -setupPP :: PackagePath -> Bool -setupPP (PackagePath _ns (QualSetup _)) = True -setupPP (PackagePath _ns _) = False - -- | Qualify a target package with its own name so that its dependencies are not -- required to be consistent with other targets. makeIndependent :: PN -> QPN diff --git a/cabal-install-solver/src/Distribution/Solver/Modular/Preference.hs b/cabal-install-solver/src/Distribution/Solver/Modular/Preference.hs index 9e0d5fb4d22..61713c305c0 100644 --- a/cabal-install-solver/src/Distribution/Solver/Modular/Preference.hs +++ b/cabal-install-solver/src/Distribution/Solver/Modular/Preference.hs @@ -43,6 +43,7 @@ import Distribution.Solver.Modular.Tree import Distribution.Solver.Modular.Version import qualified Distribution.Solver.Modular.ConflictSet as CS import qualified Distribution.Solver.Modular.WeightedPSQ as W +import Distribution.Solver.Types.ComponentDeps (Component(..)) -- | Update the weights of children under 'PChoice' nodes. 'addWeights' takes a -- list of weight-calculating functions in order to avoid sorting the package @@ -358,6 +359,7 @@ onlyConstrained p = go go x = x + -- | Sort all goals using the provided function. sortGoals :: (Variable QPN -> Variable QPN -> Ordering) -> EndoTreeTrav d c sortGoals variableOrder = go @@ -420,8 +422,9 @@ deferSetupExeChoices = go go x = x noSetupOrExe :: Goal QPN -> Bool - noSetupOrExe (Goal (P (Q (PackagePath _ns (QualSetup _)) _)) _) = False - noSetupOrExe (Goal (P (Q (PackagePath _ns (QualExe _ _)) _)) _) = False + -- TODO: MP defer all component goals? + noSetupOrExe (Goal (P (Q (PackagePath (IndependentComponent _ ComponentSetup) _) _)) _) = False + noSetupOrExe (Goal (P (Q (PackagePath (IndependentBuildTool {}) _) _)) _) = False noSetupOrExe _ = True -- | Transformation that tries to avoid making weak flag choices early. diff --git a/cabal-install-solver/src/Distribution/Solver/Modular/PrivateScopeClosure.hs b/cabal-install-solver/src/Distribution/Solver/Modular/PrivateScopeClosure.hs new file mode 100644 index 00000000000..82e3c4f5637 --- /dev/null +++ b/cabal-install-solver/src/Distribution/Solver/Modular/PrivateScopeClosure.hs @@ -0,0 +1,126 @@ +{-# LANGUAGE TupleSections #-} +module Distribution.Solver.Modular.PrivateScopeClosure where + +import Control.Exception (assert) +import Prelude hiding (cycle) +import qualified Data.Map as M + +import Distribution.Solver.Modular.Dependency +import Distribution.Solver.Modular.Flag +import Distribution.Solver.Modular.Tree +import qualified Distribution.Solver.Modular.ConflictSet as CS +import Distribution.Solver.Types.PackagePath + +-- | Find and reject any nodes that would violate the private-dependencies +-- closure property, which states that all packages within the closure of a +-- private scope must also be included in the private scope. +detectInvalidPrivateScopesPhase :: Tree d c -> Tree d c +detectInvalidPrivateScopesPhase = go + where + -- Similar to detectCyclesPhase, maybe we could deduplicate + go :: Tree d c -> Tree d c + go (PChoice qpn rdm gr cs) = + PChoice qpn rdm gr $ fmap (checkChild qpn) (fmap go cs) + go (FChoice qfn@(FN qpn _) rdm gr w m d cs) = + FChoice qfn rdm gr w m d $ fmap (checkChild qpn) (fmap go cs) + go (SChoice qsn@(SN qpn _) rdm gr w cs) = + SChoice qsn rdm gr w $ fmap (checkChild qpn) (fmap go cs) + go (GoalChoice rdm cs) = GoalChoice rdm (fmap go cs) + go x@(Fail _ _) = x + go x@(Done _ _) = x + + checkChild :: QPN -> Tree d c -> Tree d c + checkChild qpn x@(PChoice _ rdm _ _) = failIfBadClosure qpn rdm x + checkChild qpn x@(FChoice _ rdm _ _ _ _ _) = failIfBadClosure qpn rdm x + checkChild qpn x@(SChoice _ rdm _ _ _) = failIfBadClosure qpn rdm x + checkChild qpn x@(GoalChoice rdm _) = failIfBadClosure qpn rdm x + checkChild _ x@(Fail _ _) = x + checkChild qpn x@(Done rdm _) = failIfBadClosure qpn rdm x + + failIfBadClosure :: QPN -> RevDepMap -> Tree d c -> Tree d c + -- An already qualified package can't violate the closure property + failIfBadClosure (Q (PackagePath _ (QualAlias _ _ _)) _) _ x = x + failIfBadClosure qpn rdm x = + case findBadClosures qpn rdm of + Nothing -> x + Just (relSet, qual) -> Fail relSet (InvalidPrivateScope qual) + +-- | Given the reverse dependency map from a node in the tree, check if the +-- solution has any bad closures. If it is, return the conflict set containing +-- the variables violating private deps closures. +findBadClosures :: QPN -> RevDepMap -> Maybe (ConflictSet, Qualifier) +findBadClosures pkg rdm = + case concatMap (\root@(Q (PackagePath _ ps) _) -> (root,) <$> concatMap (step ps False . snd) (findRevDepsTopLevel root)) roots of + (closureBegin@(Q (PackagePath _ ql) _), closureEnd@(Q (PackagePath _ ql') _)):_ -> + assert (ql == ql') $ + return (CS.singletonWithConflict (P pkg) (CS.PrivateScopeClosureConflict closureBegin closureEnd), ql) + [] -> Nothing + where + + -- Roots of the rev dep map with QualAlias/private scope + roots :: [QPN] + roots = flip M.foldMapWithKey rdm $ + \key _ -> case key of + Q (PackagePath _ (QualAlias _ _ _)) _ -> [key] + _ -> [] + + -- Traverse up from a root until a reverse dep in the same private scope is + -- found. We only traverse up until we find another private dep in the same + -- scope because that is sufficient to complete a "local closure", and + -- because we traverse from all root deps in private scopes, we will + -- traverse all the "local" closures thus the full closure of each scope... REWRITE and RENAME + step :: Qualifier -- ^ This root's qualifier/private scope + -> Bool -- ^ Have we found the "goal" package in the "local" closure + -> QPN -- ^ Next package in the closure traversal + -> [QPN] + -- ^ The terminal nodes for each closure violated by this package. + -- Empty if the closure property is kept. + step rootQual hasFoundGoal next + -- We stop at any qualified reverse dep, even if it does not belong to + -- the same scope as the one we are checking for the closure property. + -- By case analysis: + -- * If it is the same scope, we've reached the end of the local + -- closure, and if the package has been seen as non-qualified then the + -- property is violated + -- + -- * If it is not the same scope, that means "next" in that branch is a + -- dep of a private scope goal, but it may not violate the closure + -- property for that one. Even if it were to violate the property + -- outside of a nested private scope, it doesn't matter because within a + -- (nested) private scope it just has to be consistent in + -- itself......... + | Q (PackagePath _ ps@(QualAlias _ _ _)) _ <- next + = if ps == rootQual && hasFoundGoal + then [next] + else [] + | otherwise + = case findRevDepsTopLevel next of + -- If there are no more deps (meaning we didn't stop at any rev-dep in + -- a private scope), then we don't have a private scope closure and the + -- property is preserved. + [] -> [] + -- Step through all the next reverse deps, failing (by adding terminal + -- nodes to the result) if any of the steps violates the closure + -- property + xs -> + -- If the next pkg is our goal, we recurse with "hasFoundGoal = + -- True", otherwise with what we had previously + let hasFoundGoal' = next == pkg || hasFoundGoal + in concatMap (step rootQual hasFoundGoal' . snd) xs + + -- Find the reverse dependencies of this QPN, but in the top-level scope. + -- When constructing the closure, starting from a qualified root, we need + -- to take into account that the dependencies introduced by the + -- private-scoped-depends will be in the top level scope... + findRevDepsTopLevel qpn@(Q (PackagePath namespace _) pn) = + case (Q (PackagePath namespace QualToplevel) pn) `M.lookup` rdm of + Nothing -> + -- This means the package we are looking up in the map has only been + -- introduced qualified, not at the QualToplevel. This means we look + -- it up as is. + case qpn `M.lookup` rdm of + Nothing -> findError "cannot find node" + Just rdeps -> rdeps + Just rdeps -> rdeps + + findError = error . ("Distribution.Solver.Modular.PrivateScopeClosure.findBadClosures: " ++) diff --git a/cabal-install-solver/src/Distribution/Solver/Modular/Solver.hs b/cabal-install-solver/src/Distribution/Solver/Modular/Solver.hs index 39bd7bf4690..98498813126 100644 --- a/cabal-install-solver/src/Distribution/Solver/Modular/Solver.hs +++ b/cabal-install-solver/src/Distribution/Solver/Modular/Solver.hs @@ -36,6 +36,7 @@ import Distribution.Solver.Modular.Log import Distribution.Solver.Modular.Message import Distribution.Solver.Modular.Package import qualified Distribution.Solver.Modular.Preference as P +import Distribution.Solver.Modular.PrivateScopeClosure import Distribution.Solver.Modular.Validate import Distribution.Solver.Modular.Linking import Distribution.Solver.Modular.PSQ (PSQ) @@ -98,6 +99,8 @@ solve :: SolverConfig -- ^ solver parameters -> RetryLog Message SolverFailure (Assignment, RevDepMap) solve sc cinfo idx pkgConfigDB userPrefs userConstraints userGoals = explorePhase . + traceTree "invalid-scopes.json" id . + detectInvalidPrivateScopesPhase . traceTree "cycles.json" id . detectCycles . traceTree "heuristics.json" id . diff --git a/cabal-install-solver/src/Distribution/Solver/Modular/Tree.hs b/cabal-install-solver/src/Distribution/Solver/Modular/Tree.hs index 10d372525b1..0de377f5876 100644 --- a/cabal-install-solver/src/Distribution/Solver/Modular/Tree.hs +++ b/cabal-install-solver/src/Distribution/Solver/Modular/Tree.hs @@ -127,6 +127,7 @@ data FailReason = UnsupportedExtension Extension | MultipleInstances | DependenciesNotLinked String | CyclicDependencies + | InvalidPrivateScope Qualifier | UnsupportedSpecVer Ver deriving (Eq, Show) diff --git a/cabal-install-solver/src/Distribution/Solver/Modular/Validate.hs b/cabal-install-solver/src/Distribution/Solver/Modular/Validate.hs index cbe6282b6d0..7b9d8a8bf3f 100644 --- a/cabal-install-solver/src/Distribution/Solver/Modular/Validate.hs +++ b/cabal-install-solver/src/Distribution/Solver/Modular/Validate.hs @@ -158,7 +158,7 @@ validate = go where go :: Tree d c -> Validate (Tree d c) - go (PChoice qpn rdm gr ts) = PChoice qpn rdm gr <$> W.traverseWithKey (\k -> goP qpn k . go) ts + go (PChoice qpn rdm gr ts) = PChoice qpn rdm gr <$> W.traverseWithKey (\k -> goP rdm qpn k . go) ts go (FChoice qfn rdm gr b m d ts) = do -- Flag choices may occur repeatedly (because they can introduce new constraints @@ -190,8 +190,8 @@ validate = go go (Fail c fr ) = pure (Fail c fr) -- What to do for package nodes ... - goP :: QPN -> POption -> Validate (Tree d c) -> Validate (Tree d c) - goP qpn@(Q _pp pn) (POption i _) r = do + goP :: RevDepMap -> QPN -> POption -> Validate (Tree d c) -> Validate (Tree d c) + goP rdm qpn@(Q _pp pn) (POption i _) r = do PA ppa pfa psa <- asks pa -- obtain current preassignment extSupported <- asks supportedExt -- obtain the supported extensions langSupported <- asks supportedLang -- obtain the supported languages @@ -204,7 +204,7 @@ validate = go -- obtain dependencies and index-dictated exclusions introduced by the choice let (PInfo deps comps _ mfr) = idx ! pn ! i -- qualify the deps in the current scope - let qdeps = qualifyDeps qo qpn deps + let qdeps = qualifyDeps qo rdm qpn deps -- the new active constraints are given by the instance we have chosen, -- plus the dependency information we have for that instance let newactives = extractAllDeps pfa psa qdeps @@ -400,7 +400,7 @@ extend extSupported langSupported pkgPresent newactives ppa = foldM extendSingle extendSingle a (LDep dr (Pkg pn vr)) = if pkgPresent pn vr then Right a else Left (dependencyReasonToConflictSet dr, MissingPkgconfigPackage pn vr) - extendSingle a (LDep dr (Dep dep@(PkgComponent qpn _) ci)) = + extendSingle a (LDep dr (Dep dep@(PkgComponent qpn _) _is_private ci)) = let mergedDep = M.findWithDefault (MergedDepConstrained []) qpn a in case (\ x -> M.insert qpn x a) <$> merge mergedDep (PkgDep dr dep ci) of Left (c, (d, d')) -> Left (c, ConflictingConstraints d d') @@ -530,7 +530,7 @@ extendRequiredComponents eqpn available = foldM extendSingle extendSingle :: Map QPN ComponentDependencyReasons -> LDep QPN -> Either Conflict (Map QPN ComponentDependencyReasons) - extendSingle required (LDep dr (Dep (PkgComponent qpn comp) _)) = + extendSingle required (LDep dr (Dep (PkgComponent qpn comp) _is_private _)) = let compDeps = M.findWithDefault M.empty qpn required success = Right $ M.insertWith M.union qpn (M.insert comp dr compDeps) required in -- Only check for the existence of the component if its package has diff --git a/cabal-install-solver/src/Distribution/Solver/Types/ComponentDeps.hs b/cabal-install-solver/src/Distribution/Solver/Types/ComponentDeps.hs index 8926521673b..aad27391de7 100644 --- a/cabal-install-solver/src/Distribution/Solver/Types/ComponentDeps.hs +++ b/cabal-install-solver/src/Distribution/Solver/Types/ComponentDeps.hs @@ -83,7 +83,7 @@ type ComponentDep a = (Component, a) -- | Fine-grained dependencies for a package. -- --- Typically used as @ComponentDeps [Dependency]@, to represent the list of +-- Typically used as @ComponentDeps Dependencies@, to represent the list of -- dependencies for each named component within a package. -- newtype ComponentDeps a = ComponentDeps { unComponentDeps :: Map Component a } diff --git a/cabal-install-solver/src/Distribution/Solver/Types/InstSolverPackage.hs b/cabal-install-solver/src/Distribution/Solver/Types/InstSolverPackage.hs index 871a0dd15a9..5e76b6a7a24 100644 --- a/cabal-install-solver/src/Distribution/Solver/Types/InstSolverPackage.hs +++ b/cabal-install-solver/src/Distribution/Solver/Types/InstSolverPackage.hs @@ -6,7 +6,7 @@ module Distribution.Solver.Types.InstSolverPackage import Distribution.Solver.Compat.Prelude import Prelude () -import Distribution.Package ( Package(..), HasMungedPackageId(..), HasUnitId(..) ) +import Distribution.Package ( Package(..), HasMungedPackageId(..), HasUnitId(..), PrivateAlias ) import Distribution.Solver.Types.ComponentDeps ( ComponentDeps ) import Distribution.Solver.Types.SolverId import Distribution.Types.MungedPackageId @@ -18,7 +18,7 @@ import Distribution.InstalledPackageInfo (InstalledPackageInfo) -- specified by the dependency solver. data InstSolverPackage = InstSolverPackage { instSolverPkgIPI :: InstalledPackageInfo, - instSolverPkgLibDeps :: ComponentDeps [SolverId], + instSolverPkgLibDeps :: ComponentDeps [(SolverId, Maybe PrivateAlias)], instSolverPkgExeDeps :: ComponentDeps [SolverId] } deriving (Eq, Show, Generic) diff --git a/cabal-install-solver/src/Distribution/Solver/Types/PackageConstraint.hs b/cabal-install-solver/src/Distribution/Solver/Types/PackageConstraint.hs index fbe56380e81..e8efe91dbe8 100644 --- a/cabal-install-solver/src/Distribution/Solver/Types/PackageConstraint.hs +++ b/cabal-install-solver/src/Distribution/Solver/Types/PackageConstraint.hs @@ -1,4 +1,5 @@ {-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE TypeApplications #-} -- | Per-package constraints. Package constraints must be respected by the -- solver. Multiple constraints for each package can be given, though obviously @@ -31,6 +32,8 @@ import Distribution.Solver.Types.OptionalStanza import Distribution.Solver.Types.PackagePath import qualified Text.PrettyPrint as Disp +import Distribution.Solver.Types.ComponentDeps (Component(..)) +import Distribution.Types.Dependency -- | Determines to what packages and in what contexts a @@ -43,11 +46,15 @@ data ConstraintScope -- namespace (for --no-independent-goals) or it is an independent namespace -- with the given package name (for --independent-goals). - -- TODO: Try to generalize the ConstraintScopes once component-based - -- solving is implemented, and remove this special case for targets. = ScopeTarget PackageName -- | The package with the specified name and qualifier. - | ScopeQualified Qualifier PackageName + | ScopeQualified Namespace Qualifier PackageName + + -- Apply a constraint to a private-build-depends scope + -- It is not sufficient to have ScopeQualified because we don't have enough + -- information in the constraint syntax to fill in the `Component` field of + -- `QualAlias` + | ScopePrivate PackageName PrivateAlias PackageName -- | The package with the specified name when it has a -- setup qualifier. | ScopeAnySetupQualifier PackageName @@ -60,24 +67,35 @@ data ConstraintScope -- the package with the specified name when that package is a -- top-level dependency in the default namespace. scopeToplevel :: PackageName -> ConstraintScope -scopeToplevel = ScopeQualified QualToplevel +scopeToplevel = ScopeQualified DefaultNamespace QualToplevel -- | Returns the package name associated with a constraint scope. scopeToPackageName :: ConstraintScope -> PackageName scopeToPackageName (ScopeTarget pn) = pn -scopeToPackageName (ScopeQualified _ pn) = pn +scopeToPackageName (ScopeQualified _ _ pn) = pn scopeToPackageName (ScopeAnySetupQualifier pn) = pn scopeToPackageName (ScopeAnyQualifier pn) = pn +scopeToPackageName (ScopePrivate _ _ pn) = pn +-- | Whether a ConstraintScope matches a qualified package name, the crucial +-- function which determines the rules about when constraints apply. constraintScopeMatches :: ConstraintScope -> QPN -> Bool constraintScopeMatches (ScopeTarget pn) (Q (PackagePath ns q) pn') = let namespaceMatches DefaultNamespace = True namespaceMatches (Independent namespacePn) = pn == namespacePn + namespaceMatches (IndependentComponent {}) = False + namespaceMatches (IndependentBuildTool {}) = False in namespaceMatches ns && q == QualToplevel && pn == pn' -constraintScopeMatches (ScopeQualified q pn) (Q (PackagePath _ q') pn') = - q == q' && pn == pn' +constraintScopeMatches (ScopePrivate spn alias c_pn) (Q (PackagePath _qual_ns q) c_pn') = + let qualMatches (QualAlias qual_pn _ qual_alias) = spn == qual_pn && alias == qual_alias + qualMatches _ = False + -- TODO: Check whether any ns should subsume qual_ns (if private constraint scopes grow namespaces...) + in qualMatches q && c_pn == c_pn' +constraintScopeMatches (ScopeQualified ns cq cpn) (Q (PackagePath qual_ns q) cpn') = + ns == qual_ns && cq == q && cpn == cpn' + constraintScopeMatches (ScopeAnySetupQualifier pn) (Q pp pn') = - let setup (PackagePath _ (QualSetup _)) = True + let setup (PackagePath (IndependentComponent _ ComponentSetup) _) = True setup _ = False in setup pp && pn == pn' constraintScopeMatches (ScopeAnyQualifier pn) (Q _ pn') = pn == pn' @@ -85,7 +103,8 @@ constraintScopeMatches (ScopeAnyQualifier pn) (Q _ pn') = pn == pn' -- | Pretty-prints a constraint scope. dispConstraintScope :: ConstraintScope -> Disp.Doc dispConstraintScope (ScopeTarget pn) = pretty pn <<>> Disp.text "." <<>> pretty pn -dispConstraintScope (ScopeQualified q pn) = dispQualifier q <<>> pretty pn +dispConstraintScope (ScopeQualified ns _q pn) = dispNamespace ns <<>> pretty pn +dispConstraintScope (ScopePrivate pn alias p) = Disp.text "private." <<>> pretty pn <<>> Disp.text "." <<>> pretty @PrivateAlias alias <<>> Disp.text ":" <<>> pretty p dispConstraintScope (ScopeAnySetupQualifier pn) = Disp.text "setup." <<>> pretty pn dispConstraintScope (ScopeAnyQualifier pn) = Disp.text "any." <<>> pretty pn diff --git a/cabal-install-solver/src/Distribution/Solver/Types/PackagePath.hs b/cabal-install-solver/src/Distribution/Solver/Types/PackagePath.hs index 4fc4df25f97..faa0eddb887 100644 --- a/cabal-install-solver/src/Distribution/Solver/Types/PackagePath.hs +++ b/cabal-install-solver/src/Distribution/Solver/Types/PackagePath.hs @@ -2,18 +2,19 @@ module Distribution.Solver.Types.PackagePath ( PackagePath(..) , Namespace(..) , Qualifier(..) - , dispQualifier , Qualified(..) , QPN + , dispNamespace , dispQPN , showQPN ) where import Distribution.Solver.Compat.Prelude import Prelude () -import Distribution.Package (PackageName) -import Distribution.Pretty (pretty, flatStyle) +import Distribution.Package (PackageName, PrivateAlias) +import Distribution.Pretty (Pretty, pretty, flatStyle) import qualified Text.PrettyPrint as Disp +import Distribution.Solver.Types.ComponentDeps -- | A package path consists of a namespace and a package path inside that -- namespace. @@ -25,11 +26,18 @@ data PackagePath = PackagePath Namespace Qualifier -- Package choices in different namespaces are considered completely independent -- by the solver. data Namespace = - -- | The default namespace + -- | A goal which is solved DefaultNamespace - -- | A namespace for a specific build target + -- | A goal which is solved per-package + -- `--independent-goals` | Independent PackageName + + + | IndependentComponent PackageName Component + -- Build-tools are solved per-package so there are consistent build-tools across + -- components. + | IndependentBuildTool PackageName PackageName deriving (Eq, Ord, Show) -- | Pretty-prints a namespace. The result is either empty or @@ -37,6 +45,9 @@ data Namespace = dispNamespace :: Namespace -> Disp.Doc dispNamespace DefaultNamespace = Disp.empty dispNamespace (Independent i) = pretty i <<>> Disp.text "." +dispNamespace (IndependentBuildTool pn btp) = pretty pn <<>> Disp.text ":" <<>> + pretty btp <<>> Disp.text ":exe." +dispNamespace (IndependentComponent pn c) = pretty pn <<>> Disp.text ":" <<>> pretty c <<>> Disp.text "." -- | Qualifier of a package within a namespace (see 'PackagePath') data Qualifier = @@ -48,26 +59,9 @@ data Qualifier = -- This makes it possible to have base shims. | QualBase PackageName - -- | Setup dependency - -- - -- By rights setup dependencies ought to be nestable; after all, the setup - -- dependencies of a package might themselves have setup dependencies, which - -- are independent from everything else. However, this very quickly leads to - -- infinite search trees in the solver. Therefore we limit ourselves to - -- a single qualifier (within a given namespace). - | QualSetup PackageName - - -- | If we depend on an executable from a package (via - -- @build-tools@), we should solve for the dependencies of that - -- package separately (since we're not going to actually try to - -- link it.) We qualify for EACH package separately; e.g., - -- @'Exe' pn1 pn2@ qualifies the @build-tools@ dependency on - -- @pn2@ from package @pn1@. (If we tracked only @pn1@, that - -- would require a consistent dependency resolution for all - -- of the depended upon executables from a package; if we - -- tracked only @pn2@, that would require us to pick only one - -- version of an executable over the entire install plan.) - | QualExe PackageName PackageName + -- A goal which is solved per-component + | QualAlias PackageName Component PrivateAlias + deriving (Eq, Ord, Show) -- | Pretty-prints a qualifier. The result is either empty or @@ -80,10 +74,11 @@ data Qualifier = -- 'Base' qualifier, will always be @base@). dispQualifier :: Qualifier -> Disp.Doc dispQualifier QualToplevel = Disp.empty -dispQualifier (QualSetup pn) = pretty pn <<>> Disp.text ":setup." -dispQualifier (QualExe pn pn2) = pretty pn <<>> Disp.text ":" <<>> - pretty pn2 <<>> Disp.text ":exe." -dispQualifier (QualBase pn) = pretty pn <<>> Disp.text "." +dispQualifier (QualBase pn) = pretty pn <<>> Disp.text ".bb." +dispQualifier (QualAlias pn c alias) = pretty pn <<>> Disp.text ":" <<>> pretty c <<>> Disp.text ":" <<>> pretty alias <<>> Disp.text "." + +instance Pretty Qualifier where + pretty = dispQualifier -- | A qualified entity. Pairs a package path with the entity. data Qualified a = Q PackagePath a diff --git a/cabal-install-solver/src/Distribution/Solver/Types/ResolverPackage.hs b/cabal-install-solver/src/Distribution/Solver/Types/ResolverPackage.hs index 840e58aff94..f34e5944596 100644 --- a/cabal-install-solver/src/Distribution/Solver/Types/ResolverPackage.hs +++ b/cabal-install-solver/src/Distribution/Solver/Types/ResolverPackage.hs @@ -17,6 +17,7 @@ import qualified Distribution.Solver.Types.ComponentDeps as CD import Distribution.Compat.Graph (IsNode(..)) import Distribution.Package (Package(..), HasUnitId(..)) import Distribution.Simple.Utils (ordNub) +import Distribution.Types.Dependency (PrivateAlias) -- | The dependency resolver picks either pre-existing installed packages -- or it picks source packages along with package configuration. @@ -34,7 +35,7 @@ instance Package (ResolverPackage loc) where packageId (PreExisting ipkg) = packageId ipkg packageId (Configured spkg) = packageId spkg -resolverPackageLibDeps :: ResolverPackage loc -> CD.ComponentDeps [SolverId] +resolverPackageLibDeps :: ResolverPackage loc -> CD.ComponentDeps [(SolverId, Maybe PrivateAlias)] resolverPackageLibDeps (PreExisting ipkg) = instSolverPkgLibDeps ipkg resolverPackageLibDeps (Configured spkg) = solverPkgLibDeps spkg @@ -48,5 +49,5 @@ instance IsNode (ResolverPackage loc) where nodeKey (Configured spkg) = PlannedId (packageId spkg) -- Use dependencies for ALL components nodeNeighbors pkg = - ordNub $ CD.flatDeps (resolverPackageLibDeps pkg) ++ + ordNub $ (map fst (CD.flatDeps (resolverPackageLibDeps pkg))) ++ CD.flatDeps (resolverPackageExeDeps pkg) diff --git a/cabal-install-solver/src/Distribution/Solver/Types/SolverId.hs b/cabal-install-solver/src/Distribution/Solver/Types/SolverId.hs index d32ccc17e74..115207272ca 100644 --- a/cabal-install-solver/src/Distribution/Solver/Types/SolverId.hs +++ b/cabal-install-solver/src/Distribution/Solver/Types/SolverId.hs @@ -23,7 +23,7 @@ instance Binary SolverId instance Structured SolverId instance Show SolverId where - show = show . solverSrcId + show = show . solverSrcId instance Package SolverId where packageId = solverSrcId diff --git a/cabal-install-solver/src/Distribution/Solver/Types/SolverPackage.hs b/cabal-install-solver/src/Distribution/Solver/Types/SolverPackage.hs index 186f140aefe..85148db46b5 100644 --- a/cabal-install-solver/src/Distribution/Solver/Types/SolverPackage.hs +++ b/cabal-install-solver/src/Distribution/Solver/Types/SolverPackage.hs @@ -12,6 +12,7 @@ import Distribution.Solver.Types.ComponentDeps ( ComponentDeps ) import Distribution.Solver.Types.OptionalStanza import Distribution.Solver.Types.SolverId import Distribution.Solver.Types.SourcePackage +import Distribution.Types.Dependency (PrivateAlias) -- | A 'SolverPackage' is a package specified by the dependency solver. -- It will get elaborated into a 'ConfiguredPackage' or even an @@ -24,7 +25,7 @@ data SolverPackage loc = SolverPackage { solverPkgSource :: SourcePackage loc, solverPkgFlags :: FlagAssignment, solverPkgStanzas :: OptionalStanzaSet, - solverPkgLibDeps :: ComponentDeps [SolverId], + solverPkgLibDeps :: ComponentDeps [(SolverId, Maybe PrivateAlias)], solverPkgExeDeps :: ComponentDeps [SolverId] } deriving (Eq, Show, Generic) diff --git a/cabal-install/src/Distribution/Client/CmdOutdated.hs b/cabal-install/src/Distribution/Client/CmdOutdated.hs index ed40a1a85e6..2493f8fe14e 100644 --- a/cabal-install/src/Distribution/Client/CmdOutdated.hs +++ b/cabal-install/src/Distribution/Client/CmdOutdated.hs @@ -443,7 +443,7 @@ depsFromPkgDesc verbosity comp platform = do finalizePD mempty (ComponentRequestedSpec True True) - (const True) + (\_ _ -> True) platform cinfo [] @@ -457,7 +457,11 @@ depsFromPkgDesc verbosity comp platform = do "Reading the list of dependencies from the package description" return $ map toPVC bd where - toPVC (Dependency pn vr _) = PackageVersionConstraint pn vr + -- It doesn't seem critical that we report the scope in which the package + -- is outdated, because, in order for that report to be consistent with the + -- rest of Cabal, we must first consider how cabal outdated and cabal + -- freeze work wrt private dependencies (TODO). + toPVC (_alias, (Dependency pn vr _)) = PackageVersionConstraint pn vr -- | Various knobs for customising the behaviour of 'listOutdated'. data ListOutdatedSettings = ListOutdatedSettings diff --git a/cabal-install/src/Distribution/Client/CmdRepl.hs b/cabal-install/src/Distribution/Client/CmdRepl.hs index 39468a8e545..f5c012da2cf 100644 --- a/cabal-install/src/Distribution/Client/CmdRepl.hs +++ b/cabal-install/src/Distribution/Client/CmdRepl.hs @@ -132,7 +132,8 @@ import Distribution.Types.CondTree ( CondTree (..) ) import Distribution.Types.Dependency - ( Dependency (..) + ( Dependencies (..) + , Dependency (..) , mainLibSet ) import Distribution.Types.Library @@ -300,7 +301,7 @@ replAction flags@NixStyleFlags{extraFlags = r@ReplFlags{..}, ..} targetStrings g sourcePackage = fakeProjectSourcePackage projectRoot & lSrcpkgDescription . L.condLibrary - .~ Just (CondNode library [baseDep] []) + .~ Just (CondNode library (Dependencies [baseDep] []) []) library = emptyLibrary{libBuildInfo = lBuildInfo} lBuildInfo = emptyBuildInfo diff --git a/cabal-install/src/Distribution/Client/Configure.hs b/cabal-install/src/Distribution/Client/Configure.hs index fc7ea49fe31..4c8f4a5a87f 100644 --- a/cabal-install/src/Distribution/Client/Configure.hs +++ b/cabal-install/src/Distribution/Client/Configure.hs @@ -534,7 +534,7 @@ configurePackage CD.nonSetupDeps deps ] , configDependencies = - [ GivenComponent (packageName srcid) cname uid + [ GivenComponent (packageName srcid) cname uid Nothing | ConfiguredId srcid (Just (PkgDesc.CLibName cname)) uid <- CD.nonSetupDeps deps ] @@ -555,7 +555,7 @@ configurePackage pkg = case finalizePD flags (enableStanzas stanzas) - (const True) + (\_ _ -> True) platform comp [] diff --git a/cabal-install/src/Distribution/Client/Dependency.hs b/cabal-install/src/Distribution/Client/Dependency.hs index 66a0a103c23..b3895a4c2b5 100644 --- a/cabal-install/src/Distribution/Client/Dependency.hs +++ b/cabal-install/src/Distribution/Client/Dependency.hs @@ -1,3 +1,5 @@ +{-# LANGUAGE TupleSections #-} + ----------------------------------------------------------------------------- ----------------------------------------------------------------------------- @@ -960,10 +962,10 @@ data PackageProblem = DuplicateFlag PD.FlagName | MissingFlag PD.FlagName | ExtraFlag PD.FlagName - | DuplicateDeps [PackageId] - | MissingDep Dependency - | ExtraDep PackageId - | InvalidDep Dependency PackageId + | DuplicateDeps [(PackageId, Maybe PrivateAlias)] + | MissingDep Dependency (Maybe PrivateAlias) + | ExtraDep PackageId (Maybe PrivateAlias) + | InvalidDep Dependency PackageId (Maybe PrivateAlias) showPackageProblem :: PackageProblem -> String showPackageProblem (DuplicateFlag flag) = @@ -974,20 +976,23 @@ showPackageProblem (ExtraFlag flag) = "extra flag given that is not used by the package: " ++ PD.unFlagName flag showPackageProblem (DuplicateDeps pkgids) = "duplicate packages specified as selected dependencies: " - ++ intercalate ", " (map prettyShow pkgids) -showPackageProblem (MissingDep dep) = + ++ intercalate ", " (map (\(x, y) -> maybe "" ((<> ".") . prettyShow) y <> prettyShow x) pkgids) +showPackageProblem (MissingDep dep palias) = "the package has a dependency " + ++ maybe "" ((<> ".") . prettyShow) palias ++ prettyShow dep ++ " but no package has been selected to satisfy it." -showPackageProblem (ExtraDep pkgid) = +showPackageProblem (ExtraDep pkgid palias) = "the package configuration specifies " + ++ maybe "" ((<> ".") . prettyShow) palias ++ prettyShow pkgid ++ " but (with the given flag assignment) the package does not actually" ++ " depend on any version of that package." -showPackageProblem (InvalidDep dep pkgid) = +showPackageProblem (InvalidDep dep pkgid palias) = "the package depends on " ++ prettyShow dep ++ " but the configuration specifies " + ++ maybe "" ((<> ".") . prettyShow) palias ++ prettyShow pkgid ++ " which does not satisfy the dependency." @@ -1012,13 +1017,18 @@ configuredPackageProblems | pkgs <- CD.nonSetupDeps ( fmap - (duplicatesBy (comparing packageName)) + (duplicatesBy (comparing (\(x, y) -> (packageName x, y)))) specifiedDeps1 ) ] - ++ [MissingDep dep | OnlyInLeft dep <- mergedDeps] - ++ [ExtraDep pkgid | OnlyInRight pkgid <- mergedDeps] - ++ [ InvalidDep dep pkgid | InBoth dep pkgid <- mergedDeps, not (packageSatisfiesDependency pkgid dep) + ++ [MissingDep dep alias | OnlyInLeft (dep, alias) <- mergedDeps] + ++ [ExtraDep pkgid palias | OnlyInRight (pkgid, palias) <- mergedDeps] + ++ [ InvalidDep dep pkgid palias + | InBoth (dep, palias) (pkgid, _palias) <- mergedDeps + , assert + (palias == _palias) + not + (packageSatisfiesDependency pkgid dep) ] where -- TODO: sanity tests on executable deps @@ -1026,10 +1036,10 @@ configuredPackageProblems thisPkgName :: PackageName thisPkgName = packageName (srcpkgDescription pkg) - specifiedDeps1 :: ComponentDeps [PackageId] - specifiedDeps1 = fmap (map solverSrcId) specifiedDeps0 + specifiedDeps1 :: ComponentDeps [(PackageId, Maybe PrivateAlias)] + specifiedDeps1 = fmap (map (first solverSrcId)) specifiedDeps0 - specifiedDeps :: [PackageId] + specifiedDeps :: [(PackageId, Maybe PrivateAlias)] specifiedDeps = CD.flatDeps specifiedDeps1 mergedFlags :: [MergeResult PD.FlagName PD.FlagName] @@ -1047,19 +1057,19 @@ configuredPackageProblems dependencyName (Dependency name _ _) = name - mergedDeps :: [MergeResult Dependency PackageId] + mergedDeps :: [MergeResult (Dependency, Maybe PrivateAlias) (PackageId, Maybe PrivateAlias)] mergedDeps = mergeDeps requiredDeps specifiedDeps mergeDeps - :: [Dependency] - -> [PackageId] - -> [MergeResult Dependency PackageId] + :: [(Dependency, Maybe PrivateAlias)] + -> [(PackageId, Maybe PrivateAlias)] + -> [MergeResult (Dependency, Maybe PrivateAlias) (PackageId, Maybe PrivateAlias)] mergeDeps required specified = let sortNubOn f = nubBy ((==) `on` f) . sortBy (compare `on` f) in mergeBy - (\dep pkgid -> dependencyName dep `compare` packageName pkgid) - (sortNubOn dependencyName required) - (sortNubOn packageName specified) + (\(dep, alias1) (pkgid, alias2) -> (dependencyName dep, alias1) `compare` (packageName pkgid, alias2)) + (sortNubOn (first dependencyName) required) + (sortNubOn (first packageName) specified) compSpec = enableStanzas stanzas -- TODO: It would be nicer to use ComponentDeps here so we can be more @@ -1068,13 +1078,13 @@ configuredPackageProblems -- have to allow for duplicates when we fold specifiedDeps; once we have -- proper ComponentDeps here we should get rid of the `nubOn` in -- `mergeDeps`. - requiredDeps :: [Dependency] + requiredDeps :: [(Dependency, Maybe PrivateAlias)] requiredDeps = -- TODO: use something lower level than finalizePD case finalizePD specifiedFlags compSpec - (const True) + (\_ _ -> True) platform cinfo [] @@ -1088,9 +1098,11 @@ configuredPackageProblems -- See #3775 -- filter - ((/= thisPkgName) . dependencyName) - (PD.enabledBuildDepends resolvedPkg compSpec) - ++ maybe [] PD.setupDepends (PD.setupBuildInfo resolvedPkg) + ((/= thisPkgName) . dependencyName . fst) + ( map (\(x, y) -> (y, x)) $ + PD.enabledBuildDepends resolvedPkg compSpec + ) + ++ maybe [] (map (,Nothing) . PD.setupDepends) (PD.setupBuildInfo resolvedPkg) Left _ -> error "configuredPackageInvalidDeps internal error" diff --git a/cabal-install/src/Distribution/Client/GenBounds.hs b/cabal-install/src/Distribution/Client/GenBounds.hs index ae78b50c004..a5dfdd91f3c 100644 --- a/cabal-install/src/Distribution/Client/GenBounds.hs +++ b/cabal-install/src/Distribution/Client/GenBounds.hs @@ -39,9 +39,6 @@ import Distribution.Package , packageVersion , unPackageName ) -import Distribution.PackageDescription - ( enabledBuildDepends - ) import Distribution.PackageDescription.Configuration ( finalizePD ) @@ -67,6 +64,7 @@ import Distribution.Types.ComponentRequestedSpec ( defaultComponentRequestedSpec ) import Distribution.Types.Dependency +import Distribution.Types.PackageDescription import Distribution.Utils.Path (relativeSymbolicPath) import Distribution.Version ( LowerBound (..) @@ -138,7 +136,7 @@ genBounds verbosity packageDBs repoCtxt comp platform progdb globalFlags freezeF finalizePD mempty defaultComponentRequestedSpec - (const True) + (\_ _ -> True) platform cinfo [] @@ -147,8 +145,12 @@ genBounds verbosity packageDBs repoCtxt comp platform progdb globalFlags freezeF Left _ -> putStrLn "finalizePD failed" Right (pd, _) -> do let needBounds = - map depName $ - filter (not . hasUpperBound . depVersion) $ + -- TODO: This is not quite right for gen-bounds when private + -- dependencies are included: comparing package names is no longer + -- sufficient because some packages "duplicated" by also being + -- present within some private scope + map (depName . snd) $ + filter (not . hasUpperBound . depVersion . snd) $ enabledBuildDepends pd defaultComponentRequestedSpec pkgs <- @@ -177,10 +179,10 @@ genBounds verbosity packageDBs repoCtxt comp platform progdb globalFlags freezeF traverse_ (notice verbosity . (++ ",") . showBounds padTo) thePkgs depName :: Dependency -> String -depName (Dependency pn _ _) = unPackageName pn +depName = unPackageName . depPkgName depVersion :: Dependency -> VersionRange -depVersion (Dependency _ vr _) = vr +depVersion = depVerRange -- | The message printed when some dependencies are found to be lacking proper -- PVP-mandated bounds. diff --git a/cabal-install/src/Distribution/Client/Init/Utils.hs b/cabal-install/src/Distribution/Client/Init/Utils.hs index 12605a669a0..fd0868a3a5f 100644 --- a/cabal-install/src/Distribution/Client/Init/Utils.hs +++ b/cabal-install/src/Distribution/Client/Init/Utils.hs @@ -321,7 +321,7 @@ fixupDocFiles v pkgDesc mkStringyDep :: String -> Dependency mkStringyDep = mkPackageNameDep . mkPackageName -getBaseDep :: Interactive m => InstalledPackageIndex -> InitFlags -> m [Dependency] +getBaseDep :: Interactive m => InstalledPackageIndex -> InitFlags -> m [P.Dependency] getBaseDep pkgIx flags = retrieveDependencies silent diff --git a/cabal-install/src/Distribution/Client/Install.hs b/cabal-install/src/Distribution/Client/Install.hs index a31e4d2ce62..c780febbbe7 100644 --- a/cabal-install/src/Distribution/Client/Install.hs +++ b/cabal-install/src/Distribution/Client/Install.hs @@ -1661,7 +1661,7 @@ installReadyPackage CD.nonSetupDeps deps ] , configDependencies = - [ GivenComponent (packageName srcid) cname dep_ipid + [ GivenComponent (packageName srcid) cname dep_ipid Nothing | ConfiguredId srcid (Just (PackageDescription.CLibName cname)) dep_ipid <- CD.nonSetupDeps deps ] @@ -1677,7 +1677,7 @@ installReadyPackage pkg = case finalizePD flags (enableStanzas stanzas) - (const True) + (\_ _ -> True) platform cinfo [] diff --git a/cabal-install/src/Distribution/Client/InstallPlan.hs b/cabal-install/src/Distribution/Client/InstallPlan.hs index 46212baaccc..ffafbaf071b 100644 --- a/cabal-install/src/Distribution/Client/InstallPlan.hs +++ b/cabal-install/src/Distribution/Client/InstallPlan.hs @@ -630,7 +630,11 @@ configureInstallPlan configFlags solverPlan = -- NB: no support for executable dependencies } where - deps = fmap (concatMap (map configuredId . mapDep)) (solverPkgLibDeps spkg) + -- If the private alias of a given dependency matters to the configured + -- package deps we should instead add it to the datatype rather than + -- discarding it here. However, we probably only care about the + -- dependencies as a whole here (right?), so we simply discard the scope. + deps = fmap (concatMap (map configuredId . mapDep . fst)) (solverPkgLibDeps spkg) -- ------------------------------------------------------------ @@ -757,22 +761,23 @@ failed -> ([srcpkg], Processing) failed plan (Processing processingSet completedSet failedSet) pkgid = assert (pkgid `Set.member` processingSet) $ - assert (all (`Set.notMember` processingSet) (drop 1 newlyFailedIds)) $ - assert (all (`Set.notMember` completedSet) (drop 1 newlyFailedIds)) $ + assert (all (`Set.notMember` processingSet) newlyFailedIds) $ + assert (all (`Set.notMember` completedSet) newlyFailedIds) $ -- but note that some newlyFailed may already be in the failed set -- since one package can depend on two packages that both fail and -- so would be in the rev-dep closure for both. assert (processingInvariant plan processing') $ - ( map asConfiguredPackage (drop 1 newlyFailed) + ( map asConfiguredPackage newlyFailed , processing' ) where processingSet' = Set.delete pkgid processingSet - failedSet' = failedSet `Set.union` Set.fromList newlyFailedIds + failedSet' = failedSet `Set.union` Set.fromList newlyFailedIds `Set.union` Set.singleton pkgid newlyFailedIds = map nodeKey newlyFailed - newlyFailed = - fromMaybe (internalError "failed" "package not in graph") $ - Graph.revClosure (planGraph plan) [pkgid] + newlyFailed = case fromMaybe (internalError "failed" "package not in graph") $ + Graph.revClosure (planGraph plan) [pkgid] of + [] -> error "impossible" + _ : tail' -> tail' processing' = Processing processingSet' completedSet failedSet' asConfiguredPackage (Configured pkg) = pkg diff --git a/cabal-install/src/Distribution/Client/InstallSymlink.hs b/cabal-install/src/Distribution/Client/InstallSymlink.hs index 1701aa1f652..78f5fd0b613 100644 --- a/cabal-install/src/Distribution/Client/InstallSymlink.hs +++ b/cabal-install/src/Distribution/Client/InstallSymlink.hs @@ -205,7 +205,7 @@ symlinkBinaries case finalizePD flags (enableStanzas stanzas) - (const True) + (\_ _ -> True) platform cinfo [] diff --git a/cabal-install/src/Distribution/Client/List.hs b/cabal-install/src/Distribution/Client/List.hs index b03211038de..d8bfa969ba7 100644 --- a/cabal-install/src/Distribution/Client/List.hs +++ b/cabal-install/src/Distribution/Client/List.hs @@ -651,7 +651,8 @@ mergePackageInfo versionPref installedPkgs sourcePkgs selectedPkg showVer = source , dependencies = combine - ( map (SourceDependency . simplifyDependency) + -- We discard info (with `snd`) about private scopes because we don't yet report them in cabal list or cabal info (TODO). + ( map (SourceDependency . simplifyDependency . snd) . Source.allBuildDepends ) source diff --git a/cabal-install/src/Distribution/Client/ProjectConfig.hs b/cabal-install/src/Distribution/Client/ProjectConfig.hs index 5d04f101c7d..78a2669e5e2 100644 --- a/cabal-install/src/Distribution/Client/ProjectConfig.hs +++ b/cabal-install/src/Distribution/Client/ProjectConfig.hs @@ -1535,7 +1535,7 @@ readSourcePackageCabalFile verbosity pkgfilename content = unless (null warnings) $ info verbosity (formatWarnings warnings) return pkg - (warnings, Left (mspecVersion, errors)) -> + (warnings, Left (mspecVersion, errors)) -> do throwIO $ CabalFileParseError pkgfilename content errors mspecVersion warnings where formatWarnings warnings = diff --git a/cabal-install/src/Distribution/Client/ProjectOrchestration.hs b/cabal-install/src/Distribution/Client/ProjectOrchestration.hs index 2d963b0e07f..d17bbf4b3fe 100644 --- a/cabal-install/src/Distribution/Client/ProjectOrchestration.hs +++ b/cabal-install/src/Distribution/Client/ProjectOrchestration.hs @@ -1158,7 +1158,7 @@ writeBuildReports settings buildContext plan buildOutcomes = do Right br -> case buildResultTests br of TestsNotTried -> BuildReports.NotTried TestsOk -> BuildReports.Ok - in Just $ (BuildReports.BuildReport (packageId pkg) os arch (compilerId comp) cabalInstallID (elabFlagAssignment pkg) (map (packageId . fst) $ elabLibDependencies pkg) installOutcome docsOutcome testsOutcome, getRepo . elabPkgSourceLocation $ pkg) -- TODO handle failure log files? + in Just $ (BuildReports.BuildReport (packageId pkg) os arch (compilerId comp) cabalInstallID (elabFlagAssignment pkg) (map (packageId . (\(a, _, _) -> a)) $ elabLibDependencies pkg) installOutcome docsOutcome testsOutcome, getRepo . elabPkgSourceLocation $ pkg) -- TODO handle failure log files? fromPlanPackage _ _ = Nothing buildReports = mapMaybe (\x -> fromPlanPackage x (InstallPlan.lookupBuildOutcome x buildOutcomes)) $ InstallPlan.toList plan diff --git a/cabal-install/src/Distribution/Client/ProjectPlanOutput.hs b/cabal-install/src/Distribution/Client/ProjectPlanOutput.hs index d38f07037a6..4e0773484f8 100644 --- a/cabal-install/src/Distribution/Client/ProjectPlanOutput.hs +++ b/cabal-install/src/Distribution/Client/ProjectPlanOutput.hs @@ -199,7 +199,7 @@ encodePlanAsJson distDirLayout elaboratedInstallPlan elaboratedSharedConfig = J.object $ [ comp2str c J..= J.object - ( [ "depends" J..= map (jdisplay . confInstId) (map fst ldeps) + ( [ "depends" J..= map (jdisplay . confInstId) (map (\(p, _, _) -> p) ldeps) , "exe-depends" J..= map (jdisplay . confInstId) edeps ] ++ bin_file c @@ -212,7 +212,7 @@ encodePlanAsJson distDirLayout elaboratedInstallPlan elaboratedSharedConfig = ] in ["components" J..= components] ElabComponent comp -> - [ "depends" J..= map (jdisplay . confInstId) (map fst $ elabLibDependencies elab) + [ "depends" J..= map (jdisplay . confInstId) (map (\(p, _, _) -> p) $ elabLibDependencies elab) , "exe-depends" J..= map jdisplay (elabExeDependencies elab) , "component-name" J..= J.String (comp2str (compSolverName comp)) ] @@ -639,7 +639,7 @@ postBuildProjectStatus ] elabLibDeps :: ElaboratedConfiguredPackage -> [UnitId] - elabLibDeps = map (newSimpleUnitId . confInstId) . map fst . elabLibDependencies + elabLibDeps = map (newSimpleUnitId . confInstId) . map (\(p, _, _) -> p) . elabLibDependencies -- Was a build was attempted for this package? -- If it doesn't have both a build status and outcome then the answer is no. diff --git a/cabal-install/src/Distribution/Client/ProjectPlanning.hs b/cabal-install/src/Distribution/Client/ProjectPlanning.hs index 38a59b9818c..2b5d7d59fa6 100644 --- a/cabal-install/src/Distribution/Client/ProjectPlanning.hs +++ b/cabal-install/src/Distribution/Client/ProjectPlanning.hs @@ -6,7 +6,10 @@ {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE RecordWildCards #-} +{-# LANGUAGE TupleSections #-} {-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE ViewPatterns #-} +{-# LANGUAGE NoMonoLocalBinds #-} -- | -- /Elaborated: worked out with great care and nicety of detail; executed with great minuteness: elaborate preparations; elaborate care./ @@ -1711,12 +1714,10 @@ elaborateInstallPlan where compSolverName = CD.ComponentSetup compComponentName = Nothing - - dep_pkgs = elaborateLibSolverId mapDep =<< CD.setupDeps deps0 - + dep_pkgs = [(d', rn) | (d, rn) <- CD.setupDeps deps0, d' <- elaborateLibSolverId mapDep d] compLibDependencies = -- MP: No idea what this function does - map (\cid -> (configuredId cid, False)) dep_pkgs + map (\(cid, rn) -> (configuredId cid, False, rn)) dep_pkgs compLinkedLibDependencies = notImpl "compLinkedLibDependencies" compOrderLibDependencies = notImpl "compOrderLibDependencies" @@ -1766,7 +1767,7 @@ elaborateInstallPlan let do_ cid = let cid' = annotatedIdToConfiguredId . ci_ann_id $ cid - in (cid', False) -- filled in later in pruneInstallPlanPhase2) + in (cid', False, ci_alias cid) -- filled in later in pruneInstallPlanPhase2) -- 2. Read out the dependencies from the ConfiguredComponent cc0 let compLibDependencies = -- Nub because includes can show up multiple times @@ -1881,35 +1882,35 @@ elaborateInstallPlan external_lib_dep_sids = CD.select (== compSolverName) deps0 external_exe_dep_sids = CD.select (== compSolverName) exe_deps0 - external_lib_dep_pkgs = concatMap mapDep external_lib_dep_sids + external_exe_dep_sids_raw = [(sid, Nothing) | sid <- external_exe_dep_sids] -- Combine library and build-tool dependencies, for backwards -- compatibility (See issue #5412 and the documentation for -- InstallPlan.fromSolverInstallPlan), but prefer the versions -- specified as build-tools. external_exe_dep_pkgs = - concatMap mapDep $ - ordNubBy (pkgName . packageId) $ - external_exe_dep_sids ++ external_lib_dep_sids + [(d, alias) | (sid, alias) <- ordNubBy (pkgName . packageId . fst) $ external_exe_dep_sids_raw ++ external_lib_dep_sids, d <- mapDep sid] + + external_lib_dep_pkgs = [(d, alias) | (sid, alias) <- external_lib_dep_sids, d <- mapDep sid] external_exe_map = Map.fromList $ [ (getComponentId pkg, paths) - | pkg <- external_exe_dep_pkgs + | (pkg, _) <- external_exe_dep_pkgs , let paths = planPackageExePaths pkg ] exe_map1 = Map.union external_exe_map $ fmap (\x -> [x]) exe_map external_lib_cc_map = - Map.fromListWith Map.union $ - map mkCCMapping external_lib_dep_pkgs + Map.fromListWith Map.union (map mkCCMapping external_lib_dep_pkgs) external_exe_cc_map = Map.fromListWith Map.union $ map mkCCMapping external_exe_dep_pkgs external_lc_map = Map.fromList $ map mkShapeMapping $ - external_lib_dep_pkgs ++ concatMap mapDep external_exe_dep_sids + -- MP: TODO... should these aliases work here as well + (map fst external_lib_dep_pkgs ++ concatMap (mapDep . fst) external_exe_dep_sids_raw) compPkgConfigDependencies = [ ( pn @@ -2043,9 +2044,10 @@ elaborateInstallPlan filterExt' :: [(ConfiguredId, a)] -> [(ConfiguredId, a)] filterExt' = filter (isExt . fst) + filterExt'' = filter (isExt . (\(d, _, _) -> d)) pkgLibDependencies = - buildComponentDeps (filterExt' . compLibDependencies) + buildComponentDeps (filterExt'' . compLibDependencies) pkgExeDependencies = buildComponentDeps (filterExt . compExeDependencies) pkgExeDependencyPaths = @@ -2112,7 +2114,7 @@ elaborateInstallPlan elabPkgDescription = case PD.finalizePD flags elabEnabledSpec - (const True) + (\_ _ -> True) platform (compilerInfo compiler) [] @@ -2179,7 +2181,7 @@ elaborateInstallPlan elabSetupScriptStyle elabPkgDescription libDepGraph - deps0 + (fmap (map fst) deps0) elabSetupPackageDBStack = buildAndRegisterDbs elabInplaceBuildPackageDBStack = inplacePackageDbs @@ -2458,42 +2460,45 @@ matchElabPkg p elab = -- and 'ComponentName' to the 'ComponentId' that should be used -- in this case. mkCCMapping - :: ElaboratedPlanPackage - -> (PackageName, Map ComponentName (AnnotatedId ComponentId)) -mkCCMapping = - InstallPlan.foldPlanPackage - ( \ipkg -> - ( packageName ipkg - , Map.singleton - (ipiComponentName ipkg) - -- TODO: libify - ( AnnotatedId - { ann_id = IPI.installedComponentId ipkg - , ann_pid = packageId ipkg - , ann_cname = IPI.sourceComponentName ipkg - } + :: (ElaboratedPlanPackage, Maybe PrivateAlias) + -> ((PackageName, Maybe PrivateAlias), Map ComponentName ((AnnotatedId ComponentId))) +mkCCMapping (ep, alias) = foldpp ep + where + foldpp = + InstallPlan.foldPlanPackage + ( \ipkg -> + ( (packageName ipkg, alias) + , Map.singleton + (ipiComponentName ipkg) + -- TODO: libify + ( AnnotatedId + { ann_id = IPI.installedComponentId ipkg + , ann_pid = packageId ipkg + , ann_cname = IPI.sourceComponentName ipkg + } + ) ) ) - ) - $ \elab -> - let mk_aid cn = - AnnotatedId - { ann_id = elabComponentId elab - , ann_pid = packageId elab - , ann_cname = cn - } - in ( packageName elab - , case elabPkgOrComp elab of - ElabComponent comp -> - case compComponentName comp of - Nothing -> Map.empty - Just n -> Map.singleton n (mk_aid n) - ElabPackage _ -> - Map.fromList $ - map - (\comp -> let cn = Cabal.componentName comp in (cn, mk_aid cn)) - (Cabal.pkgBuildableComponents (elabPkgDescription elab)) - ) + $ \elab -> + let mk_aid cn = + ( AnnotatedId + { ann_id = elabComponentId elab + , ann_pid = packageId elab + , ann_cname = cn + } + ) + in ( (packageName elab, alias) + , case elabPkgOrComp elab of + ElabComponent comp -> + case compComponentName comp of + Nothing -> Map.empty + Just n -> Map.singleton n (mk_aid n) + ElabPackage _ -> + Map.fromList $ + map + (\comp -> let cn = Cabal.componentName comp in (cn, mk_aid cn)) + (Cabal.pkgBuildableComponents (elabPkgDescription elab)) + ) -- | Given an 'ElaboratedPlanPackage', generate the mapping from 'ComponentId' -- to the shape of this package, as per mix-in linking. @@ -3525,7 +3530,7 @@ pruneInstallPlanPass2 pkgs = where -- We initially assume that all the dependencies are external (hence the boolean is always -- False) and here we correct the dependencies so the right packages are marked promised. - addInternal (cid, _) = (cid, (cid `Set.member` inMemoryTargets)) + addInternal (cid, _, pn) = (cid, (cid `Set.member` inMemoryTargets), pn) libTargetsRequiredForRevDeps = [ c @@ -3694,7 +3699,7 @@ setupHsScriptOptions , usePackageIndex = Nothing , useDependencies = [ (uid, srcid) - | (ConfiguredId srcid (Just (CLibName LMainLibName)) uid, _) <- + | (ConfiguredId srcid (Just (CLibName LMainLibName)) uid, _, _) <- elabSetupDependencies elab ] , useDependenciesExclusive = True @@ -3906,14 +3911,14 @@ setupHsConfigureFlags -- enough info anyway) -- configDependencies = - [ cidToGivenComponent cid - | (cid, is_internal) <- elabLibDependencies elab + [ cidToGivenComponent alias cid + | (cid, is_internal, alias) <- elabLibDependencies elab , not is_internal ] configPromisedDependencies = - [ cidToGivenComponent cid - | (cid, is_internal) <- elabLibDependencies elab + [ cidToGivenComponent alias cid + | (cid, is_internal, alias) <- elabLibDependencies elab , is_internal ] @@ -3921,7 +3926,7 @@ setupHsConfigureFlags case elabPkgOrComp of ElabPackage _ -> [ thisPackageVersionConstraint srcid - | (ConfiguredId srcid _ _uid, _) <- elabLibDependencies elab + | (ConfiguredId srcid _ _uid, _, _) <- elabLibDependencies elab ] ElabComponent _ -> [] @@ -3944,8 +3949,8 @@ setupHsConfigureFlags configUseResponseFiles = mempty configAllowDependingOnPrivateLibs = Flag $ not $ libraryVisibilitySupported pkgConfigCompiler - cidToGivenComponent :: ConfiguredId -> GivenComponent - cidToGivenComponent (ConfiguredId srcid mb_cn cid) = GivenComponent (packageName srcid) ln cid + cidToGivenComponent :: Maybe PrivateAlias -> ConfiguredId -> GivenComponent + cidToGivenComponent alias (ConfiguredId srcid mb_cn cid) = GivenComponent (packageName srcid) ln cid alias where ln = case mb_cn of Just (CLibName lname) -> lname @@ -4208,7 +4213,7 @@ packageHashInputs ElabPackage (ElaboratedPackage{..}) -> Set.fromList $ [ confInstId dep - | (dep, _) <- CD.select relevantDeps pkgLibDependencies + | (dep, _, _) <- CD.select relevantDeps pkgLibDependencies ] ++ [ confInstId dep | dep <- CD.select relevantDeps pkgExeDependencies @@ -4217,7 +4222,7 @@ packageHashInputs Set.fromList ( map confInstId - ( map fst (compLibDependencies comp) + ( map (\(d, _, _) -> d) (compLibDependencies comp) ++ compExeDependencies comp ) ) diff --git a/cabal-install/src/Distribution/Client/ProjectPlanning/SetupPolicy.hs b/cabal-install/src/Distribution/Client/ProjectPlanning/SetupPolicy.hs index 212a5d93f81..bcde2e796f5 100644 --- a/cabal-install/src/Distribution/Client/ProjectPlanning/SetupPolicy.hs +++ b/cabal-install/src/Distribution/Client/ProjectPlanning/SetupPolicy.hs @@ -178,7 +178,7 @@ instance IsNode NonSetupLibDepSolverPlanPackage where nodeKey spkg nodeNeighbors (NonSetupLibDepSolverPlanPackage spkg) = - ordNub $ CD.nonSetupDeps (resolverPackageLibDeps spkg) + ordNub $ map fst (CD.nonSetupDeps (resolverPackageLibDeps spkg)) -- | Work out which version of the Cabal we will be using to talk to the -- Setup.hs interface for this package. diff --git a/cabal-install/src/Distribution/Client/ProjectPlanning/Types.hs b/cabal-install/src/Distribution/Client/ProjectPlanning/Types.hs index 5b4896b0568..ec505ca8b4a 100644 --- a/cabal-install/src/Distribution/Client/ProjectPlanning/Types.hs +++ b/cabal-install/src/Distribution/Client/ProjectPlanning/Types.hs @@ -179,7 +179,13 @@ showElaboratedInstallPlan = InstallPlan.showInstallPlan_gen showNode installed_deps = map pretty . nodeNeighbors - local_deps cfg = [(if internal then text "+" else mempty) <> pretty (confInstId uid) | (uid, internal) <- elabLibDependencies cfg] + local_deps cfg = + [ (if internal then text "+" else mempty) <> mpalias <> pretty (confInstId uid) + | (uid, internal, alias) <- elabLibDependencies cfg + , let mpalias = case alias of + Nothing -> mempty + Just al -> pretty al <> text "." + ] -- TODO: [code cleanup] decide if we really need this, there's not much in it, and in principle -- even platform and compiler could be different if we're building things @@ -569,13 +575,13 @@ elabOrderLibDependencies elab = ElabPackage pkg -> map (newSimpleUnitId . confInstId) $ ordNub $ - CD.flatDeps (map fst <$> pkgLibDependencies pkg) + CD.flatDeps (map (\(cid, _, _) -> cid) <$> pkgLibDependencies pkg) ElabComponent comp -> compOrderLibDependencies comp -- | The library dependencies (i.e., the libraries we depend on, NOT -- the dependencies of the library), NOT including setup dependencies. -- These are passed to the @Setup@ script via @--dependency@ or @--promised-dependency@. -elabLibDependencies :: ElaboratedConfiguredPackage -> [(ConfiguredId, Bool)] +elabLibDependencies :: ElaboratedConfiguredPackage -> [(ConfiguredId, Bool, Maybe PrivateAlias)] elabLibDependencies elab = case elabPkgOrComp elab of ElabPackage pkg -> ordNub (CD.nonSetupDeps (pkgLibDependencies pkg)) @@ -609,7 +615,7 @@ elabExeDependencyPaths elab = -- | The setup dependencies (the library dependencies of the setup executable; -- note that it is not legal for setup scripts to have executable -- dependencies at the moment.) -elabSetupDependencies :: ElaboratedConfiguredPackage -> [(ConfiguredId, Bool)] +elabSetupDependencies :: ElaboratedConfiguredPackage -> [(ConfiguredId, Bool, Maybe PrivateAlias)] elabSetupDependencies elab = case elabPkgOrComp elab of ElabPackage pkg -> CD.setupDeps (pkgLibDependencies pkg) @@ -669,7 +675,7 @@ data ElaboratedComponent = ElaboratedComponent , compComponentName :: Maybe ComponentName -- ^ The name of the component to be built. Nothing if -- it's a setup dep. - , compLibDependencies :: [(ConfiguredId, Bool)] + , compLibDependencies :: [(ConfiguredId, Bool, Maybe PrivateAlias)] -- ^ The *external* library dependencies of this component. We -- pass this to the configure script. The Bool indicates whether the -- dependency is a promised dependency (True) or not (False). @@ -716,7 +722,7 @@ compOrderExeDependencies = map (newSimpleUnitId . confInstId) . compExeDependenc data ElaboratedPackage = ElaboratedPackage { pkgInstalledId :: InstalledPackageId - , pkgLibDependencies :: ComponentDeps [(ConfiguredId, Bool)] + , pkgLibDependencies :: ComponentDeps [(ConfiguredId, Bool, Maybe PrivateAlias)] -- ^ The exact dependencies (on other plan packages) -- The boolean value indicates whether the dependency is a promised dependency -- or not. @@ -790,7 +796,7 @@ whyNotPerComponent = \case -- which can be useful in some circumstances. pkgOrderDependencies :: ElaboratedPackage -> ComponentDeps [UnitId] pkgOrderDependencies pkg = - fmap (map (newSimpleUnitId . confInstId)) (map fst <$> pkgLibDependencies pkg) + fmap (map (newSimpleUnitId . confInstId)) (map (\(cid, _, _) -> cid) <$> pkgLibDependencies pkg) `Mon.mappend` fmap (map (newSimpleUnitId . confInstId)) (pkgExeDependencies pkg) -- | This is used in the install plan to indicate how the package will be diff --git a/cabal-install/src/Distribution/Client/ScriptUtils.hs b/cabal-install/src/Distribution/Client/ScriptUtils.hs index aeae4eaf459..894356074df 100644 --- a/cabal-install/src/Distribution/Client/ScriptUtils.hs +++ b/cabal-install/src/Distribution/Client/ScriptUtils.hs @@ -102,7 +102,8 @@ import Distribution.Fields , readFields ) import Distribution.PackageDescription - ( ignoreConditions + ( Dependencies (..) + , ignoreConditions ) import Distribution.PackageDescription.FieldGrammar ( executableFieldGrammar @@ -472,10 +473,11 @@ updateContextAndWriteProjectFile ctx scriptPath scriptExecutable = do absScript <- unsafeMakeSymbolicPath . makeRelative (normalise projectRoot) <$> canonicalizePath scriptPath let + deps = Dependencies (targetBuildDepends $ buildInfo executable) (targetPrivateBuildDepends $ buildInfo executable) sourcePackage = fakeProjectSourcePackage projectRoot & lSrcpkgDescription . L.condExecutables - .~ [(scriptComponenetName scriptPath, CondNode executable (targetBuildDepends $ buildInfo executable) [])] + .~ [(scriptComponenetName scriptPath, CondNode executable deps [])] executable = scriptExecutable & L.modulePath .~ absScript diff --git a/cabal-install/src/Distribution/Client/Setup.hs b/cabal-install/src/Distribution/Client/Setup.hs index c89f2a3524a..499dfa82641 100644 --- a/cabal-install/src/Distribution/Client/Setup.hs +++ b/cabal-install/src/Distribution/Client/Setup.hs @@ -740,14 +740,15 @@ filterConfigureFlags' flags cabalLibVersion -- (public sublibraries), so we convert it to the legacy -- --dependency=pkg_or_internal_component=cid configDependencies = - let convertToLegacyInternalDep (GivenComponent _ (LSubLibName cn) cid) = + let convertToLegacyInternalDep (GivenComponent _ (LSubLibName cn) cid alias) = Just $ GivenComponent (unqualComponentNameToPackageName cn) LMainLibName cid - convertToLegacyInternalDep (GivenComponent pn LMainLibName cid) = - Just $ GivenComponent pn LMainLibName cid + alias + convertToLegacyInternalDep (GivenComponent pn LMainLibName cid alias) = + Just $ GivenComponent pn LMainLibName cid alias in catMaybes $ convertToLegacyInternalDep <$> configDependencies flags , -- Cabal < 2.5 doesn't know about '--allow-depending-on-private-libs'. configAllowDependingOnPrivateLibs = NoFlag diff --git a/cabal-install/src/Distribution/Client/SolverInstallPlan.hs b/cabal-install/src/Distribution/Client/SolverInstallPlan.hs index f4422080a4b..a0a8fcd0baa 100644 --- a/cabal-install/src/Distribution/Client/SolverInstallPlan.hs +++ b/cabal-install/src/Distribution/Client/SolverInstallPlan.hs @@ -60,6 +60,7 @@ import Distribution.Package , PackageId , PackageIdentifier (..) , PackageName + , PrivateAlias (..) , packageName , packageVersion ) @@ -81,6 +82,7 @@ import Distribution.Solver.Types.SolverPackage import Data.Array ((!)) import qualified Data.Foldable as Foldable import qualified Data.Graph as OldGraph +import qualified Data.List as List import qualified Data.Map as Map import Distribution.Compat.Graph (Graph, IsNode (..)) import qualified Distribution.Compat.Graph as Graph @@ -313,7 +315,7 @@ nonSetupClosure index pkgids0 = closure Graph.empty pkgids0 Nothing -> closure completed' pkgids' where completed' = Graph.insert pkg completed - pkgids' = CD.nonSetupDeps (resolverPackageLibDeps pkg) ++ pkgids + pkgids' = map fst (CD.nonSetupDeps (resolverPackageLibDeps pkg)) ++ pkgids -- | Compute the root sets of a plan -- @@ -349,7 +351,7 @@ libraryRoots index = setupRoots :: SolverPlanIndex -> [[SolverId]] setupRoots = filter (not . null) - . map (CD.setupDeps . resolverPackageLibDeps) + . map (map fst . CD.setupDeps . resolverPackageLibDeps) . Foldable.toList -- | Given a package index where we assume we want to use all the packages @@ -365,42 +367,56 @@ dependencyInconsistencies' :: SolverPlanIndex -> [(PackageName, [(PackageIdentifier, Version)])] dependencyInconsistencies' index = - [ (name, [(pid, packageVersion dep) | (dep, pids) <- uses, pid <- pids]) + [ (name, [(pid, packageVersion dep) | (dep, pids) <- map snd uses, pid <- pids]) | (name, ipid_map) <- Map.toList inverseIndex - , let uses = Map.elems ipid_map - , reallyIsInconsistent (map fst uses) + , let uses = Map.toAscList ipid_map -- We need a sorted list with (aliases, packages) (aliases before packages) to call groupBy on. + , any (reallyIsInconsistent . map (fst . snd)) $ + -- We group together all packages without a private alias, and those with + -- private aliases by its scope name AND the SolverId of the package + -- (because, across packages, there may exist scopes with the same name). + List.groupBy + ( \x y -> case (x, y) of + (((Nothing, _), _), (_, _)) -> False + ((_, _), ((Nothing, _), _)) -> False + (((aliasA, sidA), _), ((aliasB, sidB), _)) + | aliasA == aliasB -> + sidA == sidB + | otherwise -> + False + ) + uses ] where -- For each package name (of a dependency, somewhere) -- and each installed ID of that package -- the associated package instance - -- and a list of reverse dependencies (as source IDs) - inverseIndex :: Map PackageName (Map SolverId (SolverPlanPackage, [PackageId])) + -- and a list of reverse dependencies (as source IDs) and the possible private scope of each revdep + inverseIndex :: Map PackageName (Map (Maybe PrivateAlias, SolverId) (SolverPlanPackage, [PackageId])) inverseIndex = Map.fromListWith (Map.unionWith (\(a, b) (_, b') -> (a, b ++ b'))) - [ (packageName dep, Map.fromList [(sid, (dep, [packageId pkg]))]) + [ (packageName dep, Map.fromList [((palias, sid), (dep, [(packageId pkg)]))]) | -- For each package @pkg@ pkg <- Foldable.toList index , -- Find out which @sid@ @pkg@ depends on - sid <- CD.nonSetupDeps (resolverPackageLibDeps pkg) + (sid, palias) <- CD.nonSetupDeps (resolverPackageLibDeps pkg) , -- And look up those @sid@ (i.e., @sid@ is the ID of @dep@) Just dep <- [Graph.lookup sid index] ] -- If, in a single install plan, we depend on more than one version of a - -- package, then this is ONLY okay in the (rather special) case that we - -- depend on precisely two versions of that package, and one of them - -- depends on the other. This is necessary for example for the base where - -- we have base-3 depending on base-4. - reallyIsInconsistent :: [SolverPlanPackage] -> Bool + -- package in the same top-level or private scope, then this is ONLY okay + -- in the (rather special) case that we depend on precisely two versions of + -- that package, and one of them depends on the other. This is necessary + -- for example for the base where we have base-3 depending on base-4. + reallyIsInconsistent :: ([SolverPlanPackage]) -> Bool reallyIsInconsistent [] = False reallyIsInconsistent [_p] = False reallyIsInconsistent [p1, p2] = let pid1 = nodeKey p1 pid2 = nodeKey p2 - in pid1 `notElem` CD.nonSetupDeps (resolverPackageLibDeps p2) - && pid2 `notElem` CD.nonSetupDeps (resolverPackageLibDeps p1) + in pid1 `notElem` map fst (CD.nonSetupDeps (resolverPackageLibDeps p2)) + && pid2 `notElem` map fst (CD.nonSetupDeps (resolverPackageLibDeps p1)) reallyIsInconsistent _ = True -- | The graph of packages (nodes) and dependencies (edges) must be acyclic. diff --git a/cabal-install/src/Distribution/Client/Targets.hs b/cabal-install/src/Distribution/Client/Targets.hs index 1a37c9c73b9..afef8c30223 100644 --- a/cabal-install/src/Distribution/Client/Targets.hs +++ b/cabal-install/src/Distribution/Client/Targets.hs @@ -84,7 +84,8 @@ import Distribution.Types.PackageVersionConstraint ) import Distribution.PackageDescription - ( GenericPackageDescription + ( ComponentName + , GenericPackageDescription ) import Distribution.Simple.Utils ( dieWithException @@ -106,6 +107,8 @@ import qualified Data.Map as Map import Distribution.Client.Errors import qualified Distribution.Client.GZipUtils as GZipUtils import qualified Distribution.Compat.CharParsing as P +import Distribution.Solver.Types.ComponentDeps +import Distribution.Types.Dependency import Distribution.Utils.Path (makeSymbolicPath) import Network.URI ( URI (..) @@ -613,6 +616,7 @@ data UserQualifier UserQualSetup PackageName | -- | Executable dependency. UserQualExe PackageName PackageName + | UserQualComp PackageName ComponentName deriving (Eq, Show, Generic) instance Binary UserQualifier @@ -623,6 +627,7 @@ instance Structured UserQualifier data UserConstraintScope = -- | Scope that applies to the package when it has the specified qualifier. UserQualified UserQualifier PackageName + | UserPrivateQualifier PackageName PrivateAlias PackageName | -- | Scope that applies to the package when it has a setup qualifier. UserAnySetupQualifier PackageName | -- | Scope that applies to the package when it has any qualifier. @@ -632,14 +637,16 @@ data UserConstraintScope instance Binary UserConstraintScope instance Structured UserConstraintScope -fromUserQualifier :: UserQualifier -> Qualifier -fromUserQualifier UserQualToplevel = QualToplevel -fromUserQualifier (UserQualSetup name) = QualSetup name -fromUserQualifier (UserQualExe name1 name2) = QualExe name1 name2 +fromUserQualifier :: UserQualifier -> Namespace +fromUserQualifier UserQualToplevel = DefaultNamespace +fromUserQualifier (UserQualSetup pn) = IndependentComponent pn ComponentSetup +fromUserQualifier (UserQualExe pn bpn) = IndependentBuildTool pn bpn +fromUserQualifier (UserQualComp pn cn) = IndependentComponent pn (componentNameToComponent cn) fromUserConstraintScope :: UserConstraintScope -> ConstraintScope fromUserConstraintScope (UserQualified q pn) = - ScopeQualified (fromUserQualifier q) pn + ScopeQualified (fromUserQualifier q) QualToplevel pn +fromUserConstraintScope (UserPrivateQualifier pn alias cpn) = ScopePrivate pn alias cpn fromUserConstraintScope (UserAnySetupQualifier pn) = ScopeAnySetupQualifier pn fromUserConstraintScope (UserAnyQualifier pn) = ScopeAnyQualifier pn @@ -658,6 +665,7 @@ userConstraintPackageName (UserConstraint scope _) = scopePN scope scopePN (UserQualified _ pn) = pn scopePN (UserAnyQualifier pn) = pn scopePN (UserAnySetupQualifier pn) = pn + scopePN (UserPrivateQualifier _ _ pn) = pn userToPackageConstraint :: UserConstraint -> PackageConstraint userToPackageConstraint (UserConstraint scope prop) = @@ -706,10 +714,24 @@ instance Parsec UserConstraint where withDot pn | pn == mkPackageName "any" = UserAnyQualifier <$> parsec | pn == mkPackageName "setup" = UserAnySetupQualifier <$> parsec + | pn == mkPackageName "private" = do + qpn <- parsec + _ <- P.char '.' + alias <- parsec + _ <- P.char ':' + cpn <- parsec + return $ UserPrivateQualifier qpn alias cpn | otherwise = P.unexpected $ "constraint scope: " ++ unPackageName pn - withColon :: PackageName -> m UserConstraintScope - withColon pn = + withColon, setupQual, compQual :: PackageName -> m UserConstraintScope + withColon pn = setupQual pn <|> compQual pn + + compQual pn = do + comp_qual <- UserQualComp pn <$> parsec + void $ P.char '.' + UserQualified comp_qual <$> parsec + + setupQual pn = UserQualified (UserQualSetup pn) <$ P.string "setup." <*> parsec diff --git a/cabal-install/src/Distribution/Client/Types/ConfiguredPackage.hs b/cabal-install/src/Distribution/Client/Types/ConfiguredPackage.hs index 0b7d62e7e77..aefb7bee26f 100644 --- a/cabal-install/src/Distribution/Client/Types/ConfiguredPackage.hs +++ b/cabal-install/src/Distribution/Client/Types/ConfiguredPackage.hs @@ -41,7 +41,7 @@ data ConfiguredPackage loc = ConfiguredPackage , confPkgDeps :: CD.ComponentDeps [ConfiguredId] -- ^ set of exact dependencies (installed or source). -- - -- These must be consistent with the 'buildDepends' + -- These must be consistent with the 'buildDepends' and 'privateBuildDepends' -- in the 'PackageDescription' that you'd get by -- applying the flag assignment and optional stanzas. } diff --git a/cabal-install/tests/IntegrationTests2.hs b/cabal-install/tests/IntegrationTests2.hs index 6579b2ddcc2..cc955240fc7 100644 --- a/cabal-install/tests/IntegrationTests2.hs +++ b/cabal-install/tests/IntegrationTests2.hs @@ -468,7 +468,7 @@ testTargetSelectorAmbiguous reportSubCase = do condLibrary = Nothing, condSubLibraries = [], condForeignLibs = [], - condExecutables = [ ( exeName exe, CondNode exe [] [] ) + condExecutables = [ ( exeName exe, CondNode exe mempty [] ) | exe <- exes ], condTestSuites = [], condBenchmarks = [] diff --git a/cabal-install/tests/UnitTests.hs b/cabal-install/tests/UnitTests.hs index 8434f623e82..a7d94e93890 100644 --- a/cabal-install/tests/UnitTests.hs +++ b/cabal-install/tests/UnitTests.hs @@ -24,11 +24,12 @@ import qualified UnitTests.Distribution.Solver.Modular.RetryLog import qualified UnitTests.Distribution.Solver.Modular.Solver import qualified UnitTests.Distribution.Solver.Modular.WeightedPSQ import qualified UnitTests.Distribution.Solver.Types.OptionalStanza +import UnitTests.Options (extraOptions) main :: IO () main = do initTests <- UnitTests.Distribution.Client.Init.tests - defaultMain $ + defaultMainWithIngredients (includingOptions extraOptions : defaultIngredients) $ testGroup "Unit Tests" [ testGroup diff --git a/cabal-install/tests/UnitTests/Distribution/Client/DescribedInstances.hs b/cabal-install/tests/UnitTests/Distribution/Client/DescribedInstances.hs index 7e52d25173f..a1b34671a04 100644 --- a/cabal-install/tests/UnitTests/Distribution/Client/DescribedInstances.hs +++ b/cabal-install/tests/UnitTests/Distribution/Client/DescribedInstances.hs @@ -8,6 +8,7 @@ import Distribution.Client.Compat.Prelude import Data.List ((\\)) import Distribution.Described +import Distribution.Types.Dependency (PrivateAlias) import Distribution.Types.PackageId (PackageIdentifier) import Distribution.Types.PackageName (PackageName) import Distribution.Types.VersionRange (VersionRange) @@ -164,6 +165,7 @@ instance Described UserConstraint where REUnion [ "any." <> describePN , "setup." <> describePN + , "private." <> describePN <> "." <> describe (Proxy :: Proxy PrivateAlias) <> ":" <> describePN , describePN , describePN <> ":setup." <> describePN ] diff --git a/cabal-install/tests/UnitTests/Distribution/Client/Init/Utils.hs b/cabal-install/tests/UnitTests/Distribution/Client/Init/Utils.hs index e5ed0748a45..6991613a515 100644 --- a/cabal-install/tests/UnitTests/Distribution/Client/Init/Utils.hs +++ b/cabal-install/tests/UnitTests/Distribution/Client/Init/Utils.hs @@ -78,12 +78,12 @@ mkLicense :: SPDX.LicenseId -> SPDX.License mkLicense lid = SPDX.License (SPDX.ELicense (SPDX.ELicenseId lid) Nothing) mangleBaseDep :: a -> (a -> [Dependency]) -> [Dependency] -mangleBaseDep target f = - [ if unPackageName x == "base" - then Dependency x anyVersion z - else dep - | dep@(Dependency x _ z) <- f target - ] +mangleBaseDep target f = map go (f target) + where + go dep@(Dependency x _ z) = + if unPackageName x == "base" + then Dependency x anyVersion z + else dep infix 1 @?!, @!? diff --git a/cabal-install/tests/UnitTests/Distribution/Solver/Modular/DSL.hs b/cabal-install/tests/UnitTests/Distribution/Solver/Modular/DSL.hs index 991c5cafa0e..bc9bbc14d04 100644 --- a/cabal-install/tests/UnitTests/Distribution/Solver/Modular/DSL.hs +++ b/cabal-install/tests/UnitTests/Distribution/Solver/Modular/DSL.hs @@ -1,11 +1,12 @@ {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE ScopedTypeVariables #-} -- | DSL for testing the modular solver module UnitTests.Distribution.Solver.Modular.DSL - ( ExampleDependency (..) + ( ExampleDependency (.., ExAny, ExFix, ExRange, ExSubLibAny, ExSubLibFix, ExFixPriv, ExAnyPriv) , Dependencies (..) , ExSubLib (..) , ExTest (..) @@ -140,6 +141,7 @@ import Distribution.Solver.Types.Variable -------------------------------------------------------------------------------} type ExamplePkgName = String +type ExamplePrivateAlias = String type ExamplePkgVersion = Int type ExamplePkgHash = String -- for example "installed" packages type ExampleFlagName = String @@ -181,18 +183,36 @@ publicDependencies = mempty{depsVisibility = C.LibraryVisibilityPublic} unbuildableDependencies :: Dependencies unbuildableDependencies = mempty{depsIsBuildable = False} +pattern ExAny :: ExamplePkgName -> ExampleDependency +pattern ExAny p = ExAnyD Nothing p +pattern ExFix :: ExamplePkgName -> ExamplePkgVersion -> ExampleDependency +pattern ExFix p v = ExFixD Nothing p v +pattern ExRange :: ExamplePkgName -> ExamplePkgVersion -> ExamplePkgVersion -> ExampleDependency +pattern ExRange p v1 v2 = ExRangeD Nothing p v1 v2 + +pattern ExSubLibAny :: ExamplePkgName -> ExampleSubLibName -> ExampleDependency +pattern ExSubLibAny e l = ExSubLibAnyD Nothing e l + +pattern ExSubLibFix :: ExamplePkgName -> ExampleSubLibName -> ExamplePkgVersion -> ExampleDependency +pattern ExSubLibFix e l v = ExSubLibFixD Nothing e l v + +pattern ExAnyPriv :: ExamplePrivateAlias -> ExamplePkgName -> ExampleDependency +pattern ExAnyPriv alias p = ExAnyD (Just alias) p +pattern ExFixPriv :: ExamplePrivateAlias -> ExamplePkgName -> ExamplePkgVersion -> ExampleDependency +pattern ExFixPriv alias p v = ExFixD (Just alias) p v + data ExampleDependency = -- | Simple dependency on any version - ExAny ExamplePkgName + ExAnyD (Maybe ExamplePrivateAlias) ExamplePkgName | -- | Simple dependency on a fixed version - ExFix ExamplePkgName ExamplePkgVersion + ExFixD (Maybe ExamplePrivateAlias) ExamplePkgName ExamplePkgVersion | -- | Simple dependency on a range of versions, with an inclusive lower bound -- and an exclusive upper bound. - ExRange ExamplePkgName ExamplePkgVersion ExamplePkgVersion + ExRangeD (Maybe ExamplePrivateAlias) ExamplePkgName ExamplePkgVersion ExamplePkgVersion | -- | Sub-library dependency - ExSubLibAny ExamplePkgName ExampleSubLibName + ExSubLibAnyD (Maybe ExamplePrivateAlias) ExamplePkgName ExampleSubLibName | -- | Sub-library dependency on a fixed version - ExSubLibFix ExamplePkgName ExampleSubLibName ExamplePkgVersion + ExSubLibFixD (Maybe ExamplePrivateAlias) ExamplePkgName ExampleSubLibName ExamplePkgVersion | -- | Build-tool-depends dependency ExBuildToolAny ExamplePkgName ExampleExeName | -- | Build-tool-depends dependency on a fixed version @@ -272,13 +292,12 @@ data ExampleQualifier = QualNone | QualIndep ExamplePkgName | QualSetup ExamplePkgName - | -- The two package names are the build target and the package containing the - -- setup script. - QualIndepSetup ExamplePkgName ExamplePkgName | -- The two package names are the package depending on the exe and the -- package containing the exe. QualExe ExamplePkgName ExamplePkgName +-- TODO: Add QualPrivateAlias? + -- | Whether to enable tests in all packages in a test case. newtype EnableAllTests = EnableAllTests Bool deriving (BooleanFlag) @@ -390,9 +409,9 @@ exInst pn v hash deps = ExInst pn v hash (map exInstHash deps) -- these packages. type ExampleDb = [Either ExampleInstalled ExampleAvailable] -type DependencyTree a = C.CondTree C.ConfVar [C.Dependency] a +type DependencyTree a = C.CondTree C.ConfVar C.Dependencies a -type DependencyComponent a = C.CondBranch C.ConfVar [C.Dependency] a +type DependencyComponent a = C.CondBranch C.ConfVar C.Dependencies a exDbPkgs :: ExampleDb -> [ExamplePkgName] exDbPkgs = map (either exInstName exAvName) @@ -589,11 +608,11 @@ exAvSrcPkg ex = extractFlags deps = concatMap go (depsExampleDependencies deps) where go :: ExampleDependency -> [ExampleFlagName] - go (ExAny _) = [] - go (ExFix _ _) = [] - go (ExRange _ _ _) = [] - go (ExSubLibAny _ _) = [] - go (ExSubLibFix _ _ _) = [] + go (ExAnyD{}) = [] + go (ExFixD{}) = [] + go (ExRangeD{}) = [] + go (ExSubLibAnyD{}) = [] + go (ExSubLibFixD{}) = [] go (ExBuildToolAny _ _) = [] go (ExBuildToolFix _ _ _) = [] go (ExLegacyBuildToolAny _) = [] @@ -622,7 +641,8 @@ exAvSrcPkg ex = mkCondTree :: (C.LibraryVisibility -> C.BuildInfo -> a) -> Dependencies -> DependencyTree a mkCondTree mkComponent deps = let (libraryDeps, exts, mlang, pcpkgs, buildTools, legacyBuildTools) = splitTopLevel (depsExampleDependencies deps) - (directDeps, flaggedDeps) = splitDeps libraryDeps + (allDirectDeps, flaggedDeps) = splitDeps libraryDeps + (privateDeps, directDeps) = partition (\(_, _, _, is_private) -> isJust is_private) allDirectDeps component = mkComponent (depsVisibility deps) bi bi = mempty @@ -649,12 +669,20 @@ exAvSrcPkg ex = , -- TODO: Arguably, build-tools dependencies should also -- effect constraints on conditional tree. But no way to -- distinguish between them - C.condTreeConstraints = map mkDirect directDeps + C.condTreeConstraints = + mempty + { C.publicDependencies = map mkDirect directDeps + , C.privateDependencies = map mkDirectD privateDeps + } , C.condTreeComponents = map (mkFlagged mkComponent) flaggedDeps } - mkDirect :: (ExamplePkgName, C.LibraryName, C.VersionRange) -> C.Dependency - mkDirect (dep, name, vr) = C.Dependency (C.mkPackageName dep) vr (NonEmptySet.singleton name) + mkDirect :: (ExamplePkgName, C.LibraryName, C.VersionRange, Maybe ExamplePrivateAlias) -> C.Dependency + mkDirect (dep, name, vr, _) = C.Dependency (C.mkPackageName dep) vr (NonEmptySet.singleton name) + + mkDirectD :: (ExamplePkgName, C.LibraryName, C.VersionRange, Maybe ExamplePrivateAlias) -> C.PrivateDependency + mkDirectD (dep, name, vr, Just alias) = C.PrivateDependency (C.PrivateAlias (fromString alias)) [C.Dependency (C.mkPackageName dep) vr (NonEmptySet.singleton name)] + mkDirectD (_, _, _, Nothing) = error "mkDirectD: private deps are never Nothing since we partition them by 'isJust' above" mkFlagged :: (C.LibraryVisibility -> C.BuildInfo -> a) @@ -673,26 +701,26 @@ exAvSrcPkg ex = -- guarded by a flag. splitDeps :: [ExampleDependency] - -> ( [(ExamplePkgName, C.LibraryName, C.VersionRange)] + -> ( [(ExamplePkgName, C.LibraryName, C.VersionRange, Maybe ExamplePrivateAlias)] , [(ExampleFlagName, Dependencies, Dependencies)] ) splitDeps [] = ([], []) - splitDeps (ExAny p : deps) = + splitDeps (ExAnyD is_priv p : deps) = let (directDeps, flaggedDeps) = splitDeps deps - in ((p, C.LMainLibName, C.anyVersion) : directDeps, flaggedDeps) - splitDeps (ExFix p v : deps) = + in ((p, C.LMainLibName, C.anyVersion, is_priv) : directDeps, flaggedDeps) + splitDeps (ExFixD is_priv p v : deps) = let (directDeps, flaggedDeps) = splitDeps deps - in ((p, C.LMainLibName, C.thisVersion $ mkSimpleVersion v) : directDeps, flaggedDeps) - splitDeps (ExRange p v1 v2 : deps) = + in ((p, C.LMainLibName, C.thisVersion $ mkSimpleVersion v, is_priv) : directDeps, flaggedDeps) + splitDeps (ExRangeD is_priv p v1 v2 : deps) = let (directDeps, flaggedDeps) = splitDeps deps - in ((p, C.LMainLibName, mkVersionRange v1 v2) : directDeps, flaggedDeps) - splitDeps (ExSubLibAny p lib : deps) = + in ((p, C.LMainLibName, mkVersionRange v1 v2, is_priv) : directDeps, flaggedDeps) + splitDeps (ExSubLibAnyD is_priv p lib : deps) = let (directDeps, flaggedDeps) = splitDeps deps - in ((p, C.LSubLibName (C.mkUnqualComponentName lib), C.anyVersion) : directDeps, flaggedDeps) - splitDeps (ExSubLibFix p lib v : deps) = + in ((p, C.LSubLibName (C.mkUnqualComponentName lib), C.anyVersion, is_priv) : directDeps, flaggedDeps) + splitDeps (ExSubLibFixD is_priv p lib v : deps) = let (directDeps, flaggedDeps) = splitDeps deps - in ((p, C.LSubLibName (C.mkUnqualComponentName lib), C.thisVersion $ mkSimpleVersion v) : directDeps, flaggedDeps) + in ((p, C.LSubLibName (C.mkUnqualComponentName lib), C.thisVersion $ mkSimpleVersion v, is_priv) : directDeps, flaggedDeps) splitDeps (ExFlagged f a b : deps) = let (directDeps, flaggedDeps) = splitDeps deps in (directDeps, (f, a, b) : flaggedDeps) @@ -702,7 +730,10 @@ exAvSrcPkg ex = mkSetupDeps :: [ExampleDependency] -> [C.Dependency] mkSetupDeps deps = case splitDeps deps of - (directDeps, []) -> map mkDirect directDeps + (directDeps, []) -> + if any (\(_, _, _, p) -> isJust p) directDeps + then error "mkSetupDeps: custom setup has private deps" + else map mkDirect directDeps _ -> error "mkSetupDeps: custom setup has non-simple deps" -- Check for `UnknownLanguages` and `UnknownExtensions`. See @@ -844,7 +875,7 @@ exResolve fmap ( \p -> PackageConstraint - (scopeToplevel (C.mkPackageName p)) + (ScopeAnyQualifier (C.mkPackageName p)) (PackagePropertyStanzas [TestStanzas]) ) (exDbPkgs db) diff --git a/cabal-install/tests/UnitTests/Distribution/Solver/Modular/DSL/TestCaseUtils.hs b/cabal-install/tests/UnitTests/Distribution/Solver/Modular/DSL/TestCaseUtils.hs index 91ec541f976..6bec16ea5e1 100644 --- a/cabal-install/tests/UnitTests/Distribution/Solver/Modular/DSL/TestCaseUtils.hs +++ b/cabal-install/tests/UnitTests/Distribution/Solver/Modular/DSL/TestCaseUtils.hs @@ -18,6 +18,7 @@ module UnitTests.Distribution.Solver.Modular.DSL.TestCaseUtils , preferences , setVerbose , enableAllTests + , solverResult , solverSuccess , solverFailure , anySolverFailure @@ -46,6 +47,7 @@ import Language.Haskell.Extension (Extension (..), Language (..)) -- cabal-install import Distribution.Client.Dependency (foldProgress) +import qualified Distribution.Solver.Types.ComponentDeps as C import qualified Distribution.Solver.Types.PackagePath as P import Distribution.Solver.Types.PkgConfigDb (PkgConfigDb (..), pkgConfigDbFromList) import Distribution.Solver.Types.Settings @@ -144,6 +146,9 @@ data SolverResult = SolverResult -- the given plan. } +solverResult :: ([String] -> Bool) -> [(String, Int)] -> SolverResult +solverResult slog r = SolverResult slog (Right r) + solverSuccess :: [(String, Int)] -> SolverResult solverSuccess = SolverResult (const True) . Right @@ -314,13 +319,9 @@ runTest SolverTest{..} = askOption $ \(OptionShowSolverLog showSolverLog) -> P.QualToplevel QualSetup s -> P.PackagePath - P.DefaultNamespace - (P.QualSetup (C.mkPackageName s)) - QualIndepSetup p s -> - P.PackagePath - (P.Independent $ C.mkPackageName p) - (P.QualSetup (C.mkPackageName s)) + (P.IndependentComponent (C.mkPackageName s) C.ComponentSetup) + (P.QualToplevel) QualExe p1 p2 -> P.PackagePath - P.DefaultNamespace - (P.QualExe (C.mkPackageName p1) (C.mkPackageName p2)) + (P.IndependentBuildTool (C.mkPackageName p1) (C.mkPackageName p2)) + P.QualToplevel diff --git a/cabal-install/tests/UnitTests/Distribution/Solver/Modular/QuickCheck.hs b/cabal-install/tests/UnitTests/Distribution/Solver/Modular/QuickCheck.hs index 114db775f21..7fcd6107ddf 100644 --- a/cabal-install/tests/UnitTests/Distribution/Solver/Modular/QuickCheck.hs +++ b/cabal-install/tests/UnitTests/Distribution/Solver/Modular/QuickCheck.hs @@ -24,6 +24,8 @@ import Distribution.Utils.ShortText (ShortText) import Distribution.Client.Setup (defaultMaxBackjumps) +import Distribution.ModuleName +import Distribution.Types.Dependency (PrivateAlias (..)) import Distribution.Types.LibraryVisibility import Distribution.Types.PackageName import Distribution.Types.UnqualComponentName @@ -34,6 +36,7 @@ import Distribution.Solver.Types.ComponentDeps , ComponentDeps ) import qualified Distribution.Solver.Types.ComponentDeps as CD +import qualified Distribution.Solver.Types.ComponentDeps as P import Distribution.Solver.Types.OptionalStanza import Distribution.Solver.Types.PackageConstraint import qualified Distribution.Solver.Types.PackagePath as P @@ -75,7 +78,8 @@ tests = ReverseOrder -> reverse targets in counterexample (showResults r1 r2) $ noneReachedBackjumpLimit [r1, r2] ==> - isRight (resultPlan r1) === isRight (resultPlan r2) + isRight (resultPlan r1) + === isRight (resultPlan r2) , testPropertyWithSeed "solvable without --independent-goals => solvable with --independent-goals" $ \test reorderGoals -> @@ -92,7 +96,8 @@ tests = Nothing in counterexample (showResults r1 r2) $ noneReachedBackjumpLimit [r1, r2] ==> - isRight (resultPlan r1) `implies` isRight (resultPlan r2) + isRight (resultPlan r1) + `implies` isRight (resultPlan r2) , testPropertyWithSeed "backjumping does not affect solvability" $ \test reorderGoals indepGoals -> let r1 = solve' (EnableBackjumping True) test @@ -108,7 +113,8 @@ tests = Nothing in counterexample (showResults r1 r2) $ noneReachedBackjumpLimit [r1, r2] ==> - isRight (resultPlan r1) === isRight (resultPlan r2) + isRight (resultPlan r1) + === isRight (resultPlan r2) , testPropertyWithSeed "fine-grained conflicts does not affect solvability" $ \test reorderGoals indepGoals -> let r1 = solve' (FineGrainedConflicts True) test @@ -124,7 +130,8 @@ tests = Nothing in counterexample (showResults r1 r2) $ noneReachedBackjumpLimit [r1, r2] ==> - isRight (resultPlan r1) === isRight (resultPlan r2) + isRight (resultPlan r1) + === isRight (resultPlan r2) , testPropertyWithSeed "prefer oldest does not affect solvability" $ \test reorderGoals indepGoals -> let r1 = solve' (PreferOldest True) test @@ -140,7 +147,8 @@ tests = Nothing in counterexample (showResults r1 r2) $ noneReachedBackjumpLimit [r1, r2] ==> - isRight (resultPlan r1) === isRight (resultPlan r2) + isRight (resultPlan r1) + === isRight (resultPlan r2) , -- The next two tests use --no-count-conflicts, because the goal order used -- with --count-conflicts depends on the total set of conflicts seen by the -- solver. The solver explores more of the tree and encounters more @@ -165,7 +173,8 @@ tests = Nothing in counterexample (showResults r1 r2) $ noneReachedBackjumpLimit [r1, r2] ==> - resultPlan r1 === resultPlan r2 + resultPlan r1 + === resultPlan r2 , testPropertyWithSeed "fine-grained conflicts does not affect the result (with static goal order)" $ \test reorderGoals indepGoals -> @@ -182,7 +191,8 @@ tests = Nothing in counterexample (showResults r1 r2) $ noneReachedBackjumpLimit [r1, r2] ==> - resultPlan r1 === resultPlan r2 + resultPlan r1 + === resultPlan r2 ] where noneReachedBackjumpLimit :: [Result] -> Bool @@ -612,10 +622,14 @@ instance Hashable a => Hashable (P.Qualified a) instance Hashable P.PackagePath instance Hashable P.Qualifier instance Hashable P.Namespace +instance Hashable P.Component +instance Hashable UnqualComponentName instance Hashable OptionalStanza instance Hashable FlagName instance Hashable PackageName instance Hashable ShortText +instance Hashable ModuleName +instance Hashable PrivateAlias deriving instance Generic (Variable pn) deriving instance Generic (P.Qualified a) diff --git a/cabal-install/tests/UnitTests/Distribution/Solver/Modular/Solver.hs b/cabal-install/tests/UnitTests/Distribution/Solver/Modular/Solver.hs index a1f5eed3c62..bed7ead4f13 100644 --- a/cabal-install/tests/UnitTests/Distribution/Solver/Modular/Solver.hs +++ b/cabal-install/tests/UnitTests/Distribution/Solver/Modular/Solver.hs @@ -23,6 +23,8 @@ import Language.Haskell.Extension ) -- cabal-install + +import qualified Distribution.Solver.Types.ComponentDeps as P import Distribution.Solver.Types.Flag import Distribution.Solver.Types.OptionalStanza import Distribution.Solver.Types.PackageConstraint @@ -92,7 +94,7 @@ tests = , testGroup "Qualified manual flag constraints" [ let name = "Top-level flag constraint does not constrain setup dep's flag" - cs = [ExFlagConstraint (ScopeQualified P.QualToplevel "B") "flag" False] + cs = [ExFlagConstraint (ScopeQualified P.DefaultNamespace P.QualToplevel "B") "flag" False] in runTest $ constraints cs $ mkTest dbSetupDepWithManualFlag name ["A"] $ @@ -105,7 +107,7 @@ tests = ] , let name = "Solver can toggle setup dep's flag to match top-level constraint" cs = - [ ExFlagConstraint (ScopeQualified P.QualToplevel "B") "flag" False + [ ExFlagConstraint (ScopeQualified P.DefaultNamespace P.QualToplevel "B") "flag" False , ExVersionConstraint (ScopeAnyQualifier "b-2-true-dep") V.noVersion ] in runTest $ @@ -120,8 +122,8 @@ tests = ] , let name = "User can constrain flags separately with qualified constraints" cs = - [ ExFlagConstraint (ScopeQualified P.QualToplevel "B") "flag" True - , ExFlagConstraint (ScopeQualified (P.QualSetup "A") "B") "flag" False + [ ExFlagConstraint (ScopeQualified P.DefaultNamespace P.QualToplevel "B") "flag" True + , ExFlagConstraint (ScopeQualified (P.IndependentComponent "A" P.ComponentSetup) P.QualToplevel "B") "flag" False ] in runTest $ constraints cs $ @@ -135,15 +137,15 @@ tests = ] , -- Regression test for #4299 let name = "Solver can link deps when only one has constrained manual flag" - cs = [ExFlagConstraint (ScopeQualified P.QualToplevel "B") "flag" False] + cs = [ExFlagConstraint (ScopeQualified P.DefaultNamespace P.QualToplevel "B") "flag" False] in runTest $ constraints cs $ mkTest dbLinkedSetupDepWithManualFlag name ["A"] $ solverSuccess [("A", 1), ("B", 1), ("b-1-false-dep", 1)] , let name = "Solver cannot link deps that have conflicting manual flag constraints" cs = - [ ExFlagConstraint (ScopeQualified P.QualToplevel "B") "flag" True - , ExFlagConstraint (ScopeQualified (P.QualSetup "A") "B") "flag" False + [ ExFlagConstraint (ScopeQualified P.DefaultNamespace P.QualToplevel "B") "flag" True + , ExFlagConstraint (ScopeQualified (P.IndependentComponent "A" P.ComponentSetup) P.QualToplevel "B") "flag" False ] failureReason = "(constraint from unknown source requires opposite flag selection)" checkFullLog lns = @@ -279,8 +281,8 @@ tests = mkTest dbConstraints "force older versions with unqualified constraint" ["A", "B", "C"] $ solverSuccess [("A", 1), ("B", 2), ("C", 3), ("D", 1), ("D", 2), ("D", 3)] , let cs = - [ ExVersionConstraint (ScopeQualified P.QualToplevel "D") $ mkVersionRange 1 4 - , ExVersionConstraint (ScopeQualified (P.QualSetup "B") "D") $ mkVersionRange 4 7 + [ ExVersionConstraint (ScopeQualified P.DefaultNamespace P.QualToplevel "D") $ mkVersionRange 1 4 + , ExVersionConstraint (ScopeQualified (P.IndependentComponent "B" P.ComponentSetup) P.QualToplevel "D") $ mkVersionRange 4 7 ] in runTest $ constraints cs $ @@ -363,7 +365,7 @@ tests = , runTest $ testIndepGoals5 "indepGoals5 - default goal order" DefaultGoalOrder , runTest $ testIndepGoals6 "indepGoals6 - fixed goal order" FixedGoalOrder , runTest $ testIndepGoals6 "indepGoals6 - default goal order" DefaultGoalOrder - , expectFailBecause "#9466" $ runTest $ testIndepGoals7 "indepGoals7" + , runTest $ testIndepGoals7 "indepGoals7" , runTest $ testIndepGoals8 "indepGoals8" ] , -- Tests designed for the backjumping blog post @@ -517,6 +519,7 @@ tests = ++ "[__1] rejecting: H:bt-pkg:exe.bt-pkg-2.0.0 (conflict: H => H:bt-pkg:exe.bt-pkg (exe exe1)==3.0.0)" , runTest $ chooseExeAfterBuildToolsPackage True "choose exe after choosing its package - success" , runTest $ chooseExeAfterBuildToolsPackage False "choose exe after choosing its package - failure" + , runTest $ needTwoBuildToolPkgVersions "needs two build-tool-pkg versions" , runTest $ rejectInstalledBuildToolPackage "reject installed package for build-tool dependency" , runTest $ requireConsistentBuildToolVersions "build tool versions must be consistent within one package" ] @@ -859,6 +862,26 @@ tests = SolverResult (isInfixOf msg) $ Right [("A", 1), ("B", 1)] ] + , testGroup + "Private dependencies" + [ runTest privDep1 + , runTest privDep2 + , runTest privDep3 + , runTest privDep4 + , runTest privDep5 + , runTest privDep6 + , runTest privDep7 + , runTest privDep7a + , runTest privDep8 + , runTest privDep8a + , runTest privDep9 + , runTest privDep10 + , runTest privDep11 + , runTest privDep12 + , runTest privDep13 + , runTest privDep14 + , runTest privDep15 + ] , -- Tests for the contents of the solver's log testGroup "Solver log" @@ -2366,6 +2389,20 @@ dbBuildTools = , Right $ exAv "bt-pkg" 1 [] ] +needTwoBuildToolPkgVersions :: String -> SolverTest +needTwoBuildToolPkgVersions name = setVerbose $ mkTest db name ["A"] (solverSuccess [("A", 1), ("build-tool-pkg", 1), ("build-tool-pkg", 2)]) + where + db :: ExampleDb + db = + [ Right $ exAv "build-tool-pkg" 1 [] `withExe` exExe "build-tool-exe" [] + , Right $ exAv "build-tool-pkg" 2 [] `withExe` exExe "build-tool-exe" [] + , Right $ + exAvNoLibrary "A" 1 + `withExe` exExe + "my-exe" + [ExFix "build-tool-pkg" 1, ExBuildToolFix "build-tool-pkg" "build-tool-exe" 2] + ] + -- The solver should never choose an installed package for a build tool -- dependency. rejectInstalledBuildToolPackage :: String -> SolverTest @@ -2583,6 +2620,232 @@ setupStanzaTest2 = ["A"] (solverFailure ("unknown package: A:setup.C (dependency of A:setup.B *test)" `isInfixOf`)) +-- +-- Private Dependency tests + +-- Test 1: A and B can choose different versions of C because C is a private dependency of A +priv_db1 :: ExampleDb +priv_db1 = + [ Left $ exInst "C" 1 "C-1" [] + , Left $ exInst "C" 2 "C-2" [] + , Right $ exAv "A" 1 [ExFixPriv "G0" "C" 1] + , Right $ exAv "B" 1 [ExFix "C" 2] + , Right $ exAv "D" 1 [ExAny "A", ExAny "B"] + ] + +privDep1 :: SolverTest +privDep1 = setVerbose $ mkTest priv_db1 "private-dependencies-1" ["D"] (solverSuccess [("A", 1), ("B", 1), ("D", 1)]) + +-- Test 2: A depends on both C publically and privately, directly +priv_db2 :: ExampleDb +priv_db2 = + [ Left $ exInst "C" 1 "C-1" [] + , Right $ exAv "A" 1 [ExFix "C" 1, ExFixPriv "G0" "C" 1] + ] + +privDep2 :: SolverTest +privDep2 = setVerbose $ mkTest priv_db2 "private-dependencies-2" ["A"] (solverSuccess [("A", 1)]) + +-- Test 3: A depends on both C publically and privately, transitively +priv_db3 :: ExampleDb +priv_db3 = + [ Left $ exInst "C" 1 "C-1" [] + , Right $ exAv "D" 1 [ExFix "C" 1] + , Right $ exAv "A" 1 [ExFix "D" 1, ExFixPriv "G0" "C" 1] + ] + +privDep3 :: SolverTest +privDep3 = setVerbose $ mkTest priv_db3 "private-dependencies-3" ["A"] (solverSuccess [("A", 1), ("D", 1)]) + +-- Test 4: Private dependency do not apply transitively, so we fail because the +-- version of E must match +priv_db4 :: ExampleDb +priv_db4 = + [ Left $ exInst "E" 1 "E-1" [] + , Left $ exInst "E" 2 "E-2" [] + , Right $ exAv "C" 1 [ExFix "E" 1] + , Right $ exAv "C" 2 [ExFix "E" 2] + , Right $ exAv "A" 1 [ExFixPriv "G0" "C" 1] + , Right $ exAv "B" 1 [ExFix "C" 2] + , Right $ exAv "D" 1 [ExAny "A", ExAny "B"] + ] + +privDep4 :: SolverTest +privDep4 = setVerbose $ mkTest priv_db4 "private-dependencies-4" ["D"] (solverFailure ("(conflict: E==2.0.0/installed-2, A:G0.C => E==1.0.0)" `isInfixOf`)) + +-- Test 5: Private dependencies and setup dependencies can choose different versions + +priv_db5 :: ExampleDb +priv_db5 = + [ Left $ exInst "E" 1 "E-1" [] + , Left $ exInst "E" 2 "E-2" [] + , Right $ exAv "A" 1 [ExFixPriv "G0" "E" 1] `withSetupDeps` [ExFix "E" 2] + ] + +privDep5 :: SolverTest +privDep5 = setVerbose $ mkTest priv_db5 "private-dependencies-5" ["A"] (solverSuccess [("A", 1)]) + +-- Private scope, with two dependencies +priv_db6 :: ExampleDb +priv_db6 = + let f1 = exInst "F" 1 "F-1" [] + f2 = exInst "F" 2 "F-2" [] + in [ Left $ exInst "E" 1 "E-1" [f1] + , Left $ exInst "E" 2 "E-2" [f2] + , Left f1 + , Left f2 + , Right $ exAv "A" 1 [ExFix "E" 2, ExFixPriv "G0" "E" 1, ExAnyPriv "G0" "F"] + ] + +privDep6 :: SolverTest +privDep6 = setVerbose $ mkTest priv_db6 "private-dependencies-6" ["A"] (solverSuccess [("A", 1)]) + +-- A dependency structure which violates the closure property for private dependency scopes +priv_db7 :: ExampleDb +priv_db7 = + [ Right $ exAv "A" 1 [ExAny "B"] + , Right $ exAv "B" 1 [ExAny "C"] + , Right $ exAv "C" 1 [] + , Right $ exAv "P" 1 [ExFixPriv "G0" "A" 1, ExAnyPriv "G0" "C"] + ] + +privDep7 :: SolverTest +privDep7 = setVerbose $ mkTest priv_db7 "private-dependencies-7" ["P"] (solverFailure ("a private scope must contain its closure, but package B is not included in the private scope P:G0" `isInfixOf`)) + +-- Closure property with external deps +priv_db7a :: ExampleDb +priv_db7a = + let a = exInst "A" 1 "A-1" [b] + b = exInst "B" 1 "B-1" [c] + c = exInst "C" 1 "C-1" [] + in [ Left a + , Left b + , Left c + , Right $ exAv "P" 1 [ExFixPriv "G0" "A" 1, ExAnyPriv "G0" "C"] + ] + +privDep7a :: SolverTest +privDep7a = setVerbose $ mkTest priv_db7a "private-dependencies-7a" ["P"] (solverFailure ("a private scope must contain its closure, but package B is not included in the private scope P:G0" `isInfixOf`)) + +priv_db8 :: ExampleDb +priv_db8 = + [ Right $ exAv "A" 1 [ExAny "B"] + , Right $ exAv "B" 1 [ExAny "C"] + , Right $ exAv "C" 1 [] + , Right $ exAv "P" 1 [ExFixPriv "G0" "A" 1, ExAnyPriv "G0" "B", ExAnyPriv "G0" "C"] + ] + +privDep8 :: SolverTest +privDep8 = setVerbose $ mkTest priv_db8 "private-dependencies-8" ["P"] (solverSuccess [("A", 1), ("B", 1), ("C", 1), ("P", 1)]) + +priv_db8a :: ExampleDb +priv_db8a = + let a = exInst "A" 1 "A-1" [b] + b = exInst "B" 1 "B-1" [c] + c = exInst "C" 1 "C-1" [] + in [ Left a + , Left b + , Left c + , Right $ exAv "P" 1 [ExFixPriv "G0" "A" 1, ExAnyPriv "G0" "B", ExAnyPriv "G0" "C"] + ] + +privDep8a :: SolverTest +privDep8a = setVerbose $ mkTest priv_db8a "private-dependencies-8a" ["P"] (solverSuccess [("P", 1)]) + +-- Two different private scopes can have two different versions +priv_db9 :: ExampleDb +priv_db9 = + let a = exInst "A" 1 "A-1" [] + b = exInst "A" 2 "A-2" [] + in [ Left a + , Left b + , Right $ exAv "P" 1 [ExFixPriv "G0" "A" 1, ExFixPriv "G1" "A" 2] + ] + +privDep9 :: SolverTest +privDep9 = setVerbose $ mkTest priv_db9 "private-dependencies-9" ["P"] (solverSuccess [("P", 1)]) + +-- Backtrack when closure property is violated +priv_db10 :: ExampleDb +priv_db10 = + let a2 = exInst "A" 2 "A-2" [b] + a1 = exInst "A" 1 "A-1" [] + b = exInst "B" 1 "B-1" [c] + c = exInst "C" 1 "C-1" [] + in [ Left a1 + , Left a2 + , Left b + , Left c + , Right $ exAv "P" 1 [ExAnyPriv "G0" "A", ExAnyPriv "G0" "C"] + ] + +privDep10 :: SolverTest +privDep10 = + setVerbose $ + mkTest + priv_db10 + "private-dependencies-10" + ["P"] + (solverResult (any ("private scopes must contain its closure, but package B is not included in the private scope P:lib:G0." `isInfixOf`)) [("P", 1)]) + +-- Testing constraints DON'T apply to private dependencies +priv_db11 :: ExampleDb +priv_db11 = + [ Left (exInst "A" 1 "A-1" []) + , Right $ exAv "P" 1 [ExAnyPriv "G0" "A"] + ] + +privDep11 :: SolverTest +privDep11 = + setVerbose $ + constraints [ExVersionConstraint (ScopeQualified P.DefaultNamespace P.QualToplevel "A") (V.thisVersion (V.mkVersion [2]))] $ + mkTest priv_db11 "private-dependencies-11" ["P"] (solverSuccess [("P", 1)]) + +-- Testing suitably scoped constraints do apply to private dependencies +privDep12 :: SolverTest +privDep12 = + setVerbose $ + constraints [ExVersionConstraint (ScopePrivate "P" "G0" "A") (V.thisVersion (V.mkVersion [2]))] $ + mkTest priv_db11 "private-dependencies-12" ["P"] (solverFailure ("constraint from unknown source requires ==2" `isInfixOf`)) + +-- Testing that `any` qualifier applies to private deps +privDep13 :: SolverTest +privDep13 = + setVerbose $ + constraints [ExVersionConstraint (ScopeAnyQualifier "A") (V.thisVersion (V.mkVersion [2]))] $ + mkTest priv_db11 "private-dependencies-13" ["P"] (solverFailure ("constraint from unknown source requires ==2" `isInfixOf`)) + +-- Testing nested private scopes +priv_db14 :: ExampleDb +priv_db14 = + priv_db6 -- uses A depends on E, F pkg names. + ++ [ Left $ exInst "B" 1 "B-1" [] + , Right $ exAv "P" 1 [ExAnyPriv "G0" "A", ExAnyPriv "G0" "B"] + ] + +privDep14 :: SolverTest +privDep14 = + setVerbose $ + mkTest priv_db14 "private-dependencies-14" ["P"] (solverSuccess [("A", 1), ("P", 1)]) + +-- Testing nested private scopes, where outer private scope includes deps of nested private scope. +priv_db15 :: ExampleDb +priv_db15 = + let f1 = exInst "F" 1 "F-1" [] + f2 = exInst "F" 2 "F-2" [] + in [ Left $ exInst "E" 1 "E-1" [f1] + , Left $ exInst "E" 2 "E-2" [f2] + , Left f1 + , Left f2 + , Right $ exAv "A" 1 [ExFix "E" 2, ExFixPriv "G0" "E" 1, ExAnyPriv "G0" "F"] + , Right $ exAv "P" 1 [ExAnyPriv "G0" "A", ExAnyPriv "G0" "E"] + ] + +privDep15 :: SolverTest +privDep15 = + setVerbose $ + mkTest priv_db15 "private-dependencies-15" ["P"] (solverSuccess [("A", 1), ("P", 1)]) + -- | Returns true if the second list contains all elements of the first list, in -- order. containsInOrder :: Eq a => [a] -> [a] -> Bool diff --git a/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/README.md b/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/README.md new file mode 100644 index 00000000000..bc40cd6f9a5 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/README.md @@ -0,0 +1,10 @@ +Proof of concept for Cabal hooks compatability scheme, which tests private +dependencies + +* `lib01` - The library which defines the hooks interface, which can have different versions. + +* `main-prog` - A program written against the `lib01` interface, but needs to work with multiple versions. + +* `hooks-exe` - The executable which can be compiled against multiple versions of `lib01`. + +* `hooks-lib` - A compability library which depends on all versions of lib01 which are supported and provides conversions between the new and old datatypes. diff --git a/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/cabal.project b/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/cabal.project new file mode 100644 index 00000000000..e25e053a3c0 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/cabal.project @@ -0,0 +1 @@ +packages: hooks-exe hooks-lib main-prog diff --git a/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/cabal.test.hs b/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/cabal.test.hs new file mode 100644 index 00000000000..de74350e18a --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/cabal.test.hs @@ -0,0 +1,20 @@ +import Test.Cabal.Prelude + +main = + cabalTest $ recordMode DoNotRecord $ + withProjectFile "cabal.project" $ + withRepo "repo" $ do + cabal "build" ["exe:hooks-exe", "--constraint=private.hooks-exe.L01:lib01 == 0.1.0.0"] + exePath <- withPlan $ planExePath "hooks-exe" "hooks-exe" + out1 <- cabal' "run" ["exe:main-prog", "--", exePath] + + assertOutputContains "0.1.0.0" out1 + assertOutputContains "hooks_show: A" out1 + assertOutputContains "hooks_inc: B" out1 + + cabal "build" ["exe:hooks-exe", "--constraint=private.hooks-exe.L01:lib01 == 0.2.0.0"] + out2 <- cabal' "run" ["exe:main-prog", "--", exePath] + + assertOutputContains "0.2.0.0" out2 + assertOutputContains "hooks_show: A {value = 5}" out2 + assertOutputContains "hooks_inc: B" out2 diff --git a/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/hooks-exe/CHANGELOG.md b/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/hooks-exe/CHANGELOG.md new file mode 100644 index 00000000000..ae45e4d0b14 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/hooks-exe/CHANGELOG.md @@ -0,0 +1,5 @@ +# Revision history for hooks-exe + +## 0.1.0.0 -- YYYY-mm-dd + +* First version. Released on an unsuspecting world. diff --git a/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/hooks-exe/app/Main.hs b/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/hooks-exe/app/Main.hs new file mode 100644 index 00000000000..38dc9f85525 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/hooks-exe/app/Main.hs @@ -0,0 +1,35 @@ +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE CPP #-} +module Main where + +import System.Environment + +import Prelude hiding (getContents, putStr, hPutStr) +import Data.ByteString.Lazy (getContents, putStr, hPutStr) +import System.Environment (getArgs) +import System.IO (stderr, hPrint) +import Data.String +import Data.Binary +import L01.Lib + +-- | Create an executable which accepts the name of a hook as the argument, +-- then reads arguments to the hook over stdin and writes the results of the hook +-- to stdout. +main :: IO () +main = do + [hookName] <- getArgs + case hookName of + "version" -> do + putStr $ encode (VERSION_lib01 :: String) + "show" -> do + s <- getContents + let a1 :: A = decode s + res = show a1 + putStr (encode res) + "inc" -> do + s <- getContents + let a1 :: A = decode s + res = inc a1 + putStr (encode res) + _ -> error "Hook not yet implemented" diff --git a/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/hooks-exe/hooks-exe.cabal b/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/hooks-exe/hooks-exe.cabal new file mode 100644 index 00000000000..b03865b863a --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/hooks-exe/hooks-exe.cabal @@ -0,0 +1,19 @@ +cabal-version: 3.0 +name: hooks-exe +version: 0.1.0.0 +license: NONE +author: matthewtpickering@gmail.com +maintainer: Matthew Pickering +build-type: Simple +extra-doc-files: CHANGELOG.md + +common warnings + ghc-options: -Wall + +executable hooks-exe + import: warnings + main-is: Main.hs + build-depends: base, bytestring, binary, directory + private-build-depends: L01 with (lib01) + hs-source-dirs: app + default-language: Haskell2010 diff --git a/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/hooks-lib/CHANGELOG.md b/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/hooks-lib/CHANGELOG.md new file mode 100644 index 00000000000..85a864adeca --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/hooks-lib/CHANGELOG.md @@ -0,0 +1,5 @@ +# Revision history for hooks-lib + +## 0.1.0.0 -- YYYY-mm-dd + +* First version. Released on an unsuspecting world. diff --git a/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/hooks-lib/hooks-lib.cabal b/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/hooks-lib/hooks-lib.cabal new file mode 100644 index 00000000000..bb5efe62961 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/hooks-lib/hooks-lib.cabal @@ -0,0 +1,20 @@ +cabal-version: 3.0 +name: hooks-lib +version: 0.1.0.0 +license: NONE +author: matthewtpickering@gmail.com +maintainer: Matthew Pickering +build-type: Simple +extra-doc-files: CHANGELOG.md + +common warnings + ghc-options: -Wall + +library + import: warnings + exposed-modules: HooksLib + build-depends: base, lib01 == 0.2.0.0, mtl, process, binary, bytestring, deepseq + private-build-depends: V01 with (lib01 == 0.1.0.0), V02 with (lib01 == 0.2.0.0) + hs-source-dirs: src + default-language: Haskell2010 + diff --git a/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/hooks-lib/src/HooksLib.hs b/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/hooks-lib/src/HooksLib.hs new file mode 100644 index 00000000000..aae813b46f5 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/hooks-lib/src/HooksLib.hs @@ -0,0 +1,133 @@ +{-# LANGUAGE PackageImports #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE LambdaCase #-} +{-# LANGUAGE OverloadedStrings #-} +module HooksLib where + +import Control.Monad.Reader + +import V01.Lib as L1 +import V02.Lib as L2 +import "lib01" Lib as L + +import System.IO (stderr) +import System.Process +import Control.Exception as C +import Data.Binary +import Control.Concurrent +import GHC.IO.Handle (BufferMode(..), hClose, hSetBuffering) +import Control.Concurrent.MVar +import Control.Concurrent +import qualified Control.Exception as C +import Data.ByteString.Lazy (hPutStr, hGetContents) +import qualified Data.ByteString.Char8 as C8 +import Control.DeepSeq +import GHC.IO.Exception as GHC +import Foreign.C.Error + +data SupportedVersion = V01 | V02 + +--import Lib as LX + +data HooksEnv = HooksEnv { hooksExe :: FilePath, hooksVersion :: SupportedVersion } + +type HooksM a = ReaderT HooksEnv IO a + +version :: FilePath -> IO (Maybe SupportedVersion) +version fp = do + (ver :: String) <- readHooksExe_ fp "version" () + print ver + return $ case C8.split '.' (C8.pack ver) of + ["0","1","0","0"] -> Just V01 + ["0","2","0","0"] -> Just V02 + _ -> Nothing + +withHooksExe :: FilePath -> HooksM a -> IO a +withHooksExe prog action = do + ver <- version prog + case ver of + Just sver -> runReaderT action (HooksEnv prog sver) + Nothing -> error "Hooks executable is unsupported version" + +convertA1 :: L.A -> L1.A +convertA1 (L.A {}) = L1.A +convertA1 (L.B) = L1.B + +convertA2 :: L.A -> L2.A +convertA2 (L.A x) = (L2.A x) +convertA2 L.B = L2.B + +revertA1 :: L1.A -> L.A +revertA1 L1.A = L.A 0 +revertA1 L1.B = L.B + +revertA2 :: L2.A -> L.A +revertA2 (L2.A x) = L.A x +revertA2 L2.B = L.B + + +hooks_show :: L.A -> HooksM String +hooks_show a = do + ver <- asks hooksVersion + case ver of + V01 -> readHooksExe "show" (convertA1 a) + V02 -> readHooksExe "show" (convertA2 a) + +hooks_inc :: L.A -> HooksM L.A +hooks_inc a = do + ver <- asks hooksVersion + case ver of + V01 -> revertA1 <$> (readHooksExe "inc" (convertA1 a)) + V02 -> revertA2 <$> (readHooksExe "inc" (convertA2 a)) + + + + +-- Library funcs + + +readHooksExe :: (Binary a, Binary b) => String -> a -> HooksM b +readHooksExe hook args = do + exe <- asks hooksExe + liftIO $ readHooksExe_ exe hook args + +withForkWait :: IO () -> (IO () -> IO a) -> IO a +withForkWait async body = do + waitVar <- newEmptyMVar :: IO (MVar (Either SomeException ())) + mask $ \restore -> do + tid <- forkIO $ try (restore async) >>= putMVar waitVar + let wait = takeMVar waitVar >>= either throwIO return + restore (body wait) `C.onException` killThread tid + +readHooksExe_ :: (Binary a, Binary b) => FilePath -> String -> a -> IO b +readHooksExe_ exe hook args = + let stdin_ = encode args + cp = (proc exe [hook]) { std_in = CreatePipe + , std_out = CreatePipe } + in withCreateProcess cp $ \(Just inh) (Just outh) Nothing ph -> do + -- fork off a thread to start consuming the output + hSetBuffering inh NoBuffering + hSetBuffering outh NoBuffering + output <- hGetContents outh + withForkWait (C.evaluate $ rnf output) $ \waitOut -> do + + hPutStr inh stdin_ + -- hClose performs implicit hFlush, and thus may trigger a SIGPIPE + ignoreSigPipe $ hClose inh + + -- wait on the output + waitOut + hClose outh + + -- wait on the process + _ex <- waitForProcess ph + return (decode output) + + + +-- | Ignore SIGPIPE in a subcomputation. +ignoreSigPipe :: IO () -> IO () +ignoreSigPipe = C.handle $ \case + GHC.IOError{GHC.ioe_type = GHC.ResourceVanished, GHC.ioe_errno = Just ioe} + | Errno ioe == ePIPE -> return () + e -> throwIO e diff --git a/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/hooks-lib/src/MyLib.hs b/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/hooks-lib/src/MyLib.hs new file mode 100644 index 00000000000..e657c4403f6 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/hooks-lib/src/MyLib.hs @@ -0,0 +1,4 @@ +module MyLib (someFunc) where + +someFunc :: IO () +someFunc = putStrLn "someFunc" diff --git a/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/main-prog/CHANGELOG.md b/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/main-prog/CHANGELOG.md new file mode 100644 index 00000000000..6b7696f9f1e --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/main-prog/CHANGELOG.md @@ -0,0 +1,5 @@ +# Revision history for main-prog + +## 0.1.0.0 -- YYYY-mm-dd + +* First version. Released on an unsuspecting world. diff --git a/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/main-prog/app/Main.hs b/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/main-prog/app/Main.hs new file mode 100644 index 00000000000..8cd9037f565 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/main-prog/app/Main.hs @@ -0,0 +1,21 @@ +-- This is linked directly against lib, but can communicate with older versions of +-- lib via the hooks executable. +module Main where + +import System.Directory +import Lib +import HooksLib +import Control.Monad.IO.Class +import System.Environment + +main :: IO () +main = do + -- Receive the path to the hooks_exe as an argument + [hooks_exe] <- getArgs + withHooksExe hooks_exe $ do + liftIO $ putStr "hooks_show: " + rendered <- hooks_show (A 5) + liftIO $ putStrLn rendered + liftIO $ putStr "hooks_inc: " + a' <- hooks_inc (A 5) + liftIO $ print a' diff --git a/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/main-prog/main-prog.cabal b/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/main-prog/main-prog.cabal new file mode 100644 index 00000000000..56f5ddfa5e5 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/main-prog/main-prog.cabal @@ -0,0 +1,18 @@ +cabal-version: 3.0 +name: main-prog +version: 0.1.0.0 +license: NONE +author: matthewtpickering@gmail.com +maintainer: Matthew Pickering +build-type: Simple +extra-doc-files: CHANGELOG.md + +common warnings + ghc-options: -Wall + +executable main-prog + import: warnings + main-is: Main.hs + build-depends: base, lib01, directory, hooks-lib + hs-source-dirs: app + default-language: Haskell2010 diff --git a/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/repo/lib01-0.1.0.0/CHANGELOG.md b/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/repo/lib01-0.1.0.0/CHANGELOG.md new file mode 100644 index 00000000000..6a8c7fe311e --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/repo/lib01-0.1.0.0/CHANGELOG.md @@ -0,0 +1,5 @@ +# Revision history for lib01 + +## 0.1.0.0 -- YYYY-mm-dd + +* First version. Released on an unsuspecting world. diff --git a/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/repo/lib01-0.1.0.0/lib01.cabal b/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/repo/lib01-0.1.0.0/lib01.cabal new file mode 100644 index 00000000000..1fc1ad750b9 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/repo/lib01-0.1.0.0/lib01.cabal @@ -0,0 +1,18 @@ +cabal-version: 3.0 +name: lib01 +version: 0.1.0.0 +license: NONE +author: matthewtpickering@gmail.com +maintainer: Matthew Pickering +build-type: Simple +extra-doc-files: CHANGELOG.md + +common warnings + ghc-options: -Wall + +library + import: warnings + exposed-modules: Lib + build-depends: base, binary + hs-source-dirs: src + default-language: Haskell2010 diff --git a/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/repo/lib01-0.1.0.0/src/Lib.hs b/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/repo/lib01-0.1.0.0/src/Lib.hs new file mode 100644 index 00000000000..5c3bf43eabc --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/repo/lib01-0.1.0.0/src/Lib.hs @@ -0,0 +1,16 @@ +{-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE StandaloneDeriving #-} +{-# LANGUAGE DeriveAnyClass #-} +module Lib(A(..), inc) where + +import Data.Binary +import GHC.Generics + +data A = A | B deriving (Show, Generic) + +deriving instance Binary A + +inc :: A -> A +inc A = B +inc B = B + diff --git a/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/repo/lib01-0.2.0.0/CHANGELOG.md b/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/repo/lib01-0.2.0.0/CHANGELOG.md new file mode 100644 index 00000000000..6a8c7fe311e --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/repo/lib01-0.2.0.0/CHANGELOG.md @@ -0,0 +1,5 @@ +# Revision history for lib01 + +## 0.1.0.0 -- YYYY-mm-dd + +* First version. Released on an unsuspecting world. diff --git a/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/repo/lib01-0.2.0.0/lib01.cabal b/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/repo/lib01-0.2.0.0/lib01.cabal new file mode 100644 index 00000000000..da908f3f043 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/repo/lib01-0.2.0.0/lib01.cabal @@ -0,0 +1,18 @@ +cabal-version: 3.0 +name: lib01 +version: 0.2.0.0 +license: NONE +author: matthewtpickering@gmail.com +maintainer: Matthew Pickering +build-type: Simple +extra-doc-files: CHANGELOG.md + +common warnings + ghc-options: -Wall + +library + import: warnings + exposed-modules: Lib + build-depends: base, binary + hs-source-dirs: src + default-language: Haskell2010 diff --git a/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/repo/lib01-0.2.0.0/src/Lib.hs b/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/repo/lib01-0.2.0.0/src/Lib.hs new file mode 100644 index 00000000000..24ce215cd70 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/cabal-hooks-demo/repo/lib01-0.2.0.0/src/Lib.hs @@ -0,0 +1,16 @@ +{-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE StandaloneDeriving #-} +{-# LANGUAGE DeriveAnyClass #-} +module Lib(A(..), inc) where + +import Data.Binary +import GHC.Generics + +data A = A { value :: Int } | B deriving (Show, Generic) + +deriving instance Binary A + +inc :: A -> A +inc (A {}) = B +inc B = B + diff --git a/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/README.md b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/README.md new file mode 100644 index 00000000000..573957a03fa --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/README.md @@ -0,0 +1,30 @@ +Closure property test + +package a-0.1 + :private-build-depends: G0 with (b, d) + +package a-0.2 + :build-depends: c + :private-build-depends: G0 with (b, d) + +package b-0.1 + :build-depends: x + +package b-0.2 + :build-depends: x, d + +package b-0.3 + :build-depends: x, c, d + +package c-0.1 + :build-depends: x + +package c-0.2 + :build-depends: x, d + + +Closure property violated by `b == 0.3` and `c == 0.2` THEN closure property is violated. + +Need to be able to implicitly introduce c into the private scope so that the closure property holds. +Or otherwise pick an older version of C which does not depend on D + diff --git a/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/cabal.project.1 b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/cabal.project.1 new file mode 100644 index 00000000000..1d6fdeb5c43 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/cabal.project.1 @@ -0,0 +1 @@ +packages: libA-0.1.0.0 diff --git a/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/cabal.project.2 b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/cabal.project.2 new file mode 100644 index 00000000000..6a6ab0dcb42 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/cabal.project.2 @@ -0,0 +1 @@ +packages: libA-0.2.0.0 diff --git a/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/cabal.project.3 b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/cabal.project.3 new file mode 100644 index 00000000000..50ad944ca45 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/cabal.project.3 @@ -0,0 +1 @@ +packages: libA-0.3.0.0 diff --git a/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/cabal.project.4 b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/cabal.project.4 new file mode 100644 index 00000000000..a62ce97ac49 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/cabal.project.4 @@ -0,0 +1 @@ +packages: libA-0.4.0.0 diff --git a/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/cabal.test.hs b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/cabal.test.hs new file mode 100644 index 00000000000..13215233402 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/cabal.test.hs @@ -0,0 +1,29 @@ +import Test.Cabal.Prelude + +main = do + cabalTest $ recordMode DoNotRecord $ do + + -- Will violate closure property + withProjectFile "cabal.project.1" $ + withRepo "repo" $ + fails (cabal' "v2-build" ["libA"]) + >>= assertOutputContains "private scopes must contain its closure, but package libC is not included in the private scope libA:lib:G0" + + -- Must pick libC == 0.1 + withProjectFile "cabal.project.2" $ + withRepo "repo" $ + cabal' "v2-build" ["libA"] + >>= assertOutputContains "libC-0.1.0.0" + + -- Shouldn't pick libB == 0.3 because it violates closure property + withProjectFile "cabal.project.3" $ + withRepo "repo" $ + cabal' "v2-build" ["libA"] + >>= assertOutputDoesNotContain "libB-0.3.0.0" + + -- Will be OKay with libB == 0.3 and libC == 0.2 because libC is in the closure + withProjectFile "cabal.project.4" $ + withRepo "repo" $ do + o <- cabal' "v2-build" ["libA"] + assertOutputContains "libC-0.2.0.0" o + assertOutputContains "libB-0.3.0.0" o diff --git a/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/libA-0.1.0.0/MyLib.hs b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/libA-0.1.0.0/MyLib.hs new file mode 100644 index 00000000000..dc2cb96275e --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/libA-0.1.0.0/MyLib.hs @@ -0,0 +1,3 @@ +module MyLib (someFunc) where + +someFunc = "" diff --git a/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/libA-0.1.0.0/libA.cabal b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/libA-0.1.0.0/libA.cabal new file mode 100644 index 00000000000..f92995fdacf --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/libA-0.1.0.0/libA.cabal @@ -0,0 +1,13 @@ +cabal-version: 3.0 +name: libA +version: 0.1.0.0 +license: NONE +build-type: Simple + +library + exposed-modules: MyLib + -- Will violate closure property + private-build-depends: G0 with (libB == 0.1.0.0,libD) + hs-source-dirs: . + default-language: Haskell2010 + default-extensions: NoImplicitPrelude diff --git a/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/libA-0.2.0.0/MyLib.hs b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/libA-0.2.0.0/MyLib.hs new file mode 100644 index 00000000000..6c63822a95f --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/libA-0.2.0.0/MyLib.hs @@ -0,0 +1,3 @@ +module MyLib (someFunc) where + +someFunc = "someFunc" diff --git a/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/libA-0.2.0.0/libA.cabal b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/libA-0.2.0.0/libA.cabal new file mode 100644 index 00000000000..56bdf19a058 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/libA-0.2.0.0/libA.cabal @@ -0,0 +1,14 @@ +cabal-version: 3.0 +name: libA +version: 0.2.0.0 +license: NONE +build-type: Simple + +library + exposed-modules: MyLib + build-depends: libC + -- Must pick libC == 0.1 + private-build-depends: G0 with (libB == 0.2.0.0,libD) + hs-source-dirs: . + default-language: Haskell2010 + default-extensions: NoImplicitPrelude diff --git a/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/libA-0.3.0.0/MyLib.hs b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/libA-0.3.0.0/MyLib.hs new file mode 100644 index 00000000000..6c63822a95f --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/libA-0.3.0.0/MyLib.hs @@ -0,0 +1,3 @@ +module MyLib (someFunc) where + +someFunc = "someFunc" diff --git a/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/libA-0.3.0.0/libA.cabal b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/libA-0.3.0.0/libA.cabal new file mode 100644 index 00000000000..90f84cd5a36 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/libA-0.3.0.0/libA.cabal @@ -0,0 +1,14 @@ +cabal-version: 3.0 +name: libA +version: 0.3.0.0 +license: NONE +build-type: Simple + +library + exposed-modules: MyLib + build-depends: libC + -- Shouldn't pick libB == 0.3 because it violates closure property + private-build-depends: G0 with (libB,libD) + hs-source-dirs: . + default-language: Haskell2010 + default-extensions: NoImplicitPrelude diff --git a/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/libA-0.4.0.0/MyLib.hs b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/libA-0.4.0.0/MyLib.hs new file mode 100644 index 00000000000..6c63822a95f --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/libA-0.4.0.0/MyLib.hs @@ -0,0 +1,3 @@ +module MyLib (someFunc) where + +someFunc = "someFunc" diff --git a/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/libA-0.4.0.0/libA.cabal b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/libA-0.4.0.0/libA.cabal new file mode 100644 index 00000000000..ec556d108ac --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/libA-0.4.0.0/libA.cabal @@ -0,0 +1,13 @@ +cabal-version: 3.0 +name: libA +version: 0.4.0.0 +license: NONE +build-type: Simple + +library + exposed-modules: MyLib + -- Will be OKay with libB == 0.3 and libC == 0.2 because libC is in the closure + private-build-depends: G0 with (libB == 0.3.0.0, libC, libD) + hs-source-dirs: . + default-language: Haskell2010 + default-extensions: NoImplicitPrelude diff --git a/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/repo/libB-0.1.0.0/MyLib.hs b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/repo/libB-0.1.0.0/MyLib.hs new file mode 100644 index 00000000000..6c63822a95f --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/repo/libB-0.1.0.0/MyLib.hs @@ -0,0 +1,3 @@ +module MyLib (someFunc) where + +someFunc = "someFunc" diff --git a/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/repo/libB-0.1.0.0/libB.cabal b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/repo/libB-0.1.0.0/libB.cabal new file mode 100644 index 00000000000..0b368f60db2 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/repo/libB-0.1.0.0/libB.cabal @@ -0,0 +1,12 @@ +cabal-version: 3.0 +name: libB +version: 0.1.0.0 +license: NONE +build-type: Simple + +library + exposed-modules: MyLib + build-depends: libC == 0.2.0.0 + hs-source-dirs: . + default-language: Haskell2010 + default-extensions: NoImplicitPrelude diff --git a/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/repo/libB-0.2.0.0/MyLib.hs b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/repo/libB-0.2.0.0/MyLib.hs new file mode 100644 index 00000000000..6c63822a95f --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/repo/libB-0.2.0.0/MyLib.hs @@ -0,0 +1,3 @@ +module MyLib (someFunc) where + +someFunc = "someFunc" diff --git a/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/repo/libB-0.2.0.0/libB.cabal b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/repo/libB-0.2.0.0/libB.cabal new file mode 100644 index 00000000000..010de751424 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/repo/libB-0.2.0.0/libB.cabal @@ -0,0 +1,12 @@ +cabal-version: 3.0 +name: libB +version: 0.2.0.0 +license: NONE +build-type: Simple + +library + exposed-modules: MyLib + build-depends: libC + hs-source-dirs: . + default-language: Haskell2010 + default-extensions: NoImplicitPrelude diff --git a/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/repo/libB-0.3.0.0/MyLib.hs b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/repo/libB-0.3.0.0/MyLib.hs new file mode 100644 index 00000000000..6c63822a95f --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/repo/libB-0.3.0.0/MyLib.hs @@ -0,0 +1,3 @@ +module MyLib (someFunc) where + +someFunc = "someFunc" diff --git a/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/repo/libB-0.3.0.0/libB.cabal b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/repo/libB-0.3.0.0/libB.cabal new file mode 100644 index 00000000000..cb0ff52869e --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/repo/libB-0.3.0.0/libB.cabal @@ -0,0 +1,12 @@ +cabal-version: 3.0 +name: libB +version: 0.3.0.0 +license: NONE +build-type: Simple + +library + exposed-modules: MyLib + build-depends: libC == 0.2.0.0, libD + hs-source-dirs: . + default-language: Haskell2010 + default-extensions: NoImplicitPrelude diff --git a/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/repo/libC-0.1.0.0/MyLib.hs b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/repo/libC-0.1.0.0/MyLib.hs new file mode 100644 index 00000000000..6c63822a95f --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/repo/libC-0.1.0.0/MyLib.hs @@ -0,0 +1,3 @@ +module MyLib (someFunc) where + +someFunc = "someFunc" diff --git a/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/repo/libC-0.1.0.0/libC.cabal b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/repo/libC-0.1.0.0/libC.cabal new file mode 100644 index 00000000000..abb9ae3482a --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/repo/libC-0.1.0.0/libC.cabal @@ -0,0 +1,11 @@ +cabal-version: 3.0 +name: libC +version: 0.1.0.0 +license: NONE +build-type: Simple + +library + exposed-modules: MyLib + hs-source-dirs: . + default-language: Haskell2010 + default-extensions: NoImplicitPrelude diff --git a/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/repo/libC-0.2.0.0/MyLib.hs b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/repo/libC-0.2.0.0/MyLib.hs new file mode 100644 index 00000000000..6c63822a95f --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/repo/libC-0.2.0.0/MyLib.hs @@ -0,0 +1,3 @@ +module MyLib (someFunc) where + +someFunc = "someFunc" diff --git a/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/repo/libC-0.2.0.0/libC.cabal b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/repo/libC-0.2.0.0/libC.cabal new file mode 100644 index 00000000000..3dd472acc3a --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/repo/libC-0.2.0.0/libC.cabal @@ -0,0 +1,12 @@ +cabal-version: 3.0 +name: libC +version: 0.2.0.0 +license: NONE +build-type: Simple + +library + exposed-modules: MyLib + build-depends: libD + hs-source-dirs: . + default-language: Haskell2010 + default-extensions: NoImplicitPrelude diff --git a/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/repo/libD-0.1.0.0/MyLib.hs b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/repo/libD-0.1.0.0/MyLib.hs new file mode 100644 index 00000000000..6c63822a95f --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/repo/libD-0.1.0.0/MyLib.hs @@ -0,0 +1,3 @@ +module MyLib (someFunc) where + +someFunc = "someFunc" diff --git a/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/repo/libD-0.1.0.0/libD.cabal b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/repo/libD-0.1.0.0/libD.cabal new file mode 100644 index 00000000000..117350487c7 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/repo/libD-0.1.0.0/libD.cabal @@ -0,0 +1,11 @@ +cabal-version: 3.0 +name: libD +version: 0.1.0.0 +license: NONE +build-type: Simple + +library + exposed-modules: MyLib + hs-source-dirs: . + default-language: Haskell2010 + default-extensions: NoImplicitPrelude diff --git a/cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/README.md b/cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/README.md new file mode 100644 index 00000000000..57d9e02f886 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/README.md @@ -0,0 +1,15 @@ +Backpack + Private Dependencies test + +exeA + main-is: Main.hs + private-build-depends: G1 with (libB == 0.1.0.0) + private-build-depends: G2 with (libB == 0.2.0.0) + build-depends: libB == 0.3.0.0 + mixins: + libA (A as A.G1) requires (AHole as G1.Fill) + libA (A as A.G2) requires (AHole as G2.Fill) + libA (A as A.NoScope) requires (AHole as Fill) + +libA + exposed-modules: A + signatures: AHole diff --git a/cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/cabal.project b/cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/cabal.project new file mode 100644 index 00000000000..827fcfc78cf --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/cabal.project @@ -0,0 +1 @@ +packages: libA diff --git a/cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/cabal.test.hs b/cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/cabal.test.hs new file mode 100644 index 00000000000..c740c372052 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/cabal.test.hs @@ -0,0 +1,9 @@ +import Test.Cabal.Prelude + +main = + cabalTest $ + expectBroken 0 $ + withProjectFile "cabal.project" $ + withRepo "repo" $ + cabal "v2-build" ["libA"] + diff --git a/cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/libA/app/Main.hs b/cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/libA/app/Main.hs new file mode 100644 index 00000000000..6d78a77a66a --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/libA/app/Main.hs @@ -0,0 +1,8 @@ +import qualified A.G1 +import qualified A.G2 +import qualified A.NoScope + +main = do + print (A.G1.fillhole) + print (A.G2.fillhole) + print (A.NoScope.fillhole) diff --git a/cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/libA/libA.cabal b/cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/libA/libA.cabal new file mode 100644 index 00000000000..4e9ec21c5cb --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/libA/libA.cabal @@ -0,0 +1,22 @@ +cabal-version: 3.0 +name: libA +version: 0.1.0.0 +license: NONE +build-type: Simple + +executable exeA + main-is: Main.hs + build-depends: libA, libB == 0.3.0.0 + private-build-depends: G1 with (libB == 0.1.0.0) + private-build-depends: G2 with (libB == 0.2.0.0) + mixins: + libA (A as A.G1) requires (AHole as G1.Fill), + libA (A as A.G2) requires (AHole as G2.Fill), + libA (A as A.NoScope) requires (AHole as Fill) + default-extensions: NoImplicitPrelude + +library + exposed-modules: A + signatures: AHole + hs-source-dirs: src + default-extensions: NoImplicitPrelude diff --git a/cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/libA/src/A.hs b/cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/libA/src/A.hs new file mode 100644 index 00000000000..d1a60e710e2 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/libA/src/A.hs @@ -0,0 +1,3 @@ +module A (fillhole) where + +import AHole (fillhole) diff --git a/cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/libA/src/AHole.hsig b/cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/libA/src/AHole.hsig new file mode 100644 index 00000000000..9ceafbd086e --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/libA/src/AHole.hsig @@ -0,0 +1,3 @@ +signature AHole where + +fillhole :: Int diff --git a/cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/repo/libB-0.1.0.0/Fill.hs b/cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/repo/libB-0.1.0.0/Fill.hs new file mode 100644 index 00000000000..fef98a6ce08 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/repo/libB-0.1.0.0/Fill.hs @@ -0,0 +1,4 @@ +module Fill where + +fillhole :: Int +fillhole = 1 diff --git a/cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/repo/libB-0.1.0.0/libB.cabal b/cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/repo/libB-0.1.0.0/libB.cabal new file mode 100644 index 00000000000..e5937452a61 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/repo/libB-0.1.0.0/libB.cabal @@ -0,0 +1,10 @@ +cabal-version: 3.0 +name: libB +version: 0.1.0.0 +license: NONE +build-type: Simple + +library + exposed-modules: Fill + default-language: Haskell2010 + default-extensions: NoImplicitPrelude diff --git a/cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/repo/libB-0.1.0.0/tags b/cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/repo/libB-0.1.0.0/tags new file mode 100644 index 00000000000..1a01b2d1ce5 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/repo/libB-0.1.0.0/tags @@ -0,0 +1,2 @@ +!_TAG_FILE_SORTED 1 // +fillhole Fill.hs 3;" f diff --git a/cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/repo/libB-0.2.0.0/Fill.hs b/cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/repo/libB-0.2.0.0/Fill.hs new file mode 100644 index 00000000000..fd4cd35d6d6 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/repo/libB-0.2.0.0/Fill.hs @@ -0,0 +1,4 @@ +module Fill where + +fillhole :: Int +fillhole = 2 diff --git a/cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/repo/libB-0.2.0.0/libB.cabal b/cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/repo/libB-0.2.0.0/libB.cabal new file mode 100644 index 00000000000..0f8cd48746f --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/repo/libB-0.2.0.0/libB.cabal @@ -0,0 +1,10 @@ +cabal-version: 3.0 +name: libB +version: 0.2.0.0 +license: NONE +build-type: Simple + +library + exposed-modules: Fill + default-language: Haskell2010 + default-extensions: NoImplicitPrelude diff --git a/cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/repo/libB-0.2.0.0/tags b/cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/repo/libB-0.2.0.0/tags new file mode 100644 index 00000000000..1a01b2d1ce5 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/repo/libB-0.2.0.0/tags @@ -0,0 +1,2 @@ +!_TAG_FILE_SORTED 1 // +fillhole Fill.hs 3;" f diff --git a/cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/repo/libB-0.3.0.0/Fill.hs b/cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/repo/libB-0.3.0.0/Fill.hs new file mode 100644 index 00000000000..234f38660cb --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/repo/libB-0.3.0.0/Fill.hs @@ -0,0 +1,4 @@ +module Fill where + +fillhole :: Int +fillhole = 3 diff --git a/cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/repo/libB-0.3.0.0/libB.cabal b/cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/repo/libB-0.3.0.0/libB.cabal new file mode 100644 index 00000000000..5f7b5cc4f98 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/repo/libB-0.3.0.0/libB.cabal @@ -0,0 +1,10 @@ +cabal-version: 3.0 +name: libB +version: 0.3.0.0 +license: NONE +build-type: Simple + +library + exposed-modules: Fill + default-language: Haskell2010 + default-extensions: NoImplicitPrelude diff --git a/cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/repo/libB-0.3.0.0/tags b/cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/repo/libB-0.3.0.0/tags new file mode 100644 index 00000000000..1a01b2d1ce5 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/pd-backpack/repo/libB-0.3.0.0/tags @@ -0,0 +1,2 @@ +!_TAG_FILE_SORTED 1 // +fillhole Fill.hs 3;" f diff --git a/cabal-testsuite/src/Test/Cabal/Prelude.hs b/cabal-testsuite/src/Test/Cabal/Prelude.hs index 52430830014..32c6127cd78 100644 --- a/cabal-testsuite/src/Test/Cabal/Prelude.hs +++ b/cabal-testsuite/src/Test/Cabal/Prelude.hs @@ -381,7 +381,9 @@ runPlanExe' pkg_name cname args = do recordHeader [pkg_name, cname] runM exePath args Nothing -planExePath :: String {- package name -} -> String {- component name -} +-- | Get the path to an executable built from a package. Requires 'withPlan' +-- to have been run so that we can find the dist dir. +planExePath :: String {-^ package name -} -> String {-^ component name -} -> TestM FilePath planExePath pkg_name cname = do Just plan <- testPlan `fmap` getTestEnv diff --git a/doc/buildinfo-fields-reference.rst b/doc/buildinfo-fields-reference.rst index c1ccf418f81..8bd5b9fe502 100644 --- a/doc/buildinfo-fields-reference.rst +++ b/doc/buildinfo-fields-reference.rst @@ -510,6 +510,13 @@ pkgconfig-depends .. math:: \mathrm{commalist}\mathsf{\color{red}{TODO}} +private-build-depends + * Monoidal field + * Documentation of :pkg-field:`library:private-build-depends` + + .. math:: + \mathrm{commalist}\left(\mathop{\mathit{alias}}\bullet\mathop{\mathord{``}\mathtt{with}\mathord{"}}\bullet\mathop{\mathord{``}\mathtt{\text{(}}\mathord{"}}\circ{\left(\mathop{\mathit{pkg\text{-}name}}{\left(\mathop{\mathord{``}\mathtt{\text{:}}\mathord{"}}\left\{ \mathop{\mathit{unqual\text{-}name}}\mid\mathop{\mathord{``}\mathtt{\{}\mathord{"}}\circ{\mathop{\mathit{unqual\text{-}name}}}^+_{\left(\circ\mathop{\mathord{``}\mathtt{\text{,}}\mathord{"}}\circ\right)}\circ\mathop{\mathord{``}\mathtt{\}}\mathord{"}} \right\}\right)}^?{\left(\circ\mathop{\mathit{version\text{-}range}}\right)}^?\right)}^\ast_{\left(\circ\mathop{\mathord{``}\mathtt{\text{,}}\mathord{"}}\circ\right)}\circ\mathop{\mathord{``}\mathtt{\text{)}}\mathord{"}}\right) + virtual-modules * Monoidal field * Available since ``cabal-version: 2.2``. diff --git a/doc/cabal-package-description-file.rst b/doc/cabal-package-description-file.rst index 3004fed0b0b..1d6d34fa7a1 100644 --- a/doc/cabal-package-description-file.rst +++ b/doc/cabal-package-description-file.rst @@ -2143,6 +2143,30 @@ system-dependent values for these fields. supported libraries. Depending on your system you may need to adjust ``PKG_CONFIG_PATH``. +.. pkg-field:: private-build-depends: private scope + + A private dependency can be introduced in a cabal file in the + ``private-build-depends`` field. The specification starts with the name of the + private dependency *scope* and then contains a list of normal dependency + specifications which dictate the packages included in that private scope. + For example, the following will create two private scopes, with a different + version of ``text`` each. + + :: + + private-build-depends: TEXT1 with (text == 1.2.*), TEXT2 with (text == 2.*) + + The package **goals in a private scope are solved independently of all other + scopes**. In this example, the ``TEXT1`` scope can choose a version of ``text`` + in the ``1.2.x`` range and the ``TEXT2`` scope can choose a version of ``text`` in the + ``2.*`` range. + + However, **private scopes do not apply transitively**, so the dependencies of + ``text`` will be solved in the normal top-level scope. If your program contains a + value of type ``Bool`` from the ``base`` package, which ``text`` also depends on, only + if the scopes are not applied transitively can the same ``Bool`` value can be + passed to functions from the ``TEXT1`` scope and ``TEXT2`` scope. + .. pkg-field:: frameworks: token list On Darwin/MacOS X, a list of frameworks to link to. See Apple's From 99b451a3fdbd2eed76d4f1a6ab297be2c8d3e9f3 Mon Sep 17 00:00:00 2001 From: Rodrigo Mesquita Date: Mon, 8 Apr 2024 11:52:39 +0100 Subject: [PATCH 02/12] Make Cabal check fail on private deps Hackage is not yet ready for private dependencies, so we mustn't allow packages with private deps to be uploaded just yet. --- Cabal-syntax/src/Distribution/Types/PackageDescription.hs | 8 ++++++++ Cabal/src/Distribution/PackageDescription/Check.hs | 2 ++ .../src/Distribution/PackageDescription/Check/Warning.hs | 8 ++++++++ 3 files changed, 18 insertions(+) diff --git a/Cabal-syntax/src/Distribution/Types/PackageDescription.hs b/Cabal-syntax/src/Distribution/Types/PackageDescription.hs index cec1014d222..61d91db4ab9 100644 --- a/Cabal-syntax/src/Distribution/Types/PackageDescription.hs +++ b/Cabal-syntax/src/Distribution/Types/PackageDescription.hs @@ -34,6 +34,7 @@ module Distribution.Types.PackageDescription , buildType , emptyPackageDescription , hasPublicLib + , hasPrivateDependencies , hasLibs , allLibraries , withLib @@ -59,6 +60,7 @@ module Distribution.Types.PackageDescription import Distribution.Compat.Prelude import Prelude () +import qualified Data.List -- lens @@ -366,6 +368,12 @@ allBuildDepends pd = do [(Nothing, d) | d <- targetBuildDepends bi] ++ [(Just p, d) | PrivateDependency p ds <- targetPrivateBuildDepends bi, d <- ds] +-- | Does this package have any private dependencies? At the moment, cabal +-- check will reject any packages that do. +hasPrivateDependencies :: PackageDescription -> Bool +hasPrivateDependencies pd = not . Data.List.null $ + concatMap targetPrivateBuildDepends (allBuildInfo pd) + -- | Get the combined build-depends entries of all enabled components, per the -- given request spec. enabledBuildDepends :: PackageDescription -> ComponentRequestedSpec -> [(Maybe PrivateAlias, Dependency)] diff --git a/Cabal/src/Distribution/PackageDescription/Check.hs b/Cabal/src/Distribution/PackageDescription/Check.hs index 79123f7f9df..dc16c1bf6b7 100644 --- a/Cabal/src/Distribution/PackageDescription/Check.hs +++ b/Cabal/src/Distribution/PackageDescription/Check.hs @@ -428,6 +428,8 @@ checkPackageDescription (PackageBuildImpossible $ IllegalLibraryName pn) -- § Fields check. + checkP (hasPrivateDependencies pkg) + (PackageDistInexcusable HasPrivateDependencies) checkNull category_ (PackageDistSuspicious MissingFieldCategory) diff --git a/Cabal/src/Distribution/PackageDescription/Check/Warning.hs b/Cabal/src/Distribution/PackageDescription/Check/Warning.hs index 859b3f12c50..1807d1944e5 100644 --- a/Cabal/src/Distribution/PackageDescription/Check/Warning.hs +++ b/Cabal/src/Distribution/PackageDescription/Check/Warning.hs @@ -279,6 +279,7 @@ data CheckExplanation | MissingSourceControl | MissingExpectedDocFiles Bool [FilePath] | WrongFieldForExpectedDocFiles Bool String [FilePath] + | HasPrivateDependencies deriving (Eq, Ord, Show) -- TODO Some checks have a constructor in list form @@ -441,6 +442,7 @@ data CheckExplanationID | CIMissingSourceControl | CIMissingExpectedDocFiles | CIWrongFieldForExpectedDocFiles + | CIHasPrivateDependencies deriving (Eq, Ord, Show, Enum, Bounded) checkExplanationId :: CheckExplanation -> CheckExplanationID @@ -582,6 +584,7 @@ checkExplanationId (UnknownDirectory{}) = CIUnknownDirectory checkExplanationId (MissingSourceControl{}) = CIMissingSourceControl checkExplanationId (MissingExpectedDocFiles{}) = CIMissingExpectedDocFiles checkExplanationId (WrongFieldForExpectedDocFiles{}) = CIWrongFieldForExpectedDocFiles +checkExplanationId (HasPrivateDependencies{}) = CIHasPrivateDependencies type CheckExplanationIDString = String @@ -728,6 +731,7 @@ ppCheckExplanationId CIUnknownDirectory = "unknown-directory" ppCheckExplanationId CIMissingSourceControl = "no-repository" ppCheckExplanationId CIMissingExpectedDocFiles = "no-docs" ppCheckExplanationId CIWrongFieldForExpectedDocFiles = "doc-place" +ppCheckExplanationId CIHasPrivateDependencies = "has-private-deps" -- String: the unrecognised 'CheckExplanationIDString' itself. readExplanationID @@ -1460,6 +1464,10 @@ ppExplanation (WrongFieldForExpectedDocFiles extraDocFileSupport field paths) = if extraDocFileSupport then "extra-doc-files" else "extra-source-files" +ppExplanation HasPrivateDependencies = + "Private dependencies are in a feature-preview state, " + ++ "therefore packages using them cannot be uploaded to hackage.\n" + ++ "For instance, how would hackage display the private dependencies of the package?" -- * Formatting utilities From 4312d238ca12c224fcb54d82a9a585eeb04978c8 Mon Sep 17 00:00:00 2001 From: Rodrigo Mesquita Date: Fri, 12 Apr 2024 15:14:48 +0100 Subject: [PATCH 03/12] Revert "Make Cabal check fail on private deps" This reverts commit c3b50133e21691022d00328e1af6170a39a556af. We don't need to fail in cabal check for private dependencies in particular because hackage will already reject packages whose Cabal version is "too new" to prevent experimental features to be used in hackage. This way, it is hackage which controls when private dependencies make it there, rather than controlling this via the Cabal version. --- Cabal-syntax/src/Distribution/Types/PackageDescription.hs | 8 -------- Cabal/src/Distribution/PackageDescription/Check.hs | 2 -- .../src/Distribution/PackageDescription/Check/Warning.hs | 8 -------- 3 files changed, 18 deletions(-) diff --git a/Cabal-syntax/src/Distribution/Types/PackageDescription.hs b/Cabal-syntax/src/Distribution/Types/PackageDescription.hs index 61d91db4ab9..cec1014d222 100644 --- a/Cabal-syntax/src/Distribution/Types/PackageDescription.hs +++ b/Cabal-syntax/src/Distribution/Types/PackageDescription.hs @@ -34,7 +34,6 @@ module Distribution.Types.PackageDescription , buildType , emptyPackageDescription , hasPublicLib - , hasPrivateDependencies , hasLibs , allLibraries , withLib @@ -60,7 +59,6 @@ module Distribution.Types.PackageDescription import Distribution.Compat.Prelude import Prelude () -import qualified Data.List -- lens @@ -368,12 +366,6 @@ allBuildDepends pd = do [(Nothing, d) | d <- targetBuildDepends bi] ++ [(Just p, d) | PrivateDependency p ds <- targetPrivateBuildDepends bi, d <- ds] --- | Does this package have any private dependencies? At the moment, cabal --- check will reject any packages that do. -hasPrivateDependencies :: PackageDescription -> Bool -hasPrivateDependencies pd = not . Data.List.null $ - concatMap targetPrivateBuildDepends (allBuildInfo pd) - -- | Get the combined build-depends entries of all enabled components, per the -- given request spec. enabledBuildDepends :: PackageDescription -> ComponentRequestedSpec -> [(Maybe PrivateAlias, Dependency)] diff --git a/Cabal/src/Distribution/PackageDescription/Check.hs b/Cabal/src/Distribution/PackageDescription/Check.hs index dc16c1bf6b7..79123f7f9df 100644 --- a/Cabal/src/Distribution/PackageDescription/Check.hs +++ b/Cabal/src/Distribution/PackageDescription/Check.hs @@ -428,8 +428,6 @@ checkPackageDescription (PackageBuildImpossible $ IllegalLibraryName pn) -- § Fields check. - checkP (hasPrivateDependencies pkg) - (PackageDistInexcusable HasPrivateDependencies) checkNull category_ (PackageDistSuspicious MissingFieldCategory) diff --git a/Cabal/src/Distribution/PackageDescription/Check/Warning.hs b/Cabal/src/Distribution/PackageDescription/Check/Warning.hs index 1807d1944e5..859b3f12c50 100644 --- a/Cabal/src/Distribution/PackageDescription/Check/Warning.hs +++ b/Cabal/src/Distribution/PackageDescription/Check/Warning.hs @@ -279,7 +279,6 @@ data CheckExplanation | MissingSourceControl | MissingExpectedDocFiles Bool [FilePath] | WrongFieldForExpectedDocFiles Bool String [FilePath] - | HasPrivateDependencies deriving (Eq, Ord, Show) -- TODO Some checks have a constructor in list form @@ -442,7 +441,6 @@ data CheckExplanationID | CIMissingSourceControl | CIMissingExpectedDocFiles | CIWrongFieldForExpectedDocFiles - | CIHasPrivateDependencies deriving (Eq, Ord, Show, Enum, Bounded) checkExplanationId :: CheckExplanation -> CheckExplanationID @@ -584,7 +582,6 @@ checkExplanationId (UnknownDirectory{}) = CIUnknownDirectory checkExplanationId (MissingSourceControl{}) = CIMissingSourceControl checkExplanationId (MissingExpectedDocFiles{}) = CIMissingExpectedDocFiles checkExplanationId (WrongFieldForExpectedDocFiles{}) = CIWrongFieldForExpectedDocFiles -checkExplanationId (HasPrivateDependencies{}) = CIHasPrivateDependencies type CheckExplanationIDString = String @@ -731,7 +728,6 @@ ppCheckExplanationId CIUnknownDirectory = "unknown-directory" ppCheckExplanationId CIMissingSourceControl = "no-repository" ppCheckExplanationId CIMissingExpectedDocFiles = "no-docs" ppCheckExplanationId CIWrongFieldForExpectedDocFiles = "doc-place" -ppCheckExplanationId CIHasPrivateDependencies = "has-private-deps" -- String: the unrecognised 'CheckExplanationIDString' itself. readExplanationID @@ -1464,10 +1460,6 @@ ppExplanation (WrongFieldForExpectedDocFiles extraDocFileSupport field paths) = if extraDocFileSupport then "extra-doc-files" else "extra-source-files" -ppExplanation HasPrivateDependencies = - "Private dependencies are in a feature-preview state, " - ++ "therefore packages using them cannot be uploaded to hackage.\n" - ++ "For instance, how would hackage display the private dependencies of the package?" -- * Formatting utilities From c20201bff9d8007b5703fbfbfb5b56babbdd4895 Mon Sep 17 00:00:00 2001 From: Rodrigo Mesquita Date: Fri, 12 Apr 2024 15:54:53 +0100 Subject: [PATCH 04/12] private deps: Introduce tests for Same Scope Names --- .../same-scope-name/cabal.project.scenea | 1 + .../same-scope-name/cabal.project.sceneb | 1 + .../same-scope-name/cabal.project.scenec | 1 + .../PrivateDeps/same-scope-name/cabal.test.hs | 31 +++++++++++++++++++ .../same-scope-name/pkgA/CHANGELOG.md | 5 +++ .../same-scope-name/pkgA/pkgA.cabal | 17 ++++++++++ .../same-scope-name/pkgA/src/MyLib.hs | 4 +++ .../same-scope-name/pkgB/CHANGELOG.md | 5 +++ .../same-scope-name/pkgB/pkgB.cabal | 17 ++++++++++ .../same-scope-name/pkgB/src/MyLib.hs | 4 +++ .../same-scope-name/pkgC/CHANGELOG.md | 5 +++ .../same-scope-name/pkgC/pkgC.cabal | 23 ++++++++++++++ .../same-scope-name/pkgC/src/MyLib.hs | 4 +++ .../same-scope-name/pkgD/CHANGELOG.md | 5 +++ .../same-scope-name/pkgD/pkgD.cabal | 19 ++++++++++++ .../same-scope-name/pkgD/src/MyLib.hs | 4 +++ .../repo/libA-0.1.0.0/CHANGELOG.md | 5 +++ .../repo/libA-0.1.0.0/libA.cabal | 16 ++++++++++ .../repo/libA-0.1.0.0/src/MyLib.hs | 4 +++ .../repo/libA-0.2.0.0/CHANGELOG.md | 5 +++ .../repo/libA-0.2.0.0/libA.cabal | 16 ++++++++++ .../repo/libA-0.2.0.0/src/MyLib.hs | 4 +++ 22 files changed, 196 insertions(+) create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/cabal.project.scenea create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/cabal.project.sceneb create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/cabal.project.scenec create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/cabal.test.hs create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgA/CHANGELOG.md create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgA/pkgA.cabal create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgA/src/MyLib.hs create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgB/CHANGELOG.md create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgB/pkgB.cabal create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgB/src/MyLib.hs create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgC/CHANGELOG.md create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgC/pkgC.cabal create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgC/src/MyLib.hs create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgD/CHANGELOG.md create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgD/pkgD.cabal create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgD/src/MyLib.hs create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/repo/libA-0.1.0.0/CHANGELOG.md create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/repo/libA-0.1.0.0/libA.cabal create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/repo/libA-0.1.0.0/src/MyLib.hs create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/repo/libA-0.2.0.0/CHANGELOG.md create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/repo/libA-0.2.0.0/libA.cabal create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/repo/libA-0.2.0.0/src/MyLib.hs diff --git a/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/cabal.project.scenea b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/cabal.project.scenea new file mode 100644 index 00000000000..7e858b21c61 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/cabal.project.scenea @@ -0,0 +1 @@ +packages: pkgA, pkgB diff --git a/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/cabal.project.sceneb b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/cabal.project.sceneb new file mode 100644 index 00000000000..5ed273644e7 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/cabal.project.sceneb @@ -0,0 +1 @@ +packages: pkgC diff --git a/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/cabal.project.scenec b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/cabal.project.scenec new file mode 100644 index 00000000000..932121d3d42 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/cabal.project.scenec @@ -0,0 +1 @@ +packages: pkgD diff --git a/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/cabal.test.hs b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/cabal.test.hs new file mode 100644 index 00000000000..293588f009e --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/cabal.test.hs @@ -0,0 +1,31 @@ +import Test.Cabal.Prelude + +{- +Checks that: + +(a) If there are two scopes with the same name in two separate packages, the same +name shouldn't matter and should the scopes should be solved independently +because they are in different packages + +(b) If the scopes with the same name are in same package but in different +components, they should be merged together and fail because of the conflict + +(c) If the scopes are in the same component, then they should be merged and fail +because of the conflict too +-} + +main = + cabalTest $ recordMode DoNotRecord $ do + withProjectFile "cabal.project.scenea" $ + withRepo "repo" $ do + -- Succeeds because SameName from pkgA and SameName from pkgB do not collide. + cabal "build" ["pkgA"] + withProjectFile "cabal.project.sceneb" $ + withRepo "repo" $ do + -- Fails because SameName from pkgC in its two separate components + cabal "build" ["pkgC"] + withProjectFile "cabal.project.scenec" $ + withRepo "repo" $ do + -- Fails because SameName from pkgD in the same component + cabal "build" ["pkgD"] + diff --git a/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgA/CHANGELOG.md b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgA/CHANGELOG.md new file mode 100644 index 00000000000..6c1d0fed1d1 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgA/CHANGELOG.md @@ -0,0 +1,5 @@ +# Revision history for pkgA + +## 0.1.0.0 -- YYYY-mm-dd + +* First version. Released on an unsuspecting world. diff --git a/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgA/pkgA.cabal b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgA/pkgA.cabal new file mode 100644 index 00000000000..1c667562329 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgA/pkgA.cabal @@ -0,0 +1,17 @@ +cabal-version: 3.0 +name: pkgA +version: 0.1.0.0 +license: NONE +build-type: Simple +extra-doc-files: CHANGELOG.md + +common warnings + ghc-options: -Wall + +library + import: warnings + exposed-modules: MyLib + private-build-depends: SameName with (libA == 0.1.0.0) + build-depends: base, pkgB + hs-source-dirs: src + default-language: Haskell2010 diff --git a/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgA/src/MyLib.hs b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgA/src/MyLib.hs new file mode 100644 index 00000000000..e657c4403f6 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgA/src/MyLib.hs @@ -0,0 +1,4 @@ +module MyLib (someFunc) where + +someFunc :: IO () +someFunc = putStrLn "someFunc" diff --git a/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgB/CHANGELOG.md b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgB/CHANGELOG.md new file mode 100644 index 00000000000..6c1d0fed1d1 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgB/CHANGELOG.md @@ -0,0 +1,5 @@ +# Revision history for pkgA + +## 0.1.0.0 -- YYYY-mm-dd + +* First version. Released on an unsuspecting world. diff --git a/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgB/pkgB.cabal b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgB/pkgB.cabal new file mode 100644 index 00000000000..d1cef9a5ecd --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgB/pkgB.cabal @@ -0,0 +1,17 @@ +cabal-version: 3.0 +name: pkgB +version: 0.1.0.0 +license: NONE +build-type: Simple +extra-doc-files: CHANGELOG.md + +common warnings + ghc-options: -Wall + +library + import: warnings + exposed-modules: MyLib + private-build-depends: SameName with (libA == 0.2.0.0) + build-depends: base + hs-source-dirs: src + default-language: Haskell2010 diff --git a/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgB/src/MyLib.hs b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgB/src/MyLib.hs new file mode 100644 index 00000000000..e657c4403f6 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgB/src/MyLib.hs @@ -0,0 +1,4 @@ +module MyLib (someFunc) where + +someFunc :: IO () +someFunc = putStrLn "someFunc" diff --git a/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgC/CHANGELOG.md b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgC/CHANGELOG.md new file mode 100644 index 00000000000..6c1d0fed1d1 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgC/CHANGELOG.md @@ -0,0 +1,5 @@ +# Revision history for pkgA + +## 0.1.0.0 -- YYYY-mm-dd + +* First version. Released on an unsuspecting world. diff --git a/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgC/pkgC.cabal b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgC/pkgC.cabal new file mode 100644 index 00000000000..7a75f05b208 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgC/pkgC.cabal @@ -0,0 +1,23 @@ +cabal-version: 3.0 +name: pkgC +version: 0.1.0.0 +license: NONE +build-type: Simple +extra-doc-files: CHANGELOG.md + +common warnings + ghc-options: -Wall + +library + import: warnings + exposed-modules: MyLib + private-build-depends: SameName with (libA == 0.1.0.0) + build-depends: base + hs-source-dirs: src + default-language: Haskell2010 + +executable myexe + main-is: Main.hs + private-build-depends: SameName with (libA == 0.2.0.0) + default-language: Haskell2010 + build-depends: base diff --git a/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgC/src/MyLib.hs b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgC/src/MyLib.hs new file mode 100644 index 00000000000..e657c4403f6 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgC/src/MyLib.hs @@ -0,0 +1,4 @@ +module MyLib (someFunc) where + +someFunc :: IO () +someFunc = putStrLn "someFunc" diff --git a/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgD/CHANGELOG.md b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgD/CHANGELOG.md new file mode 100644 index 00000000000..6c1d0fed1d1 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgD/CHANGELOG.md @@ -0,0 +1,5 @@ +# Revision history for pkgA + +## 0.1.0.0 -- YYYY-mm-dd + +* First version. Released on an unsuspecting world. diff --git a/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgD/pkgD.cabal b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgD/pkgD.cabal new file mode 100644 index 00000000000..e3f6fe5644f --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgD/pkgD.cabal @@ -0,0 +1,19 @@ +cabal-version: 3.0 +name: pkgD +version: 0.1.0.0 +license: NONE +build-type: Simple +extra-doc-files: CHANGELOG.md + +common warnings + ghc-options: -Wall + +library + import: warnings + exposed-modules: MyLib + private-build-depends: SameName with (libA == 0.1.0.0), + SameName with (libA == 0.2.0.0) + build-depends: base + hs-source-dirs: src + default-language: Haskell2010 + diff --git a/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgD/src/MyLib.hs b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgD/src/MyLib.hs new file mode 100644 index 00000000000..e657c4403f6 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgD/src/MyLib.hs @@ -0,0 +1,4 @@ +module MyLib (someFunc) where + +someFunc :: IO () +someFunc = putStrLn "someFunc" diff --git a/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/repo/libA-0.1.0.0/CHANGELOG.md b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/repo/libA-0.1.0.0/CHANGELOG.md new file mode 100644 index 00000000000..4e6fa27dd90 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/repo/libA-0.1.0.0/CHANGELOG.md @@ -0,0 +1,5 @@ +# Revision history for libA + +## 0.1.0.0 -- YYYY-mm-dd + +* First version. Released on an unsuspecting world. diff --git a/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/repo/libA-0.1.0.0/libA.cabal b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/repo/libA-0.1.0.0/libA.cabal new file mode 100644 index 00000000000..ced6e1bbe92 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/repo/libA-0.1.0.0/libA.cabal @@ -0,0 +1,16 @@ +cabal-version: 3.0 +name: libA +version: 0.1.0.0 +license: NONE +build-type: Simple +extra-doc-files: CHANGELOG.md + +common warnings + ghc-options: -Wall + +library + import: warnings + exposed-modules: MyLib + build-depends: base + hs-source-dirs: src + default-language: Haskell2010 diff --git a/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/repo/libA-0.1.0.0/src/MyLib.hs b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/repo/libA-0.1.0.0/src/MyLib.hs new file mode 100644 index 00000000000..e657c4403f6 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/repo/libA-0.1.0.0/src/MyLib.hs @@ -0,0 +1,4 @@ +module MyLib (someFunc) where + +someFunc :: IO () +someFunc = putStrLn "someFunc" diff --git a/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/repo/libA-0.2.0.0/CHANGELOG.md b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/repo/libA-0.2.0.0/CHANGELOG.md new file mode 100644 index 00000000000..4e6fa27dd90 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/repo/libA-0.2.0.0/CHANGELOG.md @@ -0,0 +1,5 @@ +# Revision history for libA + +## 0.1.0.0 -- YYYY-mm-dd + +* First version. Released on an unsuspecting world. diff --git a/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/repo/libA-0.2.0.0/libA.cabal b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/repo/libA-0.2.0.0/libA.cabal new file mode 100644 index 00000000000..45452d179b1 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/repo/libA-0.2.0.0/libA.cabal @@ -0,0 +1,16 @@ +cabal-version: 3.0 +name: libA +version: 0.2.0.0 +license: NONE +build-type: Simple +extra-doc-files: CHANGELOG.md + +common warnings + ghc-options: -Wall + +library + import: warnings + exposed-modules: MyLib + build-depends: base + hs-source-dirs: src + default-language: Haskell2010 diff --git a/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/repo/libA-0.2.0.0/src/MyLib.hs b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/repo/libA-0.2.0.0/src/MyLib.hs new file mode 100644 index 00000000000..e657c4403f6 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/repo/libA-0.2.0.0/src/MyLib.hs @@ -0,0 +1,4 @@ +module MyLib (someFunc) where + +someFunc :: IO () +someFunc = putStrLn "someFunc" From 97fbc907fe87c280acb173ec358745d1d8b7a2d8 Mon Sep 17 00:00:00 2001 From: Rodrigo Mesquita Date: Fri, 12 Apr 2024 17:26:21 +0100 Subject: [PATCH 05/12] private deps: Support for plan.json --- .../Distribution/Client/ProjectPlanOutput.hs | 31 ++++++++++++++----- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/cabal-install/src/Distribution/Client/ProjectPlanOutput.hs b/cabal-install/src/Distribution/Client/ProjectPlanOutput.hs index 4e0773484f8..01169449496 100644 --- a/cabal-install/src/Distribution/Client/ProjectPlanOutput.hs +++ b/cabal-install/src/Distribution/Client/ProjectPlanOutput.hs @@ -21,11 +21,12 @@ module Distribution.Client.ProjectPlanOutput , argsEquivalentOfGhcEnvironmentFile ) where +import Data.Either import Distribution.Client.DistDirLayout import Distribution.Client.HashValue (hashValue, showHashValue) import Distribution.Client.ProjectBuilding.Types import Distribution.Client.ProjectPlanning.Types -import Distribution.Client.Types.ConfiguredId (confInstId) +import Distribution.Client.Types.ConfiguredId (ConfiguredId, confInstId) import Distribution.Client.Types.PackageLocation (PackageLocation (..)) import Distribution.Client.Types.Repo (RemoteRepo (..), Repo (..)) import Distribution.Client.Types.SourceRepo (SourceRepoMaybe, SourceRepositoryPackage (..)) @@ -199,9 +200,9 @@ encodePlanAsJson distDirLayout elaboratedInstallPlan elaboratedSharedConfig = J.object $ [ comp2str c J..= J.object - ( [ "depends" J..= map (jdisplay . confInstId) (map (\(p, _, _) -> p) ldeps) - , "exe-depends" J..= map (jdisplay . confInstId) edeps - ] + ( handleLibDepends ldeps + ++ [ "exe-depends" J..= map (jdisplay . confInstId) edeps + ] ++ bin_file c ) | (c, (ldeps, edeps)) <- @@ -212,10 +213,10 @@ encodePlanAsJson distDirLayout elaboratedInstallPlan elaboratedSharedConfig = ] in ["components" J..= components] ElabComponent comp -> - [ "depends" J..= map (jdisplay . confInstId) (map (\(p, _, _) -> p) $ elabLibDependencies elab) - , "exe-depends" J..= map jdisplay (elabExeDependencies elab) - , "component-name" J..= J.String (comp2str (compSolverName comp)) - ] + handleLibDepends (elabLibDependencies elab) + ++ [ "exe-depends" J..= map jdisplay (elabExeDependencies elab) + , "component-name" J..= J.String (comp2str (compSolverName comp)) + ] ++ bin_file (compSolverName comp) where -- \| Only add build-info file location if the Setup.hs CLI @@ -321,6 +322,20 @@ encodePlanAsJson distDirLayout elaboratedInstallPlan elaboratedSharedConfig = then dist_dir "build" prettyShow s ("lib" ++ prettyShow s) <.> dllExtension plat else InstallDirs.bindir (elabInstallDirs elab) ("lib" ++ prettyShow s) <.> dllExtension plat + handleLibDepends :: [(ConfiguredId, Bool, Maybe PrivateAlias)] -> [J.Pair] + handleLibDepends deps = + let (publicDeps, privateDeps) = + partitionEithers $ + map + ( \(p, _, mb) -> case mb of + Nothing -> Left p + Just alias -> Right (alias, p) + ) + deps + in [ "depends" J..= map (jdisplay . confInstId) publicDeps + , "private-depends" J..= J.object (map (\(al, p) -> prettyShow al J..= (jdisplay . confInstId) p) privateDeps) + ] + comp2str :: ComponentDeps.Component -> String comp2str = prettyShow From b6ff81e9d98373088d3596ea1526924ed508e6a2 Mon Sep 17 00:00:00 2001 From: Rodrigo Mesquita Date: Mon, 15 Apr 2024 14:51:49 +0100 Subject: [PATCH 06/12] refactor: Use IsPrivate instead of Maybe PrivateAlias Improvement/refactor in the implementation of private dependencies to use the more descriptive `IsPrivate` type rather than the isomorphic `Maybe PrivateAlias` --- .../PackageDescription/Configuration.hs | 6 ++-- .../src/Distribution/Types/Dependency.hs | 14 +++++++- .../Distribution/Types/PackageDescription.hs | 12 +++---- .../Backpack/ConfiguredComponent.hs | 16 ++++----- .../Backpack/PreExistingComponent.hs | 6 ++-- Cabal/src/Distribution/Backpack/UnifyM.hs | 8 ++--- Cabal/src/Distribution/Simple/Configure.hs | 36 +++++++++---------- Cabal/src/Distribution/Simple/GHC/Internal.hs | 2 +- Cabal/src/Distribution/Simple/Setup/Config.hs | 6 ++-- .../Distribution/Types/ComponentInclude.hs | 4 +-- .../src/Distribution/Types/GivenComponent.hs | 2 +- .../Distribution/Types/LocalBuildConfig.hs | 2 +- .../src/Distribution/Types/LocalBuildInfo.hs | 2 +- .../Solver/Modular/ConfiguredConversion.hs | 10 +++--- .../Solver/Types/InstSolverPackage.hs | 4 +-- .../Solver/Types/ResolverPackage.hs | 4 +-- .../Solver/Types/SolverPackage.hs | 4 +-- .../src/Distribution/Client/Configure.hs | 2 +- .../src/Distribution/Client/Dependency.hs | 32 ++++++++--------- .../src/Distribution/Client/Install.hs | 3 +- .../Distribution/Client/ProjectPlanOutput.hs | 6 ++-- .../Distribution/Client/ProjectPlanning.hs | 8 ++--- .../Client/ProjectPlanning/Types.hs | 12 +++---- .../Distribution/Client/SolverInstallPlan.hs | 8 ++--- 24 files changed, 111 insertions(+), 98 deletions(-) diff --git a/Cabal-syntax/src/Distribution/PackageDescription/Configuration.hs b/Cabal-syntax/src/Distribution/PackageDescription/Configuration.hs index 397c4a40ad0..83cc5633b01 100644 --- a/Cabal-syntax/src/Distribution/PackageDescription/Configuration.hs +++ b/Cabal-syntax/src/Distribution/PackageDescription/Configuration.hs @@ -464,7 +464,7 @@ finalizePD :: FlagAssignment -- ^ Explicitly specified flag assignments -> ComponentRequestedSpec - -> (Maybe PrivateAlias -> Dependency -> Bool) + -> (IsPrivate -> Dependency -> Bool) -- ^ Is a given dependency satisfiable from the set of -- available packages? If this is unknown then use -- True. @@ -539,8 +539,8 @@ finalizePD check ds = let missingDeps = Dependencies - (filter (not . satisfyDep Nothing) (publicDependencies ds)) - (mapMaybe (\(PrivateDependency priv pds) -> case filter (not . satisfyDep (Just priv)) pds of [] -> Nothing; pds' -> Just (PrivateDependency priv pds')) (privateDependencies ds)) + (filter (not . satisfyDep Public) (publicDependencies ds)) + (mapMaybe (\(PrivateDependency priv pds) -> case filter (not . satisfyDep (Private priv)) pds of [] -> Nothing; pds' -> Just (PrivateDependency priv pds')) (privateDependencies ds)) in if null (publicDependencies missingDeps) && null (privateDependencies missingDeps) then DepOk else MissingDeps missingDeps diff --git a/Cabal-syntax/src/Distribution/Types/Dependency.hs b/Cabal-syntax/src/Distribution/Types/Dependency.hs index a50c863d6bd..63c5e196d7f 100644 --- a/Cabal-syntax/src/Distribution/Types/Dependency.hs +++ b/Cabal-syntax/src/Distribution/Types/Dependency.hs @@ -1,6 +1,7 @@ {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE InstanceSigs #-} +{-# LANGUAGE LambdaCase #-} {-# LANGUAGE ScopedTypeVariables #-} module Distribution.Types.Dependency @@ -16,6 +17,7 @@ module Distribution.Types.Dependency , Dependencies (..) , IsPrivate (..) , mapDependencies + , foldIsPrivate ) where import Distribution.Compat.Prelude @@ -38,7 +40,7 @@ import qualified Distribution.Compat.NonEmptySet as NES import Distribution.ModuleName import qualified Text.PrettyPrint as PP -data IsPrivate = Private PrivateAlias | Public deriving (Show, Ord, Read, Eq) +data IsPrivate = Private PrivateAlias | Public deriving (Show, Ord, Read, Eq, Generic, Data) data Dependencies = Dependencies {publicDependencies :: [Dependency], privateDependencies :: [PrivateDependency]} deriving (Eq, Show, Generic, Data) @@ -125,6 +127,10 @@ mkDependency pn vr lb = Dependency pn vr (NES.map conv lb) | ln == pn' = LMainLibName | otherwise = l +instance Binary IsPrivate +instance Structured IsPrivate +instance NFData IsPrivate where rnf = genericRnf + instance Binary Dependency instance Structured Dependency instance NFData Dependency where rnf = genericRnf @@ -247,3 +253,9 @@ mainLibSet = NES.singleton LMainLibName simplifyDependency :: Dependency -> Dependency simplifyDependency (Dependency name range comps) = Dependency name (simplifyVersionRange range) comps + +-- | Deconstruct 'IsPrivate' using a function on a 'PrivateAlias' or a default value; akin to 'maybe'. +foldIsPrivate :: a -> (PrivateAlias -> a) -> IsPrivate -> a +foldIsPrivate d f = \case + Public -> d + Private a -> f a diff --git a/Cabal-syntax/src/Distribution/Types/PackageDescription.hs b/Cabal-syntax/src/Distribution/Types/PackageDescription.hs index cec1014d222..b994f9c8813 100644 --- a/Cabal-syntax/src/Distribution/Types/PackageDescription.hs +++ b/Cabal-syntax/src/Distribution/Types/PackageDescription.hs @@ -360,20 +360,20 @@ enabledBuildInfos pkg enabled = -- ------------------------------------------------------------ -- | Get the combined build-depends entries of all components. -allBuildDepends :: PackageDescription -> [(Maybe PrivateAlias, Dependency)] +allBuildDepends :: PackageDescription -> [(IsPrivate, Dependency)] allBuildDepends pd = do bi <- allBuildInfo pd - [(Nothing, d) | d <- targetBuildDepends bi] - ++ [(Just p, d) | PrivateDependency p ds <- targetPrivateBuildDepends bi, d <- ds] + [(Public, d) | d <- targetBuildDepends bi] + ++ [(Private p, d) | PrivateDependency p ds <- targetPrivateBuildDepends bi, d <- ds] -- | Get the combined build-depends entries of all enabled components, per the -- given request spec. -enabledBuildDepends :: PackageDescription -> ComponentRequestedSpec -> [(Maybe PrivateAlias, Dependency)] +enabledBuildDepends :: PackageDescription -> ComponentRequestedSpec -> [(IsPrivate, Dependency)] enabledBuildDepends spec pd = do bi <- enabledBuildInfos spec pd - [(Nothing, d) | d <- targetBuildDepends bi] - ++ [(Just p, d) | PrivateDependency p ds <- targetPrivateBuildDepends bi, d <- ds] + [(Public, d) | d <- targetBuildDepends bi] + ++ [(Private p, d) | PrivateDependency p ds <- targetPrivateBuildDepends bi, d <- ds] updatePackageDescription :: HookedBuildInfo -> PackageDescription -> PackageDescription updatePackageDescription (mb_lib_bi, exe_bi) p = diff --git a/Cabal/src/Distribution/Backpack/ConfiguredComponent.hs b/Cabal/src/Distribution/Backpack/ConfiguredComponent.hs index a542bc98dcb..22045ca3b6c 100644 --- a/Cabal/src/Distribution/Backpack/ConfiguredComponent.hs +++ b/Cabal/src/Distribution/Backpack/ConfiguredComponent.hs @@ -100,7 +100,7 @@ dispConfiguredComponent cc = mkConfiguredComponent :: PackageDescription -> ComponentId - -> [(AnnotatedId ComponentId, Maybe PrivateAlias)] -- lib deps + -> [(AnnotatedId ComponentId, IsPrivate)] -- lib deps -> [AnnotatedId ComponentId] -- exe deps -> Component -> LogProgress ConfiguredComponent @@ -121,7 +121,7 @@ mkConfiguredComponent pkg_descr this_cid lib_deps exe_deps component = do , ci_renaming = rns , ci_implicit = False , -- Mixins can't be private - ci_alias = Nothing + ci_alias = Public } -- Any @build-depends@ which is not explicitly mentioned in @@ -171,7 +171,7 @@ mkConfiguredComponent pkg_descr this_cid lib_deps exe_deps component = do -- A function from PackageName -> Maybe PrivateQualifier -> ComponentName -> ResolvedComponentId type ConfiguredComponentMap = - Map (PackageName, Maybe PrivateAlias) (Map ComponentName ((AnnotatedId ComponentId))) + Map (PackageName, IsPrivate) (Map ComponentName ((AnnotatedId ComponentId))) toConfiguredComponent :: PackageDescription @@ -184,7 +184,7 @@ toConfiguredComponent pkg_descr this_cid lib_dep_map exe_dep_map component = do lib_deps <- if newPackageDepsBehaviour pkg_descr then fmap concat $ - forM ([(d, Nothing) | d <- targetBuildDepends bi] ++ [(d, Just alias) | (PrivateDependency alias ds) <- targetPrivateBuildDepends bi, d <- ds]) $ + forM ([(d, Public) | d <- targetBuildDepends bi] ++ [(d, Private alias) | (PrivateDependency alias ds) <- targetPrivateBuildDepends bi, d <- ds]) $ \((Dependency name _ sublibs), alias) -> do case Map.lookup (name, alias) lib_dep_map of Nothing -> @@ -192,7 +192,7 @@ toConfiguredComponent pkg_descr this_cid lib_dep_map exe_dep_map component = do text "Dependency on unbuildable" <+> text "package" <+> pretty name - <+> maybe mempty pretty alias + <+> foldIsPrivate mempty pretty alias <+> text (show lib_dep_map) Just pkg -> do -- Return all library components @@ -205,7 +205,7 @@ toConfiguredComponent pkg_descr this_cid lib_dep_map exe_dep_map component = do <+> text (showLibraryName lib) <+> text "from" <+> pretty name - <+> maybe mempty pretty alias + <+> foldIsPrivate mempty pretty alias Just v -> return (v, alias) else return old_style_lib_deps mkConfiguredComponent @@ -243,7 +243,7 @@ toConfiguredComponent pkg_descr this_cid lib_dep_map exe_dep_map component = do -- which the package is attempting to use (those deps are only -- fed in when cabal-install uses this codepath.) -- TODO: Let cabal-install request errors here - Just exe <- [Map.lookup (CExeName cn) =<< Map.lookup (pn, Nothing) exe_dep_map] + Just exe <- [Map.lookup (CExeName cn) =<< Map.lookup (pn, Public) exe_dep_map] ] -- | Also computes the 'ComponentId', and sets cc_public if necessary. @@ -299,7 +299,7 @@ extendConfiguredComponentMap extendConfiguredComponentMap cc = Map.insertWith Map.union - ((pkgName (cc_pkgid cc)), Nothing) + ((pkgName (cc_pkgid cc)), Public) (Map.singleton (cc_name cc) (cc_ann_id cc)) -- Compute the 'ComponentId's for a graph of 'Component's. The diff --git a/Cabal/src/Distribution/Backpack/PreExistingComponent.hs b/Cabal/src/Distribution/Backpack/PreExistingComponent.hs index aeca962b299..3c5bc90e1f5 100644 --- a/Cabal/src/Distribution/Backpack/PreExistingComponent.hs +++ b/Cabal/src/Distribution/Backpack/PreExistingComponent.hs @@ -27,7 +27,7 @@ import Distribution.Types.AnnotatedId data PromisedComponent = PromisedComponent { pr_pkgname :: PackageName , pr_cid :: AnnotatedId ComponentId - , pr_alias :: Maybe PrivateAlias + , pr_alias :: IsPrivate } instance Package PromisedComponent where @@ -48,13 +48,13 @@ data PreExistingComponent = PreExistingComponent , pc_cid :: ComponentId , pc_open_uid :: OpenUnitId , pc_shape :: ModuleShape - , pc_alias :: Maybe PrivateAlias + , pc_alias :: IsPrivate } -- | Convert an 'InstalledPackageInfo' into a 'PreExistingComponent', -- which was brought into scope under the 'PackageName' (important for -- a package qualified reference.) -ipiToPreExistingComponent :: Maybe PrivateAlias -> InstalledPackageInfo -> PreExistingComponent +ipiToPreExistingComponent :: IsPrivate -> InstalledPackageInfo -> PreExistingComponent ipiToPreExistingComponent alias ipi = PreExistingComponent { pc_pkgname = packageName ipi diff --git a/Cabal/src/Distribution/Backpack/UnifyM.hs b/Cabal/src/Distribution/Backpack/UnifyM.hs index 11c82b65751..46d1be8d5a1 100644 --- a/Cabal/src/Distribution/Backpack/UnifyM.hs +++ b/Cabal/src/Distribution/Backpack/UnifyM.hs @@ -625,16 +625,16 @@ convertInclude -- Expand the alias let prepend_alias mn = case alias of - Just (PrivateAlias alias_mn) -> combineModuleName alias_mn mn - Nothing -> mn + Private (PrivateAlias alias_mn) -> combineModuleName alias_mn mn + Public -> mn let pre_prov_scope' = map (first prepend_alias) pre_prov_scope let prov_rns'' = case prov_rns' of DefaultRenaming -> case alias of - Nothing -> DefaultRenaming - Just{} -> ModuleRenaming (map ((\x -> (x, prepend_alias x)) . fst) (pre_prov_scope)) + Public -> DefaultRenaming + Private{} -> ModuleRenaming (map ((\x -> (x, prepend_alias x)) . fst) (pre_prov_scope)) ModuleRenaming rn -> ModuleRenaming (map (\(x, y) -> (x, prepend_alias y)) rn) -- Can't happen, expanded above HidingRenaming{} -> error "unreachable" diff --git a/Cabal/src/Distribution/Simple/Configure.hs b/Cabal/src/Distribution/Simple/Configure.hs index c927c8974e4..abc36cdf78b 100644 --- a/Cabal/src/Distribution/Simple/Configure.hs +++ b/Cabal/src/Distribution/Simple/Configure.hs @@ -819,9 +819,9 @@ computeLocalBuildConfig cfg comp programDb = do data PackageInfo = PackageInfo { internalPackageSet :: Set LibraryName - , promisedDepsSet :: Map (PackageName, ComponentName, Maybe PrivateAlias) ComponentId + , promisedDepsSet :: Map (PackageName, ComponentName, IsPrivate) ComponentId , installedPackageSet :: InstalledPackageIndex - , requiredDepsMap :: Map (PackageName, ComponentName, Maybe PrivateAlias) InstalledPackageInfo + , requiredDepsMap :: Map (PackageName, ComponentName, IsPrivate) InstalledPackageInfo } configurePackage @@ -975,7 +975,7 @@ finalizeAndConfigurePackage cfg lbc0 g_pkg_descr comp platform enabled = do -- that is not possible to configure a test-suite to use one -- version of a dependency, and the executable to use another. ( allConstraints :: [(IsPrivate, PackageVersionConstraint)] - , requiredDepsMap :: Map (PackageName, ComponentName, Maybe PrivateAlias) InstalledPackageInfo + , requiredDepsMap :: Map (PackageName, ComponentName, IsPrivate) InstalledPackageInfo ) <- either (dieWithException verbosity) return $ combinedConstraints @@ -1355,7 +1355,7 @@ configureComponents return lbi -mkPromisedDepsSet :: [GivenComponent] -> Map (PackageName, ComponentName, Maybe PrivateAlias) ComponentId +mkPromisedDepsSet :: [GivenComponent] -> Map (PackageName, ComponentName, IsPrivate) ComponentId mkPromisedDepsSet comps = Map.fromList [((pn, CLibName ln, alias), cid) | GivenComponent pn ln cid alias <- comps] -- | Adds the extra program paths from the flags provided to @configure@ as @@ -1459,10 +1459,10 @@ dependencySatisfiable -- ^ installed set -> Set LibraryName -- ^ library components - -> Map (PackageName, ComponentName, Maybe PrivateAlias) ComponentId - -> Map (PackageName, ComponentName, Maybe PrivateAlias) InstalledPackageInfo + -> Map (PackageName, ComponentName, IsPrivate) ComponentId + -> Map (PackageName, ComponentName, IsPrivate) InstalledPackageInfo -- ^ required dependencies - -> (Maybe PrivateAlias -> Dependency -> Bool) + -> (IsPrivate -> Dependency -> Bool) dependencySatisfiable use_external_internal_deps exact_config @@ -1556,7 +1556,7 @@ configureFinalizedPackage -> ConfigFlags -> ComponentRequestedSpec -> [(IsPrivate, PackageVersionConstraint)] - -> (Maybe PrivateAlias -> Dependency -> Bool) + -> (IsPrivate -> Dependency -> Bool) -- ^ tests if a dependency is satisfiable. -- Might say it's satisfiable even when not. -> Compiler @@ -1623,10 +1623,10 @@ configureDependencies :: Verbosity -> UseExternalInternalDeps -> Set LibraryName - -> Map (PackageName, ComponentName, Maybe PrivateAlias) ComponentId + -> Map (PackageName, ComponentName, IsPrivate) ComponentId -> InstalledPackageIndex -- ^ installed packages - -> Map (PackageName, ComponentName, Maybe PrivateAlias) InstalledPackageInfo + -> Map (PackageName, ComponentName, IsPrivate) InstalledPackageInfo -- ^ required deps -> PackageDescription -> ComponentRequestedSpec @@ -1878,17 +1878,17 @@ selectDependency -- ^ Package id of current package -> Set LibraryName -- ^ package libraries - -> Map (PackageName, ComponentName, Maybe PrivateAlias) ComponentId + -> Map (PackageName, ComponentName, IsPrivate) ComponentId -- ^ Set of components that are promised, i.e. are not installed already. See 'PromisedDependency' for more details. -> InstalledPackageIndex -- ^ Installed packages - -> Map (PackageName, ComponentName, Maybe PrivateAlias) InstalledPackageInfo + -> Map (PackageName, ComponentName, IsPrivate) InstalledPackageInfo -- ^ Packages for which we have been given specific deps to -- use -> UseExternalInternalDeps -- ^ Are we configuring a -- single component? - -> Maybe PrivateAlias + -> IsPrivate -> Dependency -> [Either FailedDependency DependencyResolution] selectDependency @@ -2129,7 +2129,7 @@ combinedConstraints -> Either CabalException ( [(IsPrivate, PackageVersionConstraint)] - , Map (PackageName, ComponentName, Maybe PrivateAlias) InstalledPackageInfo + , Map (PackageName, ComponentName, IsPrivate) InstalledPackageInfo ) combinedConstraints constraints dependencies installedPackages = do when (not (null badComponentIds)) $ @@ -2143,11 +2143,11 @@ combinedConstraints constraints dependencies installedPackages = do allConstraints :: [(IsPrivate, PackageVersionConstraint)] allConstraints = constraints - ++ [ (case mAlias of Nothing -> Public; Just a -> Private a, thisPackageVersionConstraint (packageId pkg)) + ++ [ (mAlias, thisPackageVersionConstraint (packageId pkg)) | (_, _, mAlias, _, Just pkg) <- dependenciesPkgInfo ] - idConstraintMap :: Map (PackageName, ComponentName, Maybe PrivateAlias) InstalledPackageInfo + idConstraintMap :: Map (PackageName, ComponentName, IsPrivate) InstalledPackageInfo idConstraintMap = Map.fromList -- NB: do NOT use the packageName from @@ -2157,7 +2157,7 @@ combinedConstraints constraints dependencies installedPackages = do ] -- The dependencies along with the installed package info, if it exists - dependenciesPkgInfo :: [(PackageName, ComponentName, Maybe PrivateAlias, ComponentId, Maybe InstalledPackageInfo)] + dependenciesPkgInfo :: [(PackageName, ComponentName, IsPrivate, ComponentId, Maybe InstalledPackageInfo)] dependenciesPkgInfo = [ (pkgname, CLibName lname, alias, cid, mpkg) | GivenComponent pkgname lname cid alias <- dependencies @@ -2186,7 +2186,7 @@ combinedConstraints constraints dependencies installedPackages = do _ -> ":" <<>> pretty cname <<>> char '=' <<>> pretty cid - <<>> maybe "" (\a -> "=" <<>> pretty a) alias + <<>> foldIsPrivate "" (\a -> "=" <<>> pretty a) alias ) | (pkgname, cname, alias, cid) <- deps ] diff --git a/Cabal/src/Distribution/Simple/GHC/Internal.hs b/Cabal/src/Distribution/Simple/GHC/Internal.hs index 108bba30250..87fc54fc05c 100644 --- a/Cabal/src/Distribution/Simple/GHC/Internal.hs +++ b/Cabal/src/Distribution/Simple/GHC/Internal.hs @@ -672,7 +672,7 @@ getHaskellObjects _implInfo lib lbi clbi pref wanted_obj_ext allow_split_objs -- and is a hack to avoid passing bogus `-package` arguments to GHC. The assumption being that -- in 99% of cases we will include the right `-package` so that the C file finds the right headers. mkGhcOptPackages - :: Map (PackageName, ComponentName, Maybe PrivateAlias) ComponentId + :: Map (PackageName, ComponentName, IsPrivate) ComponentId -> ComponentLocalBuildInfo -> [(OpenUnitId, ModuleRenaming)] mkGhcOptPackages promisedPkgsMap clbi = diff --git a/Cabal/src/Distribution/Simple/Setup/Config.hs b/Cabal/src/Distribution/Simple/Setup/Config.hs index 3e75880946e..60633eb4498 100644 --- a/Cabal/src/Distribution/Simple/Setup/Config.hs +++ b/Cabal/src/Distribution/Simple/Setup/Config.hs @@ -910,9 +910,9 @@ parsecGivenComponent = do else LSubLibName ucn _ <- P.char '=' cid <- parsec - alias <- P.option Nothing $ do + alias <- P.option Public $ do _ <- P.char '=' - Just <$> parsec + Private <$> parsec return $ GivenComponent pn ln cid alias prettyGivenComponent :: GivenComponent -> String @@ -923,7 +923,7 @@ prettyGivenComponent (GivenComponent pn cn cid alias) = LSubLibName n -> ":" ++ prettyShow n ++ "=" ++ prettyShow cid - ++ maybe "" (\a -> "=" ++ prettyShow a) alias + ++ (case alias of Public -> ""; Private a -> "=" ++ prettyShow a) installDirsOptions :: [OptionField (InstallDirs (Flag PathTemplate))] installDirsOptions = diff --git a/Cabal/src/Distribution/Types/ComponentInclude.hs b/Cabal/src/Distribution/Types/ComponentInclude.hs index e2e4057a042..604e0975cc6 100644 --- a/Cabal/src/Distribution/Types/ComponentInclude.hs +++ b/Cabal/src/Distribution/Types/ComponentInclude.hs @@ -7,7 +7,7 @@ module Distribution.Types.ComponentInclude import Distribution.Types.AnnotatedId import Distribution.Types.ComponentName -import Distribution.Types.Dependency (PrivateAlias) +import Distribution.Types.Dependency (IsPrivate) import Distribution.Types.PackageId -- Once ci_id is refined to an 'OpenUnitId' or 'DefUnitId', @@ -20,7 +20,7 @@ data ComponentInclude id rn = ComponentInclude , ci_implicit :: Bool -- ^ Did this come from an entry in @mixins@, or -- was implicitly generated by @build-depends@? - , ci_alias :: Maybe PrivateAlias + , ci_alias :: IsPrivate } deriving (Show) diff --git a/Cabal/src/Distribution/Types/GivenComponent.hs b/Cabal/src/Distribution/Types/GivenComponent.hs index eaab3e8e713..1ebcea15f79 100644 --- a/Cabal/src/Distribution/Types/GivenComponent.hs +++ b/Cabal/src/Distribution/Types/GivenComponent.hs @@ -23,7 +23,7 @@ data GivenComponent = GivenComponent , givenComponentName :: LibraryName -- --dependency is for libraries -- only, not for any component , givenComponentId :: ComponentId - , givenComponentAlias :: Maybe PrivateAlias + , givenComponentAlias :: IsPrivate } deriving (Generic, Read, Show, Eq, Typeable) diff --git a/Cabal/src/Distribution/Types/LocalBuildConfig.hs b/Cabal/src/Distribution/Types/LocalBuildConfig.hs index 4fd700d83e4..070908f3b11 100644 --- a/Cabal/src/Distribution/Types/LocalBuildConfig.hs +++ b/Cabal/src/Distribution/Types/LocalBuildConfig.hs @@ -101,7 +101,7 @@ data ComponentBuildDescr = ComponentBuildDescr -- ^ A map from component name to all matching -- components. These coincide with 'componentGraph' -- There may be more than one matching component because of backpack instantiations - , promisedPkgs :: Map (PackageName, ComponentName, Maybe PrivateAlias) ComponentId + , promisedPkgs :: Map (PackageName, ComponentName, IsPrivate) ComponentId -- ^ The packages we were promised, but aren't already installed. -- MP: Perhaps this just needs to be a Set UnitId at this stage. , installedPkgs :: InstalledPackageIndex diff --git a/Cabal/src/Distribution/Types/LocalBuildInfo.hs b/Cabal/src/Distribution/Types/LocalBuildInfo.hs index e0e3d58da79..799c48e0d7b 100644 --- a/Cabal/src/Distribution/Types/LocalBuildInfo.hs +++ b/Cabal/src/Distribution/Types/LocalBuildInfo.hs @@ -156,7 +156,7 @@ pattern LocalBuildInfo -> Maybe (SymbolicPath Pkg File) -> Graph ComponentLocalBuildInfo -> Map ComponentName [ComponentLocalBuildInfo] - -> Map (PackageName, ComponentName, Maybe PrivateAlias) ComponentId + -> Map (PackageName, ComponentName, IsPrivate) ComponentId -> InstalledPackageIndex -> PackageDescription -> ProgramDb diff --git a/cabal-install-solver/src/Distribution/Solver/Modular/ConfiguredConversion.hs b/cabal-install-solver/src/Distribution/Solver/Modular/ConfiguredConversion.hs index 86928083faf..31e11e90947 100644 --- a/cabal-install-solver/src/Distribution/Solver/Modular/ConfiguredConversion.hs +++ b/cabal-install-solver/src/Distribution/Solver/Modular/ConfiguredConversion.hs @@ -20,7 +20,7 @@ import Distribution.Solver.Types.SolverId import Distribution.Solver.Types.SolverPackage import Distribution.Solver.Types.InstSolverPackage import Distribution.Solver.Types.SourcePackage -import Distribution.Types.Dependency (PrivateAlias) +import Distribution.Types.Dependency (IsPrivate(..), PrivateAlias) -- | Converts from the solver specific result @CP QPN@ into -- a 'ResolverPackage', which can then be converted into @@ -49,16 +49,16 @@ convCP iidx sidx (CP qpi fa es ds) = srcpkg = fromMaybe (error "convCP: lookupPackageId failed") $ CI.lookupPackageId sidx pi where - ds' :: Maybe PackageName -> ComponentDeps (([(SolverId, Maybe PrivateAlias)] {- lib -}, [SolverId] {- exe -})) + ds' :: Maybe PackageName -> ComponentDeps (([(SolverId, IsPrivate)] {- lib -}, [SolverId] {- exe -})) ds' pn = fmap (partitionDeps . map (convConfId pn)) ds -partitionDeps :: [Converted] -> (([(SolverId, Maybe PrivateAlias)], [SolverId])) +partitionDeps :: [Converted] -> (([(SolverId, IsPrivate)], [SolverId])) partitionDeps [] = ([], []) partitionDeps (dep:deps) = let (p, e) = partitionDeps deps in case dep of - AliasPkg sid pn -> ((sid, Just pn) : p, e) - NormalPkg sid -> ((sid, Nothing) :p, e) + AliasPkg sid pn -> ((sid, Private pn) : p, e) + NormalPkg sid -> ((sid, Public) :p, e) NormalExe sid -> (p, sid:e) convPI :: PI QPN -> Either UnitId PackageId diff --git a/cabal-install-solver/src/Distribution/Solver/Types/InstSolverPackage.hs b/cabal-install-solver/src/Distribution/Solver/Types/InstSolverPackage.hs index 5e76b6a7a24..8476e757f90 100644 --- a/cabal-install-solver/src/Distribution/Solver/Types/InstSolverPackage.hs +++ b/cabal-install-solver/src/Distribution/Solver/Types/InstSolverPackage.hs @@ -6,7 +6,7 @@ module Distribution.Solver.Types.InstSolverPackage import Distribution.Solver.Compat.Prelude import Prelude () -import Distribution.Package ( Package(..), HasMungedPackageId(..), HasUnitId(..), PrivateAlias ) +import Distribution.Package ( Package(..), HasMungedPackageId(..), HasUnitId(..), IsPrivate ) import Distribution.Solver.Types.ComponentDeps ( ComponentDeps ) import Distribution.Solver.Types.SolverId import Distribution.Types.MungedPackageId @@ -18,7 +18,7 @@ import Distribution.InstalledPackageInfo (InstalledPackageInfo) -- specified by the dependency solver. data InstSolverPackage = InstSolverPackage { instSolverPkgIPI :: InstalledPackageInfo, - instSolverPkgLibDeps :: ComponentDeps [(SolverId, Maybe PrivateAlias)], + instSolverPkgLibDeps :: ComponentDeps [(SolverId, IsPrivate)], instSolverPkgExeDeps :: ComponentDeps [SolverId] } deriving (Eq, Show, Generic) diff --git a/cabal-install-solver/src/Distribution/Solver/Types/ResolverPackage.hs b/cabal-install-solver/src/Distribution/Solver/Types/ResolverPackage.hs index f34e5944596..e079ef15980 100644 --- a/cabal-install-solver/src/Distribution/Solver/Types/ResolverPackage.hs +++ b/cabal-install-solver/src/Distribution/Solver/Types/ResolverPackage.hs @@ -17,7 +17,7 @@ import qualified Distribution.Solver.Types.ComponentDeps as CD import Distribution.Compat.Graph (IsNode(..)) import Distribution.Package (Package(..), HasUnitId(..)) import Distribution.Simple.Utils (ordNub) -import Distribution.Types.Dependency (PrivateAlias) +import Distribution.Types.Dependency (IsPrivate) -- | The dependency resolver picks either pre-existing installed packages -- or it picks source packages along with package configuration. @@ -35,7 +35,7 @@ instance Package (ResolverPackage loc) where packageId (PreExisting ipkg) = packageId ipkg packageId (Configured spkg) = packageId spkg -resolverPackageLibDeps :: ResolverPackage loc -> CD.ComponentDeps [(SolverId, Maybe PrivateAlias)] +resolverPackageLibDeps :: ResolverPackage loc -> CD.ComponentDeps [(SolverId, IsPrivate)] resolverPackageLibDeps (PreExisting ipkg) = instSolverPkgLibDeps ipkg resolverPackageLibDeps (Configured spkg) = solverPkgLibDeps spkg diff --git a/cabal-install-solver/src/Distribution/Solver/Types/SolverPackage.hs b/cabal-install-solver/src/Distribution/Solver/Types/SolverPackage.hs index 85148db46b5..18bf3bcc9fa 100644 --- a/cabal-install-solver/src/Distribution/Solver/Types/SolverPackage.hs +++ b/cabal-install-solver/src/Distribution/Solver/Types/SolverPackage.hs @@ -12,7 +12,7 @@ import Distribution.Solver.Types.ComponentDeps ( ComponentDeps ) import Distribution.Solver.Types.OptionalStanza import Distribution.Solver.Types.SolverId import Distribution.Solver.Types.SourcePackage -import Distribution.Types.Dependency (PrivateAlias) +import Distribution.Types.Dependency (IsPrivate) -- | A 'SolverPackage' is a package specified by the dependency solver. -- It will get elaborated into a 'ConfiguredPackage' or even an @@ -25,7 +25,7 @@ data SolverPackage loc = SolverPackage { solverPkgSource :: SourcePackage loc, solverPkgFlags :: FlagAssignment, solverPkgStanzas :: OptionalStanzaSet, - solverPkgLibDeps :: ComponentDeps [(SolverId, Maybe PrivateAlias)], + solverPkgLibDeps :: ComponentDeps [(SolverId, IsPrivate)], solverPkgExeDeps :: ComponentDeps [SolverId] } deriving (Eq, Show, Generic) diff --git a/cabal-install/src/Distribution/Client/Configure.hs b/cabal-install/src/Distribution/Client/Configure.hs index 4c8f4a5a87f..08ba1fbba82 100644 --- a/cabal-install/src/Distribution/Client/Configure.hs +++ b/cabal-install/src/Distribution/Client/Configure.hs @@ -534,7 +534,7 @@ configurePackage CD.nonSetupDeps deps ] , configDependencies = - [ GivenComponent (packageName srcid) cname uid Nothing + [ GivenComponent (packageName srcid) cname uid PkgDesc.Public | ConfiguredId srcid (Just (PkgDesc.CLibName cname)) uid <- CD.nonSetupDeps deps ] diff --git a/cabal-install/src/Distribution/Client/Dependency.hs b/cabal-install/src/Distribution/Client/Dependency.hs index b3895a4c2b5..c9317f83a8e 100644 --- a/cabal-install/src/Distribution/Client/Dependency.hs +++ b/cabal-install/src/Distribution/Client/Dependency.hs @@ -962,10 +962,10 @@ data PackageProblem = DuplicateFlag PD.FlagName | MissingFlag PD.FlagName | ExtraFlag PD.FlagName - | DuplicateDeps [(PackageId, Maybe PrivateAlias)] - | MissingDep Dependency (Maybe PrivateAlias) - | ExtraDep PackageId (Maybe PrivateAlias) - | InvalidDep Dependency PackageId (Maybe PrivateAlias) + | DuplicateDeps [(PackageId, IsPrivate)] + | MissingDep Dependency (IsPrivate) + | ExtraDep PackageId (IsPrivate) + | InvalidDep Dependency PackageId (IsPrivate) showPackageProblem :: PackageProblem -> String showPackageProblem (DuplicateFlag flag) = @@ -976,15 +976,15 @@ showPackageProblem (ExtraFlag flag) = "extra flag given that is not used by the package: " ++ PD.unFlagName flag showPackageProblem (DuplicateDeps pkgids) = "duplicate packages specified as selected dependencies: " - ++ intercalate ", " (map (\(x, y) -> maybe "" ((<> ".") . prettyShow) y <> prettyShow x) pkgids) + ++ intercalate ", " (map (\(x, y) -> foldIsPrivate "" ((<> ".") . prettyShow) y <> prettyShow x) pkgids) showPackageProblem (MissingDep dep palias) = "the package has a dependency " - ++ maybe "" ((<> ".") . prettyShow) palias + ++ foldIsPrivate "" ((<> ".") . prettyShow) palias ++ prettyShow dep ++ " but no package has been selected to satisfy it." showPackageProblem (ExtraDep pkgid palias) = "the package configuration specifies " - ++ maybe "" ((<> ".") . prettyShow) palias + ++ foldIsPrivate "" ((<> ".") . prettyShow) palias ++ prettyShow pkgid ++ " but (with the given flag assignment) the package does not actually" ++ " depend on any version of that package." @@ -992,7 +992,7 @@ showPackageProblem (InvalidDep dep pkgid palias) = "the package depends on " ++ prettyShow dep ++ " but the configuration specifies " - ++ maybe "" ((<> ".") . prettyShow) palias + ++ foldIsPrivate "" ((<> ".") . prettyShow) palias ++ prettyShow pkgid ++ " which does not satisfy the dependency." @@ -1036,10 +1036,10 @@ configuredPackageProblems thisPkgName :: PackageName thisPkgName = packageName (srcpkgDescription pkg) - specifiedDeps1 :: ComponentDeps [(PackageId, Maybe PrivateAlias)] + specifiedDeps1 :: ComponentDeps [(PackageId, IsPrivate)] specifiedDeps1 = fmap (map (first solverSrcId)) specifiedDeps0 - specifiedDeps :: [(PackageId, Maybe PrivateAlias)] + specifiedDeps :: [(PackageId, IsPrivate)] specifiedDeps = CD.flatDeps specifiedDeps1 mergedFlags :: [MergeResult PD.FlagName PD.FlagName] @@ -1057,13 +1057,13 @@ configuredPackageProblems dependencyName (Dependency name _ _) = name - mergedDeps :: [MergeResult (Dependency, Maybe PrivateAlias) (PackageId, Maybe PrivateAlias)] + mergedDeps :: [MergeResult (Dependency, IsPrivate) (PackageId, IsPrivate)] mergedDeps = mergeDeps requiredDeps specifiedDeps mergeDeps - :: [(Dependency, Maybe PrivateAlias)] - -> [(PackageId, Maybe PrivateAlias)] - -> [MergeResult (Dependency, Maybe PrivateAlias) (PackageId, Maybe PrivateAlias)] + :: [(Dependency, IsPrivate)] + -> [(PackageId, IsPrivate)] + -> [MergeResult (Dependency, IsPrivate) (PackageId, IsPrivate)] mergeDeps required specified = let sortNubOn f = nubBy ((==) `on` f) . sortBy (compare `on` f) in mergeBy @@ -1078,7 +1078,7 @@ configuredPackageProblems -- have to allow for duplicates when we fold specifiedDeps; once we have -- proper ComponentDeps here we should get rid of the `nubOn` in -- `mergeDeps`. - requiredDeps :: [(Dependency, Maybe PrivateAlias)] + requiredDeps :: [(Dependency, IsPrivate)] requiredDeps = -- TODO: use something lower level than finalizePD case finalizePD @@ -1102,7 +1102,7 @@ configuredPackageProblems ( map (\(x, y) -> (y, x)) $ PD.enabledBuildDepends resolvedPkg compSpec ) - ++ maybe [] (map (,Nothing) . PD.setupDepends) (PD.setupBuildInfo resolvedPkg) + ++ maybe [] (map (,Public) . PD.setupDepends) (PD.setupBuildInfo resolvedPkg) Left _ -> error "configuredPackageInvalidDeps internal error" diff --git a/cabal-install/src/Distribution/Client/Install.hs b/cabal-install/src/Distribution/Client/Install.hs index c780febbbe7..c5e9c28136e 100644 --- a/cabal-install/src/Distribution/Client/Install.hs +++ b/cabal-install/src/Distribution/Client/Install.hs @@ -154,6 +154,7 @@ import Distribution.Client.Utils import Distribution.Package ( HasMungedPackageId (..) , HasUnitId (..) + , IsPrivate (..) , Package (..) , PackageId , PackageIdentifier (..) @@ -1661,7 +1662,7 @@ installReadyPackage CD.nonSetupDeps deps ] , configDependencies = - [ GivenComponent (packageName srcid) cname dep_ipid Nothing + [ GivenComponent (packageName srcid) cname dep_ipid Public | ConfiguredId srcid (Just (PackageDescription.CLibName cname)) dep_ipid <- CD.nonSetupDeps deps ] diff --git a/cabal-install/src/Distribution/Client/ProjectPlanOutput.hs b/cabal-install/src/Distribution/Client/ProjectPlanOutput.hs index 01169449496..9484e4cd52b 100644 --- a/cabal-install/src/Distribution/Client/ProjectPlanOutput.hs +++ b/cabal-install/src/Distribution/Client/ProjectPlanOutput.hs @@ -322,14 +322,14 @@ encodePlanAsJson distDirLayout elaboratedInstallPlan elaboratedSharedConfig = then dist_dir "build" prettyShow s ("lib" ++ prettyShow s) <.> dllExtension plat else InstallDirs.bindir (elabInstallDirs elab) ("lib" ++ prettyShow s) <.> dllExtension plat - handleLibDepends :: [(ConfiguredId, Bool, Maybe PrivateAlias)] -> [J.Pair] + handleLibDepends :: [(ConfiguredId, Bool, IsPrivate)] -> [J.Pair] handleLibDepends deps = let (publicDeps, privateDeps) = partitionEithers $ map ( \(p, _, mb) -> case mb of - Nothing -> Left p - Just alias -> Right (alias, p) + Public -> Left p + Private alias -> Right (alias, p) ) deps in [ "depends" J..= map (jdisplay . confInstId) publicDeps diff --git a/cabal-install/src/Distribution/Client/ProjectPlanning.hs b/cabal-install/src/Distribution/Client/ProjectPlanning.hs index 2b5d7d59fa6..ad802f24118 100644 --- a/cabal-install/src/Distribution/Client/ProjectPlanning.hs +++ b/cabal-install/src/Distribution/Client/ProjectPlanning.hs @@ -1882,7 +1882,7 @@ elaborateInstallPlan external_lib_dep_sids = CD.select (== compSolverName) deps0 external_exe_dep_sids = CD.select (== compSolverName) exe_deps0 - external_exe_dep_sids_raw = [(sid, Nothing) | sid <- external_exe_dep_sids] + external_exe_dep_sids_raw = [(sid, Public) | sid <- external_exe_dep_sids] -- Combine library and build-tool dependencies, for backwards -- compatibility (See issue #5412 and the documentation for @@ -2460,8 +2460,8 @@ matchElabPkg p elab = -- and 'ComponentName' to the 'ComponentId' that should be used -- in this case. mkCCMapping - :: (ElaboratedPlanPackage, Maybe PrivateAlias) - -> ((PackageName, Maybe PrivateAlias), Map ComponentName ((AnnotatedId ComponentId))) + :: (ElaboratedPlanPackage, IsPrivate) + -> ((PackageName, IsPrivate), Map ComponentName ((AnnotatedId ComponentId))) mkCCMapping (ep, alias) = foldpp ep where foldpp = @@ -3949,7 +3949,7 @@ setupHsConfigureFlags configUseResponseFiles = mempty configAllowDependingOnPrivateLibs = Flag $ not $ libraryVisibilitySupported pkgConfigCompiler - cidToGivenComponent :: Maybe PrivateAlias -> ConfiguredId -> GivenComponent + cidToGivenComponent :: IsPrivate -> ConfiguredId -> GivenComponent cidToGivenComponent alias (ConfiguredId srcid mb_cn cid) = GivenComponent (packageName srcid) ln cid alias where ln = case mb_cn of diff --git a/cabal-install/src/Distribution/Client/ProjectPlanning/Types.hs b/cabal-install/src/Distribution/Client/ProjectPlanning/Types.hs index ec505ca8b4a..5f88f755d17 100644 --- a/cabal-install/src/Distribution/Client/ProjectPlanning/Types.hs +++ b/cabal-install/src/Distribution/Client/ProjectPlanning/Types.hs @@ -183,8 +183,8 @@ showElaboratedInstallPlan = InstallPlan.showInstallPlan_gen showNode [ (if internal then text "+" else mempty) <> mpalias <> pretty (confInstId uid) | (uid, internal, alias) <- elabLibDependencies cfg , let mpalias = case alias of - Nothing -> mempty - Just al -> pretty al <> text "." + Public -> mempty + Private al -> pretty al <> text "." ] -- TODO: [code cleanup] decide if we really need this, there's not much in it, and in principle @@ -581,7 +581,7 @@ elabOrderLibDependencies elab = -- | The library dependencies (i.e., the libraries we depend on, NOT -- the dependencies of the library), NOT including setup dependencies. -- These are passed to the @Setup@ script via @--dependency@ or @--promised-dependency@. -elabLibDependencies :: ElaboratedConfiguredPackage -> [(ConfiguredId, Bool, Maybe PrivateAlias)] +elabLibDependencies :: ElaboratedConfiguredPackage -> [(ConfiguredId, Bool, IsPrivate)] elabLibDependencies elab = case elabPkgOrComp elab of ElabPackage pkg -> ordNub (CD.nonSetupDeps (pkgLibDependencies pkg)) @@ -615,7 +615,7 @@ elabExeDependencyPaths elab = -- | The setup dependencies (the library dependencies of the setup executable; -- note that it is not legal for setup scripts to have executable -- dependencies at the moment.) -elabSetupDependencies :: ElaboratedConfiguredPackage -> [(ConfiguredId, Bool, Maybe PrivateAlias)] +elabSetupDependencies :: ElaboratedConfiguredPackage -> [(ConfiguredId, Bool, IsPrivate)] elabSetupDependencies elab = case elabPkgOrComp elab of ElabPackage pkg -> CD.setupDeps (pkgLibDependencies pkg) @@ -675,7 +675,7 @@ data ElaboratedComponent = ElaboratedComponent , compComponentName :: Maybe ComponentName -- ^ The name of the component to be built. Nothing if -- it's a setup dep. - , compLibDependencies :: [(ConfiguredId, Bool, Maybe PrivateAlias)] + , compLibDependencies :: [(ConfiguredId, Bool, IsPrivate)] -- ^ The *external* library dependencies of this component. We -- pass this to the configure script. The Bool indicates whether the -- dependency is a promised dependency (True) or not (False). @@ -722,7 +722,7 @@ compOrderExeDependencies = map (newSimpleUnitId . confInstId) . compExeDependenc data ElaboratedPackage = ElaboratedPackage { pkgInstalledId :: InstalledPackageId - , pkgLibDependencies :: ComponentDeps [(ConfiguredId, Bool, Maybe PrivateAlias)] + , pkgLibDependencies :: ComponentDeps [(ConfiguredId, Bool, IsPrivate)] -- ^ The exact dependencies (on other plan packages) -- The boolean value indicates whether the dependency is a promised dependency -- or not. diff --git a/cabal-install/src/Distribution/Client/SolverInstallPlan.hs b/cabal-install/src/Distribution/Client/SolverInstallPlan.hs index a0a8fcd0baa..76d45f455f0 100644 --- a/cabal-install/src/Distribution/Client/SolverInstallPlan.hs +++ b/cabal-install/src/Distribution/Client/SolverInstallPlan.hs @@ -56,11 +56,11 @@ import Prelude () import Distribution.Package ( HasUnitId (..) + , IsPrivate (..) , Package (..) , PackageId , PackageIdentifier (..) , PackageName - , PrivateAlias (..) , packageName , packageVersion ) @@ -376,8 +376,8 @@ dependencyInconsistencies' index = -- (because, across packages, there may exist scopes with the same name). List.groupBy ( \x y -> case (x, y) of - (((Nothing, _), _), (_, _)) -> False - ((_, _), ((Nothing, _), _)) -> False + (((Public, _), _), (_, _)) -> False + ((_, _), ((Public, _), _)) -> False (((aliasA, sidA), _), ((aliasB, sidB), _)) | aliasA == aliasB -> sidA == sidB @@ -391,7 +391,7 @@ dependencyInconsistencies' index = -- and each installed ID of that package -- the associated package instance -- and a list of reverse dependencies (as source IDs) and the possible private scope of each revdep - inverseIndex :: Map PackageName (Map (Maybe PrivateAlias, SolverId) (SolverPlanPackage, [PackageId])) + inverseIndex :: Map PackageName (Map (IsPrivate, SolverId) (SolverPlanPackage, [PackageId])) inverseIndex = Map.fromListWith (Map.unionWith (\(a, b) (_, b') -> (a, b ++ b'))) From 6a132704ec474ea76feffadab858e43c94fe4628 Mon Sep 17 00:00:00 2001 From: Rodrigo Mesquita Date: Mon, 15 Apr 2024 17:00:23 +0100 Subject: [PATCH 07/12] doc: Add private dependencies to the user guide Documents private dependencies in the user facing user guide --- doc/cabal-package-description-file.rst | 2 +- doc/how-to-use-private-dependencies.rst | 240 ++++++++++++++++++++++++ doc/index.rst | 1 + 3 files changed, 242 insertions(+), 1 deletion(-) create mode 100644 doc/how-to-use-private-dependencies.rst diff --git a/doc/cabal-package-description-file.rst b/doc/cabal-package-description-file.rst index 1d6d34fa7a1..512a87cf697 100644 --- a/doc/cabal-package-description-file.rst +++ b/doc/cabal-package-description-file.rst @@ -2145,7 +2145,7 @@ system-dependent values for these fields. .. pkg-field:: private-build-depends: private scope - A private dependency can be introduced in a cabal file in the + A `private dependency ` can be introduced in a cabal file in the ``private-build-depends`` field. The specification starts with the name of the private dependency *scope* and then contains a list of normal dependency specifications which dictate the packages included in that private scope. diff --git a/doc/how-to-use-private-dependencies.rst b/doc/how-to-use-private-dependencies.rst new file mode 100644 index 00000000000..0ce908ac773 --- /dev/null +++ b/doc/how-to-use-private-dependencies.rst @@ -0,0 +1,240 @@ +.. _Private dependencies: + +Private dependencies +==================== + +Historically, Cabal has enforced the restriction that a library must only link +against one version of each package it depends on. This ensures that all of the +dependencies in the build plan work together. In your application you use +different libraries together, so it's of paramount importance that they all +agree on what ``Text`` means or what a ``ByteString`` is. + +However, sometimes it's desirable to allow multiple versions of the same +library into a build plan. In this case, it's desirable to allow a library +author to specify a **private** dependency with the promise that its existence +will not leak from the interface of the library which uses it. + +The two main use cases of private dependencies are: + +* Writing benchmarks and testsuites for your library which test new versions of + your library against old versions. +* Writing libraries which can communicate with processes built against + a range of different library versions (such as ``cabal`-install` calling `./`Setup``). + +Private dependencies are a new feature in ``Cabal`` and ``cabal-install`` which +allows the Cabal solver to pick versions for private dependencies independently +from the package versions chosen for public dependencies, enabling the scenarios above. + +Private dependencies are an advanced feature which should only be used if you +know what you are doing and need a build plan which involves linking a library against +multiple versions of the same library. + +The examples used in this blog post are available in its "complete" form in +this `github repository `__. + +Using private dependencies +-------------------------- + +To explore the syntax and properties of private dependencies, consider a +testsuite which will have a private dependency on ``text-1.2`` and a +separate private dependency on ``text-2``: + +:: + + ┌──────────┐ + ┌─┤bench-text├─┐ + │ └──────────┘ │ + │ │ + ┌──▼───┐ ┌────▼─┐ + │text-1│ │text-2│ + └──────┘ └──────┘ + +This benchmark/testsuite will be able to run two different versions of +the same function from the package in the same executable, making it +much easier to e.g. detect performance regressions or improvements +across versions. + +A private dependency can be introduced in a cabal file in the +``private-build-depends`` field. The specification starts with the name +of the private dependency *scope* and then contains a list of normal +dependency specifications which dictate the packages included in that +private scope. Our example needs two private scopes, each with a +specific version of text: + +:: + + private-build-depends: TEXT1 with (text == 1.2.*), TEXT2 with (text == 2.*) + +The package **goals in a private scope are solved independently of all +other scopes**. In this example, the ``TEXT1`` scope can choose a +version of ``text`` in the ``1.2.x`` range and the ``TEXT2`` scope can +choose a version of ``text`` in the ``2.*`` range. + +However, **private scopes do not apply transitively**, so the +dependencies of ``text`` will be solved in the normal top-level scope. +If your program contains a value of type ``Bool`` from the ``base`` +package, which ``text`` also depends on, only if the scopes are not +applied transitively can the same ``Bool`` value can be passed to +functions from the ``TEXT1`` scope and ``TEXT2`` scope. Visually, the +“complete” dependency graph would look like: + +:: + + ┌──────────┐ + ┌─┤bench-text├─┐ + │ └──────────┘ │ + │ │ + ┌──▼───┐ ┌────▼─┐ + │text-1│ │text-2│ + └──┬───┘ └───┬──┘ + │ │ + │ ┌──────┐ │ + └───►base-4◄──┘ + └──────┘ + +Dependencies introduced privately can be imported into modules in the +project by prefixing the name of the private scope to an exposed module +name: + +:: + + import qualified TEXT1.Data.Text as T1 + import qualified TEXT2.Data.Text as T2 + +Now, obviously, ``T1.Text`` and ``T2.Text`` are distinct types, and it’s +the programmer’s responsibility to ensure that their program does not +mix them together. The typechecker will tell you if you attempt to use +incompatible types with each other. + +Further to this, the private dependencies contract states that you are +**not allowed to expose anything from a private scope in the public API +of your library**. Again, it’s the programmer’s responsibility to ensure +that their public API doesn’t expose any of these types. This isn’t +checked by the compiler; if you don’t ensure the public API doesn’t +expose types imported from a private scope, your package is going to be +broken. + +Once the types are imported, they are used just like any other qualified +imports. In a simple test, we check that ``text-2.*`` and ``text-1.2.*`` +agree in the length of ``"abc"``: + +:: + + main = print $ T1.length (T1.pack "abc") == T2.length (T2.pack "abc") + +Closure of Private Dependencies +------------------------------- + +A private dependency scope may contain multiple packages, and **packages +in the same private scope are solved together**. That is, you have to +pick one version per package in the scope that satisfies all constraints +of all packages in that scope. For instance, having +``private-build-depends: S0 with (pkg-a == 0.1, pkg-b == 0.2)`` will +fail if ``pkg-a`` has ``build-depends: pkg-b == 0-1`` in its cabal file. + +Specifying two (or more) packages in the same scope can be particularly +useful if these two packages are tightly coupled and you need each to +use a version compatible with the other, but still want them to be +solved independently of the top-level scope. + +A crucial property must hold true of the packages in a private scope: +**the transitive closure of the packages in the private scope must be +closed**. A scope is **closed** if, whenever we have a dependency chain +``P1 -> Q -> P2``, in which ``P1`` and ``P2`` are both in a given +private scope ``S``, then ``Q`` also belongs to the private scope ``S``. +The Cabal solver checks this property and guarantees no scope violates +this property, however, it doesn’t implicit add packages into a private +scope, so you may need to add packages violating the closure property +manually to the scope. + +Apartness of Private Dependencies +--------------------------------- + +A library using private dependencies must **assume that a privately +scoped dependency is apart from the top-level scope and from other +private scopes**. + +By coincidence (and heuristics), the solver might choose the same +version of a package to satisfy different private scopes. Conversely, it +might also not choose the same version. Therefore, in order to robustly +write a program using private dependencies, the programmer must assume +that modules in separate scopes are incompatible with other modules of +the same name, even if those modules come from the same package. + +Benchmarking using Private Dependencies +--------------------------------------- + +Using private dependencies, it is straightforward to write a benchmark +suite which tests different versions of the same library against each +other. + +Consider the task of benchmarking ``text-1.2.*`` vs ``text-2.*`` again: +private dependencies make it possible to benchmark the two versions +directly against each other in the same benchmark run. + +Working through a complete benchmarking example, let’s introduce two new +private scopes to encapsulate the different ``text`` versions which we +want to test: + +:: + + benchmark testing-text-benchmarks + import: warnings + default-language: Haskell2010 + type: exitcode-stdio-1.0 + hs-source-dirs: bench/ + main-is: Main.hs + build-depends: base ^>=4.18.0.0, tasty-bench, tasty, deepseq + private-build-depends: TEXT1 with (text == 1.2.*), TEXT2 with (text == 2.*) + +The different versions of ``text`` are made available with the +respective prefixes in ``Main.hs``: + +:: + + import qualified TEXT1.Data.Text as TEXT1 + import qualified TEXT1.Data.Text.IO as TEXT1 + + + import qualified TEXT2.Data.Text as TEXT2 + import qualified TEXT2.Data.Text.IO as TEXT2 + +The ``InputEnv`` type allows us to wrap ``TEXT1.Text`` and +``TEXT2.Text`` to provide an ``NFData`` instance for types which we just +have to force to WHNF to be sure of having evaluated fully: + +:: + + data InputEnv a = InputEnv { lorem :: !a } + + instance NFData (InputEnv a) where + rnf InputEnv{} = () + + type T1Env = InputEnv TEXT1.Text + type T2Env = InputEnv TEXT2.Text + +We declare a helper function (``mkBench``) which takes the two prepared +``Text`` values and functions from the relevant library versions, and +proceed with benchmarking as is typically done for other benchmarks +regardless of private scopes: + +:: + + mkBench :: T1Env -> T2Env -> (TEXT1.Text -> a) -> (TEXT2.Text -> b) -> [Benchmark] + mkBench t1env t2env t1 t2 = + [ bench "t1" $ whnf t1 (lorem t1env) + , bench "t2" $ whnf t2 (lorem t2env) ] + + main = + defaultMain . (:[]) $ + env (InputEnv <$> TEXT1.readFile "lorem.txt") $ \t1env -> + env (InputEnv <$> TEXT2.readFile "lorem.txt") $ \t2env -> + let mk_bench = mkBench t1env t2env + in bgroup "text" + [ bgroup "Reverse" (mk_bench TEXT1.reverse TEXT2.reverse) + , bgroup "Length" (mk_bench TEXT1.length TEXT2.length) + ] + +Running the benchmarks we can see that ``text-2.*`` performs much better +than ``text-1.2``, at least in the case of reversing and length. + diff --git a/doc/index.rst b/doc/index.rst index 69109a67685..cdfa61f45e0 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -16,6 +16,7 @@ Welcome to the Cabal User Guide how-to-package-haskell-code how-to-build-like-nix how-to-use-backpack + how-to-use-private-dependencies how-to-report-bugs .. toctree:: From c4e0f3d617152fa2778f4a1bf08deff6ab1d66ea Mon Sep 17 00:00:00 2001 From: Rodrigo Mesquita Date: Tue, 16 Apr 2024 13:38:48 +0100 Subject: [PATCH 08/12] Redesign private scope closure check for performance Redesigns the algorithm for checking the private scope closure property in the solver. The algorithm is described in detail in the comment of `findBadPrivClosures`. A key change is that we construct and propagate together with the `RevDepMap` a cache of the private scopes at every node, which allow us to efficiently look up the "root" packages from which we can easily validate the property holds. This change was prompted by stress testing private dependencies: The stress test uncovered that way too much time was being spent on validating the closure property, despite the property already being checked at every node. Specifically, the baseline for solving without the check was 11s, however, with the check in place, solving instead took over 50s when NO private dependencies were in the plan, and over 2 minutes when there were a lot of private scopes. After this change, the check of the private scope closure property is negligible on performance, being slightly faster (40ms) when there are a lot of private scopes (because the algorithm short circuits faster) and slightly slower (90ms) when there are no private scopes at all. This is more in line with the `findCycles` check takes some 110ms on my machine. This commit also adds the stress test which uncovered the problem, however, this stress test is disabled by default and should only be run manually since testing time-based performance in CI can be problematic. --- .../cabal-install-solver.cabal | 1 + .../Distribution/Solver/Modular/Assignment.hs | 2 +- .../Distribution/Solver/Modular/Builder.hs | 17 +- .../Solver/Modular/ConflictSet.hs | 9 - .../src/Distribution/Solver/Modular/Cycles.hs | 52 +--- .../Distribution/Solver/Modular/Dependency.hs | 11 +- .../Distribution/Solver/Modular/Explore.hs | 1 - .../Distribution/Solver/Modular/Message.hs | 8 +- .../Solver/Modular/PrivateScopeClosure.hs | 292 +++++++++++------- .../src/Distribution/Solver/Modular/Solver.hs | 11 +- .../Solver/Modular/ValidateDependencies.hs | 66 ++++ .../Distribution/Solver/Modular/Solver.hs | 93 +++++- .../closure-property-test/cabal.test.hs | 2 +- .../PrivateDeps/same-scope-name/cabal.test.hs | 10 +- .../same-scope-name/pkgA/CHANGELOG.md | 5 - .../same-scope-name/pkgA/pkgA.cabal | 1 - .../same-scope-name/pkgB/CHANGELOG.md | 5 - .../same-scope-name/pkgB/pkgB.cabal | 1 - .../same-scope-name/pkgC/CHANGELOG.md | 5 - .../same-scope-name/pkgC/app/Main.hs | 1 + .../same-scope-name/pkgC/pkgC.cabal | 2 +- .../same-scope-name/pkgD/CHANGELOG.md | 5 - .../same-scope-name/pkgD/pkgD.cabal | 1 - .../repo/libA-0.1.0.0/CHANGELOG.md | 5 - .../repo/libA-0.1.0.0/libA.cabal | 1 - .../repo/libA-0.2.0.0/CHANGELOG.md | 5 - .../repo/libA-0.2.0.0/libA.cabal | 1 - 27 files changed, 390 insertions(+), 223 deletions(-) create mode 100644 cabal-install-solver/src/Distribution/Solver/Modular/ValidateDependencies.hs delete mode 100644 cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgA/CHANGELOG.md delete mode 100644 cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgB/CHANGELOG.md delete mode 100644 cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgC/CHANGELOG.md create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgC/app/Main.hs delete mode 100644 cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgD/CHANGELOG.md delete mode 100644 cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/repo/libA-0.1.0.0/CHANGELOG.md delete mode 100644 cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/repo/libA-0.2.0.0/CHANGELOG.md diff --git a/cabal-install-solver/cabal-install-solver.cabal b/cabal-install-solver/cabal-install-solver.cabal index 151f46fa09a..ab41ac7786b 100644 --- a/cabal-install-solver/cabal-install-solver.cabal +++ b/cabal-install-solver/cabal-install-solver.cabal @@ -72,6 +72,7 @@ library Distribution.Solver.Modular.Solver Distribution.Solver.Modular.Tree Distribution.Solver.Modular.Validate + Distribution.Solver.Modular.ValidateDependencies Distribution.Solver.Modular.Var Distribution.Solver.Modular.Version Distribution.Solver.Modular.WeightedPSQ diff --git a/cabal-install-solver/src/Distribution/Solver/Modular/Assignment.hs b/cabal-install-solver/src/Distribution/Solver/Modular/Assignment.hs index d1ae64e5b38..00d5666ba8f 100644 --- a/cabal-install-solver/src/Distribution/Solver/Modular/Assignment.hs +++ b/cabal-install-solver/src/Distribution/Solver/Modular/Assignment.hs @@ -54,7 +54,7 @@ toCPs (A pa fa sa) rdm = cvm :: QPN -> Maybe Vertex -- Note that the RevDepMap contains duplicate dependencies. Therefore the nub. (g, vm, cvm) = graphFromEdges (L.map (\ (x, xs) -> ((), x, nub xs)) - (M.toList rdm)) + (M.toList $ revDeps rdm)) tg :: Graph Component tg = transposeG g -- Topsort the dependency graph, yielding a list of pkgs in the right order. diff --git a/cabal-install-solver/src/Distribution/Solver/Modular/Builder.hs b/cabal-install-solver/src/Distribution/Solver/Modular/Builder.hs index 95373cbd473..d9a2a7b5e2a 100644 --- a/cabal-install-solver/src/Distribution/Solver/Modular/Builder.hs +++ b/cabal-install-solver/src/Distribution/Solver/Modular/Builder.hs @@ -81,10 +81,19 @@ extendOpen qpn' gs s@(BS { rdeps = gs', open = o' }) = go gs' o' gs -- instance for the setup script. We may need to track other -- self-dependencies once we implement component-based solving. case c of - ComponentSetup -> go (M.adjust (addIfAbsent (ComponentSetup, qpn')) qpn g) o ngs + ComponentSetup -> go g{revDeps = M.adjust (addIfAbsent (ComponentSetup, qpn')) qpn (revDeps g)} o ngs _ -> go g o ngs - | qpn `M.member` g = go (M.adjust (addIfAbsent (c, qpn')) qpn g) o ngs - | otherwise = go (M.insert qpn [(c, qpn')] g) (PkgGoal qpn (DependencyGoal dr) : o) ngs + | qpn `M.member` (revDeps g) + = go g{ revDeps = M.adjust (addIfAbsent (c, qpn')) qpn (revDeps g) + -- If qpn is already a member of revDeps, it is already in the privScopes mapping. + } o ngs + | otherwise + = go g{ revDeps = M.insert qpn [(c, qpn')] (revDeps g) + , privScopes = case qpn of + Q (PackagePath _ ql@QualAlias{}) _ -> + M.insertWith(<>) ql (S.singleton qpn) (privScopes g) + _ -> privScopes g + } (PkgGoal qpn (DependencyGoal dr) : o) ngs -- code above is correct; insert/adjust have different arg order go g o ((Simple (LDep _dr (Ext _ext )) _) : ngs) = go g o ngs go g o ((Simple (LDep _dr (Lang _lang))_) : ngs) = go g o ngs @@ -252,7 +261,7 @@ buildTree idx (IndependentGoals ind) igs = build Linker { buildState = BS { index = idx - , rdeps = M.fromList (L.map (\ qpn -> (qpn, [])) qpns) + , rdeps = RevDepMap { revDeps = M.fromList (L.map (\ qpn -> (qpn, [])) qpns), privScopes = mempty } , open = L.map topLevelGoal qpns , next = Goals , qualifyOptions = defaultQualifyOptions idx diff --git a/cabal-install-solver/src/Distribution/Solver/Modular/ConflictSet.hs b/cabal-install-solver/src/Distribution/Solver/Modular/ConflictSet.hs index 6c9b4280986..00cf15b466f 100644 --- a/cabal-install-solver/src/Distribution/Solver/Modular/ConflictSet.hs +++ b/cabal-install-solver/src/Distribution/Solver/Modular/ConflictSet.hs @@ -74,15 +74,6 @@ data Conflict = -- means that package y's constraint 'x >= 2.0' excluded some version of x. | VersionConflict QPN OrderedVersionRange - -- | The conflict set variable represents a package that was excluded for - -- violating the closure property of a private-scope, because that package is part of - -- the closure of the private scope, but it itself is not - -- included in it. For example, the conflict set entry '(P pkgC, - -- PrivateScopeClosureConflict pkgA:lib:G0:pkgB pkgA:lib:G0:pkgD)' means - -- that pkgC is in the (private-deps) closure from pkgA:lib:G0:pkgB to - -- pkgA:lib:G0:pkgD, but pkgC is not included in the private scope pkgA:lib:G0. - | PrivateScopeClosureConflict QPN QPN - -- | Any other conflict. | OtherConflict deriving (Eq, Ord, Show) diff --git a/cabal-install-solver/src/Distribution/Solver/Modular/Cycles.hs b/cabal-install-solver/src/Distribution/Solver/Modular/Cycles.hs index b82e39a0d26..eaf0b1bb789 100644 --- a/cabal-install-solver/src/Distribution/Solver/Modular/Cycles.hs +++ b/cabal-install-solver/src/Distribution/Solver/Modular/Cycles.hs @@ -1,6 +1,7 @@ +{-# LANGUAGE TupleSections #-} {-# LANGUAGE TypeFamilies #-} module Distribution.Solver.Modular.Cycles ( - detectCyclesPhase + findCycles ) where import Prelude hiding (cycle) @@ -8,51 +9,20 @@ import qualified Data.Map as M import qualified Data.Set as S import qualified Distribution.Compat.Graph as G -import Distribution.Simple.Utils (ordNub) import Distribution.Solver.Modular.Dependency -import Distribution.Solver.Modular.Flag import Distribution.Solver.Modular.Tree import qualified Distribution.Solver.Modular.ConflictSet as CS -import Distribution.Solver.Types.ComponentDeps (Component) import Distribution.Solver.Types.PackagePath +import Distribution.Solver.Modular.ValidateDependencies --- | Find and reject any nodes with cyclic dependencies -detectCyclesPhase :: Tree d c -> Tree d c -detectCyclesPhase = go - where - -- Only check children of choice nodes. - go :: Tree d c -> Tree d c - go (PChoice qpn rdm gr cs) = - PChoice qpn rdm gr $ fmap (checkChild qpn) (fmap go cs) - go (FChoice qfn@(FN qpn _) rdm gr w m d cs) = - FChoice qfn rdm gr w m d $ fmap (checkChild qpn) (fmap go cs) - go (SChoice qsn@(SN qpn _) rdm gr w cs) = - SChoice qsn rdm gr w $ fmap (checkChild qpn) (fmap go cs) - go (GoalChoice rdm cs) = GoalChoice rdm (fmap go cs) - go x@(Fail _ _) = x - go x@(Done _ _) = x - - checkChild :: QPN -> Tree d c -> Tree d c - checkChild qpn x@(PChoice _ rdm _ _) = failIfCycle qpn rdm x - checkChild qpn x@(FChoice _ rdm _ _ _ _ _) = failIfCycle qpn rdm x - checkChild qpn x@(SChoice _ rdm _ _ _) = failIfCycle qpn rdm x - checkChild qpn x@(GoalChoice rdm _) = failIfCycle qpn rdm x - checkChild _ x@(Fail _ _) = x - checkChild qpn x@(Done rdm _) = failIfCycle qpn rdm x - - failIfCycle :: QPN -> RevDepMap -> Tree d c -> Tree d c - failIfCycle qpn rdm x = - case findCycles qpn rdm of - Nothing -> x - Just relSet -> Fail relSet CyclicDependencies -- | Given the reverse dependency map from a node in the tree, check -- if the solution is cyclic. If it is, return the conflict set containing -- all decisions that could potentially break the cycle. -- -- TODO: The conflict set should also contain flag and stanza variables. -findCycles :: QPN -> RevDepMap -> Maybe ConflictSet -findCycles pkg rdm = +findCycles :: QPN -> RevDepMap -> Maybe (ConflictSet, FailReason) +findCycles pkg rdm = (,CyclicDependencies) <$> -- This function has two parts: a faster cycle check that is called at every -- step and a slower calculation of the conflict set. -- @@ -102,19 +72,9 @@ findCycles pkg rdm = else foldl go (S.insert x s) $ neighbors x neighbors :: QPN -> [QPN] - neighbors x = case x `M.lookup` rdm of + neighbors x = case x `M.lookup` revDeps rdm of Nothing -> findCyclesError "cannot find node" Just xs -> map snd xs findCyclesError = error . ("Distribution.Solver.Modular.Cycles.findCycles: " ++) -data RevDepMapNode = RevDepMapNode QPN [(Component, QPN)] - -instance G.IsNode RevDepMapNode where - type Key RevDepMapNode = QPN - nodeKey (RevDepMapNode qpn _) = qpn - nodeNeighbors (RevDepMapNode _ ns) = ordNub $ map snd ns - -revDepMapToGraph :: RevDepMap -> G.Graph RevDepMapNode -revDepMapToGraph rdm = G.fromDistinctList - [RevDepMapNode qpn ns | (qpn, ns) <- M.toList rdm] diff --git a/cabal-install-solver/src/Distribution/Solver/Modular/Dependency.hs b/cabal-install-solver/src/Distribution/Solver/Modular/Dependency.hs index 195c9b71646..91fb6715fcf 100644 --- a/cabal-install-solver/src/Distribution/Solver/Modular/Dependency.hs +++ b/cabal-install-solver/src/Distribution/Solver/Modular/Dependency.hs @@ -25,7 +25,7 @@ module Distribution.Solver.Modular.Dependency ( , qualifyDeps , unqualifyDeps -- * Reverse dependency map - , RevDepMap + , RevDepMap(..) -- * Goals , Goal(..) , GoalReason(..) @@ -226,7 +226,7 @@ qualifyDeps QO{..} rdm (Q pp@(PackagePath ns q) pn) = go -- with the package-path of the package that introduced -- this dependency, which will match if this dependency is -- included in the same private scope. - case M.lookup (Q pp pnx) rdm of + case M.lookup (Q pp pnx) (revDeps rdm) of Just _x -> q -- found, use same private qualifier Nothing -> QualToplevel -- not found, use top level qual @@ -268,7 +268,12 @@ unqualifyDeps = go -- | A map containing reverse dependencies between qualified -- package names. -type RevDepMap = Map QPN [(Component, QPN)] +data RevDepMap = RevDepMap + { revDeps :: Map QPN [(Component, QPN)] + -- ^ The reverse dependencies + , privScopes :: Map Qualifier {- a private qualifier -} (S.Set QPN) {- caches the packages in this private scope -} + -- ^ Information related to reverse dependency mapped additionally cached here. + } {------------------------------------------------------------------------------- Goals diff --git a/cabal-install-solver/src/Distribution/Solver/Modular/Explore.hs b/cabal-install-solver/src/Distribution/Solver/Modular/Explore.hs index fe54752771d..cf1544bc0fd 100644 --- a/cabal-install-solver/src/Distribution/Solver/Modular/Explore.hs +++ b/cabal-install-solver/src/Distribution/Solver/Modular/Explore.hs @@ -274,7 +274,6 @@ exploreLog mbj enableBj fineGrainedConflicts (CountConflicts countConflicts) idx couldBeResolved :: CS.Conflict -> Maybe ConflictSet couldBeResolved CS.OtherConflict = Nothing - couldBeResolved (CS.PrivateScopeClosureConflict _ _) = Nothing -- Could we optimise here? couldBeResolved (CS.GoalConflict conflictingDep) = -- Check whether this package instance also has 'conflictingDep' -- as a dependency (ignoring flag and stanza choices). diff --git a/cabal-install-solver/src/Distribution/Solver/Modular/Message.hs b/cabal-install-solver/src/Distribution/Solver/Modular/Message.hs index 8f1b05c23e9..3eb01081efb 100644 --- a/cabal-install-solver/src/Distribution/Solver/Modular/Message.hs +++ b/cabal-install-solver/src/Distribution/Solver/Modular/Message.hs @@ -181,7 +181,6 @@ showConflicts conflicts = Just (qpn, MergedPackageConflict False [v] Nothing) toMergedConflict (CS.VersionConflict qpn (CS.OrderedVersionRange vr)) = Just (qpn, MergedPackageConflict False [] (Just vr)) - toMergedConflict (CS.PrivateScopeClosureConflict _ _) = Nothing toMergedConflict CS.OtherConflict = Nothing showConflict :: QPN -> MergedPackageConflict -> String @@ -303,7 +302,12 @@ showFR c Backjump = " (backjumping, conflict set: " ++ s showFR _ MultipleInstances = " (multiple instances)" showFR c (DependenciesNotLinked msg) = " (dependencies not linked: " ++ msg ++ "; conflict set: " ++ showConflictSet c ++ ")" showFR c CyclicDependencies = " (cyclic dependencies; conflict set: " ++ showConflictSet c ++ ")" -showFR c (InvalidPrivateScope qual) = " (private scopes must contain its closure, but package " ++ showConflictSet c ++ " is not included in the private scope " ++ prettyShow qual ++ ")" +showFR c (InvalidPrivateScope qual) + = " (a private scope must contain its closure, but package" ++ plural ++ " " ++ showConflictSet c ++ " " ++ isOrAre ++ " not included in the private scope " ++ prettyShow qual ++ ")" + where + (plural, isOrAre) + | [_] <- CS.toList c = ("", "is") + | otherwise = ("s", "are") showFR _ (UnsupportedSpecVer ver) = " (unsupported spec-version " ++ prettyShow ver ++ ")" -- The following are internal failures. They should not occur. In the -- interest of not crashing unnecessarily, we still just print an error diff --git a/cabal-install-solver/src/Distribution/Solver/Modular/PrivateScopeClosure.hs b/cabal-install-solver/src/Distribution/Solver/Modular/PrivateScopeClosure.hs index 82e3c4f5637..1f70972e6bf 100644 --- a/cabal-install-solver/src/Distribution/Solver/Modular/PrivateScopeClosure.hs +++ b/cabal-install-solver/src/Distribution/Solver/Modular/PrivateScopeClosure.hs @@ -1,126 +1,202 @@ +{-# LANGUAGE BangPatterns #-} +{-# LANGUAGE LambdaCase #-} {-# LANGUAGE TupleSections #-} +{-# LANGUAGE ViewPatterns #-} module Distribution.Solver.Modular.PrivateScopeClosure where -import Control.Exception (assert) +import Data.Maybe +import qualified Data.Set as S import Prelude hiding (cycle) import qualified Data.Map as M import Distribution.Solver.Modular.Dependency -import Distribution.Solver.Modular.Flag import Distribution.Solver.Modular.Tree import qualified Distribution.Solver.Modular.ConflictSet as CS import Distribution.Solver.Types.PackagePath --- | Find and reject any nodes that would violate the private-dependencies --- closure property, which states that all packages within the closure of a --- private scope must also be included in the private scope. -detectInvalidPrivateScopesPhase :: Tree d c -> Tree d c -detectInvalidPrivateScopesPhase = go - where - -- Similar to detectCyclesPhase, maybe we could deduplicate - go :: Tree d c -> Tree d c - go (PChoice qpn rdm gr cs) = - PChoice qpn rdm gr $ fmap (checkChild qpn) (fmap go cs) - go (FChoice qfn@(FN qpn _) rdm gr w m d cs) = - FChoice qfn rdm gr w m d $ fmap (checkChild qpn) (fmap go cs) - go (SChoice qsn@(SN qpn _) rdm gr w cs) = - SChoice qsn rdm gr w $ fmap (checkChild qpn) (fmap go cs) - go (GoalChoice rdm cs) = GoalChoice rdm (fmap go cs) - go x@(Fail _ _) = x - go x@(Done _ _) = x - - checkChild :: QPN -> Tree d c -> Tree d c - checkChild qpn x@(PChoice _ rdm _ _) = failIfBadClosure qpn rdm x - checkChild qpn x@(FChoice _ rdm _ _ _ _ _) = failIfBadClosure qpn rdm x - checkChild qpn x@(SChoice _ rdm _ _ _) = failIfBadClosure qpn rdm x - checkChild qpn x@(GoalChoice rdm _) = failIfBadClosure qpn rdm x - checkChild _ x@(Fail _ _) = x - checkChild qpn x@(Done rdm _) = failIfBadClosure qpn rdm x - - failIfBadClosure :: QPN -> RevDepMap -> Tree d c -> Tree d c - -- An already qualified package can't violate the closure property - failIfBadClosure (Q (PackagePath _ (QualAlias _ _ _)) _) _ x = x - failIfBadClosure qpn rdm x = - case findBadClosures qpn rdm of - Nothing -> x - Just (relSet, qual) -> Fail relSet (InvalidPrivateScope qual) - -- | Given the reverse dependency map from a node in the tree, check if the --- solution has any bad closures. If it is, return the conflict set containing +-- solution has any bad closures. If it does, return the conflict set containing -- the variables violating private deps closures. -findBadClosures :: QPN -> RevDepMap -> Maybe (ConflictSet, Qualifier) -findBadClosures pkg rdm = - case concatMap (\root@(Q (PackagePath _ ps) _) -> (root,) <$> concatMap (step ps False . snd) (findRevDepsTopLevel root)) roots of - (closureBegin@(Q (PackagePath _ ql) _), closureEnd@(Q (PackagePath _ ql') _)):_ -> - assert (ql == ql') $ - return (CS.singletonWithConflict (P pkg) (CS.PrivateScopeClosureConflict closureBegin closureEnd), ql) - [] -> Nothing +-- +-- INVARIANT: The RevDepMap forms an acyclic graph (guaranteed by this check running after 'findCycles') +findBadPrivClosures :: QPN + -- ^ Newly added package that I need to check if violates property + -> RevDepMap + -> Maybe (ConflictSet, FailReason) +{- +Note [The Private Scope Closure Property Check] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +In practice, for every package that is added to the solution (the 'QPN'), we ask: +Does choosing this package violate the closure property? +By case analysis: + + (a) If the package X introduced is in a private scope S, then S may now + violate the closure property. To determine so, + * We take the list of packages in that same private scope S[1] (the + so-called "roots" of the check) + + * And compute, for each root, the up-to-private reverse-dependency + closure[2] of that package X qualified with QualTopLevel instead of the + private scope[3]. + + * If we were able to reach the private scope S from the "special closure" of the + top-level-qualified roots, the closure property is violated! + + (b) If the package X introduced is NOT in a private scope, we need to + determine all packages Ys in private scopes PSs that depend on this package X. + * We do so by traversing upwards from X, ie computing the up-to-private + reverse-dependency closure[2] of X. + + * For every private scope PS reached from traversing upwards from X + (possibleBadPrivateScopes), we get the list of packages in that private + scope PS (see [1] again), the "roots" of this branch of the check. + + * For every package (aka root) in that private scope, we traverse upwards + from the top-level-qualified root[3] until we find another private scope + or until we find the "original" package X from which we originally + computed the reachable roots. + + This is similar to up-to-private reverse-dependency closure[2] of the + root but we also stop traversing upwards if we find the package X. + + * If the package X is reachable from any of the private scopes' roots + then the property is violated. That is, if we can reach PS from the + (non-private) X, and one of the roots of PS can reach X too, then X sits + unqualified between two packages in the private scope (violating the + closure property) + +Additionally, when the private closure property is violated for some private +qualifier Q, we compute the packages missing from the private scope for it +to be valid (see 'computeBadPkgs'). + +[1] We associate private scopes to the set of packages contained in it in a +cache in the 'RevDepMap' (the 'privScopes' field). We insert into this +mapping around the same time a package is introduced in the reverse +dependency map, if the package has a private scope. + +This cache is needed for the 'findBadPrivClosures' check to be fast, because +we always need to find the set of packages in a given private scope to perform the check. + +[2] The up-to-private reverse-dependency closure of X is the +reverse-dependency closure of X, constructed by traversing upwards the +reverse dependency map, with the twist of stopping at any +privately-qualified reverse dependency. + +The function which computes this 'upwardsClosure' local to 'findBadPrivClosures'. +When the first argument is 'True', we additionally stop when the package X is reached. + +We use this "special closure" because dependencies introduced by packages in +a private scope can only violate the property of that scope (it is +impossible for them to violate the property of scopes further upward) + +[3] When we traverse upwards from a privately-qualified root, we want to +first unqualify the root and search the unqualified space. The local function +'findRevDepsTopLevel' explains in more detail with an example. + +-} +findBadPrivClosures pkg rdm = do + -- Maybe a bad scope and the reachable-from-roots map + let badScopeAndPaths = + case pkg of + Q (PackagePath _ ql@QualAlias{}) _ -> do + -- (a) case + let + roots = pkgsInPrivScope ql + reachableTopLevel = upwardsClosure False (concatMap findRevDepsTopLevel roots) + isViolated = + -- From the top level roots there can be no package in the same private scope reachable + any ((== ql) . getQual) (M.keys reachableTopLevel) + in + if isViolated then Just (ql, reachableTopLevel) else Nothing + + Q (PackagePath _ _) _ -> do + -- (b) case + let + upClosureFromPkg = upwardsClosure False [pkg] + roots = + -- Filter out from the scope packages which were reached from `pkg`: + S.filter (not . (`M.member` upClosureFromPkg)) $ + M.foldrWithKey (\p _ acc -> + if hasPrivateQual p -- privately-qualified package reached from `pkg` + then (pkgsInPrivScope (getQual p)) <> acc + else acc) S.empty upClosureFromPkg + reachableTopLevel = + S.map (\x -> (getQual x, upwardsClosure True $ findRevDepsTopLevel x)) roots + invalidScopes = + -- For any of the qualifiers, if the package is reachable from + -- the roots the prv scope of that root is bad + S.filter (any (== pkg) . M.keys . snd) reachableTopLevel + in + case S.toList invalidScopes of + -- We only report one bad scope. Eventually we could report more. + (ql,rbl):_ -> Just (ql, M.unionWith (<>) rbl upClosureFromPkg {- report with the remaining half of the closure too -}) + [] -> Nothing + + + (badScope, paths) <- badScopeAndPaths + -- All packages in paths from roots to terminal nodes in the same private scope + let badPkgs = concat . M.elems . M.filterWithKey (\k _ -> badScope == getQual k) $ paths + return (CS.fromList $ map P badPkgs, InvalidPrivateScope badScope) + + where - -- Roots of the rev dep map with QualAlias/private scope - roots :: [QPN] - roots = flip M.foldMapWithKey rdm $ - \key _ -> case key of - Q (PackagePath _ (QualAlias _ _ _)) _ -> [key] - _ -> [] - - -- Traverse up from a root until a reverse dep in the same private scope is - -- found. We only traverse up until we find another private dep in the same - -- scope because that is sufficient to complete a "local closure", and - -- because we traverse from all root deps in private scopes, we will - -- traverse all the "local" closures thus the full closure of each scope... REWRITE and RENAME - step :: Qualifier -- ^ This root's qualifier/private scope - -> Bool -- ^ Have we found the "goal" package in the "local" closure - -> QPN -- ^ Next package in the closure traversal - -> [QPN] - -- ^ The terminal nodes for each closure violated by this package. - -- Empty if the closure property is kept. - step rootQual hasFoundGoal next - -- We stop at any qualified reverse dep, even if it does not belong to - -- the same scope as the one we are checking for the closure property. - -- By case analysis: - -- * If it is the same scope, we've reached the end of the local - -- closure, and if the package has been seen as non-qualified then the - -- property is violated - -- - -- * If it is not the same scope, that means "next" in that branch is a - -- dep of a private scope goal, but it may not violate the closure - -- property for that one. Even if it were to violate the property - -- outside of a nested private scope, it doesn't matter because within a - -- (nested) private scope it just has to be consistent in - -- itself......... - | Q (PackagePath _ ps@(QualAlias _ _ _)) _ <- next - = if ps == rootQual && hasFoundGoal - then [next] - else [] - | otherwise - = case findRevDepsTopLevel next of - -- If there are no more deps (meaning we didn't stop at any rev-dep in - -- a private scope), then we don't have a private scope closure and the - -- property is preserved. - [] -> [] - -- Step through all the next reverse deps, failing (by adding terminal - -- nodes to the result) if any of the steps violates the closure - -- property - xs -> - -- If the next pkg is our goal, we recurse with "hasFoundGoal = - -- True", otherwise with what we had previously - let hasFoundGoal' = next == pkg || hasFoundGoal - in concatMap (step rootQual hasFoundGoal' . snd) xs + pkgsInPrivScope :: Qualifier -> S.Set QPN + pkgsInPrivScope ql' = fromMaybe (error "all private scopes should be cached") $ M.lookup ql' (privScopes rdm) -- Find the reverse dependencies of this QPN, but in the top-level scope. - -- When constructing the closure, starting from a qualified root, we need - -- to take into account that the dependencies introduced by the - -- private-scoped-depends will be in the top level scope... - findRevDepsTopLevel qpn@(Q (PackagePath namespace _) pn) = - case (Q (PackagePath namespace QualToplevel) pn) `M.lookup` rdm of + -- + -- Recall that the private closure property may only be violated by pkgA + -- depending privately on pkgB and pkgD, but not on pkgC, when + -- pkgB --top-level-depends-> pkgC + -- pkgC --top-level-depends-> pkgD + -- + -- In the reverse dependency map we'd have + -- pkgD(private) --rd-> pkgA(top) + -- pkgB(private) --rd-> pkgA(top) + -- pkgC(top) --rd-> pkgB(private) + -- pkgD(top) --rd-> pkgC(top) + -- + -- So, for each pkg with a private scope (like pkgD or pkgB), we look for + -- the top-level equivalent of that package (this function), and will + -- traverse up until we find (or not) that there is a reverse dep on a + -- package in the same private scope as the root from which we started. + findRevDepsTopLevel (Q (PackagePath namespace _) pn) = + case (Q (PackagePath namespace QualToplevel) pn) `M.lookup` revDeps rdm of Nothing -> - -- This means the package we are looking up in the map has only been - -- introduced qualified, not at the QualToplevel. This means we look - -- it up as is. - case qpn `M.lookup` rdm of - Nothing -> findError "cannot find node" - Just rdeps -> rdeps - Just rdeps -> rdeps - - findError = error . ("Distribution.Solver.Modular.PrivateScopeClosure.findBadClosures: " ++) + -- If this package wasn't at the top-level means there is no + -- top-level package publicly depending on it. Nothing to worry about then. + [] + Just rdeps -> map snd rdeps + + getQual (Q (PackagePath _ ql) _) = ql + + hasPrivateQual :: QPN -> Bool + hasPrivateQual = \case + Q (PackagePath _ QualAlias{}) _ -> True + _ -> False + + upwardsClosure :: Bool {- Whether to stop traversing when `pkg` is found -} + -> [QPN] {- ps roots in qualtoplevel -} + -> M.Map QPN [QPN] {- all the things you can reach (stopping at pkg and on any private thing); only lookup privately qualified packages!-} + upwardsClosure stopAtPkg = fst . foldl go mempty + where + go :: (M.Map QPN [QPN] {- de-duplicate things we've seen -}, [QPN]) + -> QPN -> (M.Map QPN [QPN], [QPN]) + go (s,path) x + | x `M.member` s + = (s, path) + | hasPrivateQual x + = (M.insert x path s, path) + | stopAtPkg && x == pkg + = (M.insert x (dontLook x) s, path) + | otherwise + = foldl go (M.insert x (dontLook x) s, x:path) $ neighbors x + + dontLook x = error $ "We should only lookup privately-qualified pkgs, but instead " ++ show x ++ " was looked up -- it is only inserted in the map for de-duplication purposes." + + neighbors :: QPN -> [QPN] + neighbors x = case x `M.lookup` revDeps rdm of + Nothing -> error $ "cannot find node: " ++ show x + Just xs -> map snd xs + diff --git a/cabal-install-solver/src/Distribution/Solver/Modular/Solver.hs b/cabal-install-solver/src/Distribution/Solver/Modular/Solver.hs index 98498813126..a1e57408670 100644 --- a/cabal-install-solver/src/Distribution/Solver/Modular/Solver.hs +++ b/cabal-install-solver/src/Distribution/Solver/Modular/Solver.hs @@ -36,6 +36,7 @@ import Distribution.Solver.Modular.Log import Distribution.Solver.Modular.Message import Distribution.Solver.Modular.Package import qualified Distribution.Solver.Modular.Preference as P +import Distribution.Solver.Modular.ValidateDependencies import Distribution.Solver.Modular.PrivateScopeClosure import Distribution.Solver.Modular.Validate import Distribution.Solver.Modular.Linking @@ -99,10 +100,11 @@ solve :: SolverConfig -- ^ solver parameters -> RetryLog Message SolverFailure (Assignment, RevDepMap) solve sc cinfo idx pkgConfigDB userPrefs userConstraints userGoals = explorePhase . - traceTree "invalid-scopes.json" id . - detectInvalidPrivateScopesPhase . - traceTree "cycles.json" id . - detectCycles . + traceTree "invalid-dep-graph.json" id . + detectInvalidDepGraphPhase + [ findCycles -- this first + , findBadPrivClosures -- then this + ] . traceTree "heuristics.json" id . trav ( heuristicsPhase . @@ -121,7 +123,6 @@ solve sc cinfo idx pkgConfigDB userPrefs userConstraints userGoals = (fineGrainedConflicts sc) (countConflicts sc) idx - detectCycles = detectCyclesPhase heuristicsPhase = let sortGoals = case goalOrder sc of diff --git a/cabal-install-solver/src/Distribution/Solver/Modular/ValidateDependencies.hs b/cabal-install-solver/src/Distribution/Solver/Modular/ValidateDependencies.hs new file mode 100644 index 00000000000..37edcfefc81 --- /dev/null +++ b/cabal-install-solver/src/Distribution/Solver/Modular/ValidateDependencies.hs @@ -0,0 +1,66 @@ +{-# LANGUAGE TypeFamilies #-} +module Distribution.Solver.Modular.ValidateDependencies ( + detectInvalidDepGraphPhase + , RevDepMapNode(..) + , revDepMapToGraph + ) where + +import Prelude hiding (cycle) +import qualified Data.Map as M + +import qualified Distribution.Compat.Graph as G +import Distribution.Simple.Utils (ordNub) +import Distribution.Solver.Modular.Dependency +import Distribution.Solver.Modular.Flag +import Distribution.Solver.Modular.Tree +import Distribution.Solver.Types.ComponentDeps (Component) +import Distribution.Solver.Types.PackagePath + +-- | Run checks on the dependencies at every node, such as the cycle check +-- 'findCycles' and the private scope closure check 'findBadPrivClosures' +detectInvalidDepGraphPhase :: [QPN -> RevDepMap -> Maybe (ConflictSet, FailReason)] + -- ^ The list of checks to run at every node, run left to right. + -> Tree d c -> Tree d c +detectInvalidDepGraphPhase checks = go + where + -- Only check children of choice nodes. + go :: Tree d c -> Tree d c + go (PChoice qpn rdm gr cs) = + PChoice qpn rdm gr $ fmap (checkChild qpn) (fmap go cs) + go (FChoice qfn@(FN qpn _) rdm gr w m d cs) = + FChoice qfn rdm gr w m d $ fmap (checkChild qpn) (fmap go cs) + go (SChoice qsn@(SN qpn _) rdm gr w cs) = + SChoice qsn rdm gr w $ fmap (checkChild qpn) (fmap go cs) + go (GoalChoice rdm cs) = GoalChoice rdm (fmap go cs) + go x@(Fail _ _) = x + go x@(Done _ _) = x + + checkChild :: QPN -> Tree d c -> Tree d c + checkChild qpn x@(PChoice _ rdm _ _) = failIfBad qpn rdm x + checkChild qpn x@(FChoice _ rdm _ _ _ _ _) = failIfBad qpn rdm x + checkChild qpn x@(SChoice _ rdm _ _ _) = failIfBad qpn rdm x + checkChild qpn x@(GoalChoice rdm _) = failIfBad qpn rdm x + checkChild _ x@(Fail _ _) = x + checkChild qpn x@(Done rdm _) = failIfBad qpn rdm x + + failIfBad :: QPN -> RevDepMap -> Tree d c -> Tree d c + failIfBad qpn rdm x = maybe x (uncurry Fail) (goCheck checks) where + goCheck :: [QPN -> RevDepMap -> Maybe (ConflictSet, FailReason)] -> Maybe (ConflictSet, FailReason) + goCheck [] = Nothing -- no more check, succeed + goCheck (c:cs) = + case c qpn rdm of + Nothing -> + -- success for this check, but we need to run all checks + goCheck cs + Just f -> Just f + +data RevDepMapNode = RevDepMapNode QPN [(Component, QPN)] + +instance G.IsNode RevDepMapNode where + type Key RevDepMapNode = QPN + nodeKey (RevDepMapNode qpn _) = qpn + nodeNeighbors (RevDepMapNode _ ns) = ordNub $ map snd ns + +revDepMapToGraph :: RevDepMap -> G.Graph RevDepMapNode +revDepMapToGraph rdm = G.fromDistinctList + [RevDepMapNode qpn ns | (qpn, ns) <- M.toList $ revDeps rdm] diff --git a/cabal-install/tests/UnitTests/Distribution/Solver/Modular/Solver.hs b/cabal-install/tests/UnitTests/Distribution/Solver/Modular/Solver.hs index bed7ead4f13..be9863f9042 100644 --- a/cabal-install/tests/UnitTests/Distribution/Solver/Modular/Solver.hs +++ b/cabal-install/tests/UnitTests/Distribution/Solver/Modular/Solver.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE BlockArguments #-} {-# LANGUAGE OverloadedStrings #-} -- | This is a set of unit tests for the dependency solver, @@ -7,10 +8,15 @@ module UnitTests.Distribution.Solver.Modular.Solver (tests) where -- base + +import Control.Monad import Data.List (isInfixOf) import qualified Distribution.Version as V +-- mtl +import Control.Monad.State + -- test-framework import Test.Tasty as TF import Test.Tasty.ExpectedFailure @@ -24,6 +30,7 @@ import Language.Haskell.Extension -- cabal-install +import Data.Bifunctor import qualified Distribution.Solver.Types.ComponentDeps as P import Distribution.Solver.Types.Flag import Distribution.Solver.Types.OptionalStanza @@ -881,6 +888,9 @@ tests = , runTest privDep13 , runTest privDep14 , runTest privDep15 + -- These tests should only be run manually! (Not enabled by default) + -- , runTest $ _manualPrivDepsStressTest True + -- , runTest $ _manualPrivDepsStressTestWithBacktracking True ] , -- Tests for the contents of the solver's log testGroup @@ -2786,7 +2796,7 @@ privDep10 = priv_db10 "private-dependencies-10" ["P"] - (solverResult (any ("private scopes must contain its closure, but package B is not included in the private scope P:lib:G0." `isInfixOf`)) [("P", 1)]) + (solverResult (any ("a private scope must contain its closure, but package B is not included in the private scope P:G0" `isInfixOf`)) [("P", 1)]) -- Testing constraints DON'T apply to private dependencies priv_db11 :: ExampleDb @@ -2846,6 +2856,87 @@ privDep15 = setVerbose $ mkTest priv_db15 "private-dependencies-15" ["P"] (solverSuccess [("A", 1), ("P", 1)]) +uniqPkgName :: State Int String +uniqPkgName = do + i <- get + modify' (+ 1) + return ("pkgN" ++ show i) +uniqScope :: State Int String +uniqScope = do + i <- get + modify' (+ 1) + return ("S" ++ show i) + +-- The stress test for private dependencies without backtracking +manual_priv_stress + :: Bool + -- ^ Use private scopes? + -> ExampleDb +manual_priv_stress usePrivScopes = (`evalState` 1) do + (deps, depsOfDeps) <- bimap concat concat . unzip <$> forM [1 .. param] (const $ mkPkg param) + return ([Right $ exAv "P" 1 $ map (ExAny . exAvName) deps] ++ map Right (deps ++ depsOfDeps)) + where + param :: Int + param = 6 + + mkPkg :: Int -> State Int ([ExampleAvailable], [ExampleAvailable]) + mkPkg 0 = return ([], []) + mkPkg i = do + (depPkgs, depsOfDeps) <- bimap concat concat . unzip <$> forM [1 .. param] (const $ mkPkg (i - 1)) + deps <- + concat <$> forM (zip depPkgs [(1 :: Int) ..]) \(p, ix) -> + if even ix && usePrivScopes + then do + sc <- uniqScope + return [ExAnyPriv sc (exAvName p)] + else return [ExAny (exAvName p)] -- note, no backtracking so no constraints. + pkgid <- uniqPkgName + return ([exAv pkgid 1 deps], (depPkgs ++ depsOfDeps)) + +-- The stress test for private dependencies with backtracking +manual_priv_stress_with_bt + :: Bool + -- ^ Use private scopes? + -> ExampleDb +manual_priv_stress_with_bt usePrivScopes = (`evalState` 1) do + (deps, depsOfDeps) <- bimap concat concat . unzip <$> forM [1 .. param] (const $ mkPkg param) + return ([Right $ exAv "P" 1 $ map (ExAny . exAvName) deps] ++ map Right (deps ++ depsOfDeps)) + where + param :: Int + param = 5 + + mkPkg :: Int -> State Int ([ExampleAvailable], [ExampleAvailable]) + mkPkg 0 = return ([], []) + mkPkg i = do + (depPkgs, depsOfDeps) <- bimap concat concat . unzip <$> forM [1 .. param] (const $ mkPkg (i - 1)) + let nn n = + concat <$> forM (zip depPkgs [(1 :: Int) ..]) \(p, ix) -> + let ver = if ix `mod` n == 0 then 1 else 2 + in if even ix && usePrivScopes + then do + sc <- uniqScope + return [ExFixPriv sc (exAvName p) ver] + else return [ExFix (exAvName p) ver] + deps <- nn 13 + deps' <- nn 14 + pkgid <- uniqPkgName + return ([exAv pkgid 1 deps, exAv pkgid 2 deps'], (depPkgs ++ depsOfDeps)) + +-- | This is a stress test of private dependencies which should be manually +-- enabled for local testing, but not enabled in CI. +_manualPrivDepsStressTest :: Bool -> SolverTest +_manualPrivDepsStressTest b = + setVerbose $ + mkTest (manual_priv_stress b) "manual-private-dependencies-stress-test" ["P"] (solverSuccess [("P", 1)]) + +-- | This is a stress test of private dependencies which should be manually +-- enabled for local testing, but not enabled in CI. +-- It is quite hard to provoke backtracking in a procedural test, but here's an attempt. +_manualPrivDepsStressTestWithBacktracking :: Bool -> SolverTest +_manualPrivDepsStressTestWithBacktracking b = + setVerbose $ + mkTest (manual_priv_stress_with_bt b) "manual-private-dependencies-stress-test-backtrack" ["P"] (solverSuccess [("P", 1)]) + -- | Returns true if the second list contains all elements of the first list, in -- order. containsInOrder :: Eq a => [a] -> [a] -> Bool diff --git a/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/cabal.test.hs b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/cabal.test.hs index 13215233402..409e47a3174 100644 --- a/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/cabal.test.hs +++ b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-test/cabal.test.hs @@ -7,7 +7,7 @@ main = do withProjectFile "cabal.project.1" $ withRepo "repo" $ fails (cabal' "v2-build" ["libA"]) - >>= assertOutputContains "private scopes must contain its closure, but package libC is not included in the private scope libA:lib:G0" + >>= assertOutputContains "a private scope must contain its closure, but package libC is not included in the private scope libA:G0" -- Must pick libC == 0.1 withProjectFile "cabal.project.2" $ diff --git a/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/cabal.test.hs b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/cabal.test.hs index 293588f009e..8128995e676 100644 --- a/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/cabal.test.hs +++ b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/cabal.test.hs @@ -16,16 +16,14 @@ because of the conflict too main = cabalTest $ recordMode DoNotRecord $ do - withProjectFile "cabal.project.scenea" $ + -- withProjectFile "cabal.project.scenea" $ -- For some reason this doesn't work... withRepo "repo" $ do -- Succeeds because SameName from pkgA and SameName from pkgB do not collide. - cabal "build" ["pkgA"] - withProjectFile "cabal.project.sceneb" $ + cabal "build" ["pkgA", "--project-file=cabal.project.scenea"] withRepo "repo" $ do -- Fails because SameName from pkgC in its two separate components - cabal "build" ["pkgC"] - withProjectFile "cabal.project.scenec" $ + cabal "build" ["pkgC", "--project-file=cabal.project.sceneb"] withRepo "repo" $ do -- Fails because SameName from pkgD in the same component - cabal "build" ["pkgD"] + cabal "build" ["pkgD", "--project-file=cabal.project.scenec"] diff --git a/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgA/CHANGELOG.md b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgA/CHANGELOG.md deleted file mode 100644 index 6c1d0fed1d1..00000000000 --- a/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgA/CHANGELOG.md +++ /dev/null @@ -1,5 +0,0 @@ -# Revision history for pkgA - -## 0.1.0.0 -- YYYY-mm-dd - -* First version. Released on an unsuspecting world. diff --git a/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgA/pkgA.cabal b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgA/pkgA.cabal index 1c667562329..b081ea9530b 100644 --- a/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgA/pkgA.cabal +++ b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgA/pkgA.cabal @@ -3,7 +3,6 @@ name: pkgA version: 0.1.0.0 license: NONE build-type: Simple -extra-doc-files: CHANGELOG.md common warnings ghc-options: -Wall diff --git a/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgB/CHANGELOG.md b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgB/CHANGELOG.md deleted file mode 100644 index 6c1d0fed1d1..00000000000 --- a/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgB/CHANGELOG.md +++ /dev/null @@ -1,5 +0,0 @@ -# Revision history for pkgA - -## 0.1.0.0 -- YYYY-mm-dd - -* First version. Released on an unsuspecting world. diff --git a/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgB/pkgB.cabal b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgB/pkgB.cabal index d1cef9a5ecd..d1c0dff0489 100644 --- a/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgB/pkgB.cabal +++ b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgB/pkgB.cabal @@ -3,7 +3,6 @@ name: pkgB version: 0.1.0.0 license: NONE build-type: Simple -extra-doc-files: CHANGELOG.md common warnings ghc-options: -Wall diff --git a/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgC/CHANGELOG.md b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgC/CHANGELOG.md deleted file mode 100644 index 6c1d0fed1d1..00000000000 --- a/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgC/CHANGELOG.md +++ /dev/null @@ -1,5 +0,0 @@ -# Revision history for pkgA - -## 0.1.0.0 -- YYYY-mm-dd - -* First version. Released on an unsuspecting world. diff --git a/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgC/app/Main.hs b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgC/app/Main.hs new file mode 100644 index 00000000000..76a9bdb5d48 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgC/app/Main.hs @@ -0,0 +1 @@ +main = pure () diff --git a/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgC/pkgC.cabal b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgC/pkgC.cabal index 7a75f05b208..a2798b523ee 100644 --- a/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgC/pkgC.cabal +++ b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgC/pkgC.cabal @@ -3,7 +3,6 @@ name: pkgC version: 0.1.0.0 license: NONE build-type: Simple -extra-doc-files: CHANGELOG.md common warnings ghc-options: -Wall @@ -18,6 +17,7 @@ library executable myexe main-is: Main.hs + hs-source-dirs: app private-build-depends: SameName with (libA == 0.2.0.0) default-language: Haskell2010 build-depends: base diff --git a/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgD/CHANGELOG.md b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgD/CHANGELOG.md deleted file mode 100644 index 6c1d0fed1d1..00000000000 --- a/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgD/CHANGELOG.md +++ /dev/null @@ -1,5 +0,0 @@ -# Revision history for pkgA - -## 0.1.0.0 -- YYYY-mm-dd - -* First version. Released on an unsuspecting world. diff --git a/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgD/pkgD.cabal b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgD/pkgD.cabal index e3f6fe5644f..83b11345752 100644 --- a/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgD/pkgD.cabal +++ b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/pkgD/pkgD.cabal @@ -3,7 +3,6 @@ name: pkgD version: 0.1.0.0 license: NONE build-type: Simple -extra-doc-files: CHANGELOG.md common warnings ghc-options: -Wall diff --git a/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/repo/libA-0.1.0.0/CHANGELOG.md b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/repo/libA-0.1.0.0/CHANGELOG.md deleted file mode 100644 index 4e6fa27dd90..00000000000 --- a/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/repo/libA-0.1.0.0/CHANGELOG.md +++ /dev/null @@ -1,5 +0,0 @@ -# Revision history for libA - -## 0.1.0.0 -- YYYY-mm-dd - -* First version. Released on an unsuspecting world. diff --git a/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/repo/libA-0.1.0.0/libA.cabal b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/repo/libA-0.1.0.0/libA.cabal index ced6e1bbe92..8162c86fb8f 100644 --- a/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/repo/libA-0.1.0.0/libA.cabal +++ b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/repo/libA-0.1.0.0/libA.cabal @@ -3,7 +3,6 @@ name: libA version: 0.1.0.0 license: NONE build-type: Simple -extra-doc-files: CHANGELOG.md common warnings ghc-options: -Wall diff --git a/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/repo/libA-0.2.0.0/CHANGELOG.md b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/repo/libA-0.2.0.0/CHANGELOG.md deleted file mode 100644 index 4e6fa27dd90..00000000000 --- a/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/repo/libA-0.2.0.0/CHANGELOG.md +++ /dev/null @@ -1,5 +0,0 @@ -# Revision history for libA - -## 0.1.0.0 -- YYYY-mm-dd - -* First version. Released on an unsuspecting world. diff --git a/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/repo/libA-0.2.0.0/libA.cabal b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/repo/libA-0.2.0.0/libA.cabal index 45452d179b1..84a8664ca62 100644 --- a/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/repo/libA-0.2.0.0/libA.cabal +++ b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/repo/libA-0.2.0.0/libA.cabal @@ -3,7 +3,6 @@ name: libA version: 0.2.0.0 license: NONE build-type: Simple -extra-doc-files: CHANGELOG.md common warnings ghc-options: -Wall From b7469fbe7180c0c32b97c980ac982e3c1b949a9e Mon Sep 17 00:00:00 2001 From: Rodrigo Mesquita Date: Fri, 26 Apr 2024 12:20:50 +0100 Subject: [PATCH 09/12] priv deps: Don't component qualify private scopes Originally, we were qualifying a private dependency with the component with that private dep. Now, we qualify a private dependency without the component, i.e. only with the package name and the scope name. However, we want the same private scope name to be shared across all components of a package (and, if different dependencies are desired across components, different scope names should be used). For example, the following package should not be possible to solve (and does not with this commit): cabal-version: 3.0 name: pkgC version: 0.1.0.0 build-type: Simple library private-build-depends: SameName with (libA == 0.1.0.0) build-depends: base executable myexe private-build-depends: SameName with (libA == 0.2.0.0) build-depends: base See the second case of the `same-scope-name` test. --- .../Solver/Modular/ConfiguredConversion.hs | 4 ++-- .../src/Distribution/Solver/Modular/Dependency.hs | 2 +- .../Distribution/Solver/Types/PackageConstraint.hs | 2 +- .../src/Distribution/Solver/Types/PackagePath.hs | 4 ++-- .../PrivateDeps/same-scope-name/cabal.test.hs | 14 +++++++++++--- 5 files changed, 17 insertions(+), 9 deletions(-) diff --git a/cabal-install-solver/src/Distribution/Solver/Modular/ConfiguredConversion.hs b/cabal-install-solver/src/Distribution/Solver/Modular/ConfiguredConversion.hs index 31e11e90947..1b9d357fdd1 100644 --- a/cabal-install-solver/src/Distribution/Solver/Modular/ConfiguredConversion.hs +++ b/cabal-install-solver/src/Distribution/Solver/Modular/ConfiguredConversion.hs @@ -75,7 +75,7 @@ convConfId parent (PI (Q (PackagePath ns qn) pn) (I v loc)) = -- As below, we need to identify where `AliasPkg` applies. This is -- needed to qualify `solverPkgLibDeps` since we may have multiple -- instances of the same package qualified. - | QualAlias pn' _ alias <- qn + | QualAlias pn' alias <- qn , parent == Just pn' -> AliasPkg (PreExistingId sourceId pi) alias | otherwise @@ -84,7 +84,7 @@ convConfId parent (PI (Q (PackagePath ns qn) pn) (I v loc)) = -- Same reasoning as for exes, the "top" qualified goal is the one -- which is private and needs to be aliased, but there might be other goals underneath which -- are solved in the same scope (but are not private) - | QualAlias pn' _ alias <- qn + | QualAlias pn' alias <- qn , parent == Just pn' -> AliasPkg (PlannedId sourceId) alias | IndependentBuildTool _ pn' <- ns diff --git a/cabal-install-solver/src/Distribution/Solver/Modular/Dependency.hs b/cabal-install-solver/src/Distribution/Solver/Modular/Dependency.hs index 91fb6715fcf..cca47f92bb1 100644 --- a/cabal-install-solver/src/Distribution/Solver/Modular/Dependency.hs +++ b/cabal-install-solver/src/Distribution/Solver/Modular/Dependency.hs @@ -204,7 +204,7 @@ qualifyDeps QO{..} rdm (Q pp@(PackagePath ns q) pn) = go goD (Dep dep@(PkgComponent qpn (ExposedExe _)) is_private ci) _ = Dep (Q (PackagePath (IndependentBuildTool pn qpn) QualToplevel) <$> dep) is_private ci goD (Dep dep@(PkgComponent qpn (ExposedLib _)) is_private ci) comp - | Private pq <- is_private = Dep (Q (PackagePath ns (QualAlias pn comp pq)) <$> dep) is_private ci + | Private pq <- is_private = Dep (Q (PackagePath ns (QualAlias pn pq)) <$> dep) is_private ci | qBase qpn = Dep (Q (PackagePath ns (QualBase pn)) <$> dep) is_private ci | qSetup comp = Dep (Q (PackagePath (IndependentComponent pn ComponentSetup) QualToplevel) <$> dep) is_private ci | otherwise = Dep (Q (PackagePath ns (inheritedQ qpn) ) <$> dep) is_private ci diff --git a/cabal-install-solver/src/Distribution/Solver/Types/PackageConstraint.hs b/cabal-install-solver/src/Distribution/Solver/Types/PackageConstraint.hs index e8efe91dbe8..caa028e873e 100644 --- a/cabal-install-solver/src/Distribution/Solver/Types/PackageConstraint.hs +++ b/cabal-install-solver/src/Distribution/Solver/Types/PackageConstraint.hs @@ -87,7 +87,7 @@ constraintScopeMatches (ScopeTarget pn) (Q (PackagePath ns q) pn') = namespaceMatches (IndependentBuildTool {}) = False in namespaceMatches ns && q == QualToplevel && pn == pn' constraintScopeMatches (ScopePrivate spn alias c_pn) (Q (PackagePath _qual_ns q) c_pn') = - let qualMatches (QualAlias qual_pn _ qual_alias) = spn == qual_pn && alias == qual_alias + let qualMatches (QualAlias qual_pn qual_alias) = spn == qual_pn && alias == qual_alias qualMatches _ = False -- TODO: Check whether any ns should subsume qual_ns (if private constraint scopes grow namespaces...) in qualMatches q && c_pn == c_pn' diff --git a/cabal-install-solver/src/Distribution/Solver/Types/PackagePath.hs b/cabal-install-solver/src/Distribution/Solver/Types/PackagePath.hs index faa0eddb887..895ea6afba1 100644 --- a/cabal-install-solver/src/Distribution/Solver/Types/PackagePath.hs +++ b/cabal-install-solver/src/Distribution/Solver/Types/PackagePath.hs @@ -60,7 +60,7 @@ data Qualifier = | QualBase PackageName -- A goal which is solved per-component - | QualAlias PackageName Component PrivateAlias + | QualAlias PackageName PrivateAlias deriving (Eq, Ord, Show) @@ -75,7 +75,7 @@ data Qualifier = dispQualifier :: Qualifier -> Disp.Doc dispQualifier QualToplevel = Disp.empty dispQualifier (QualBase pn) = pretty pn <<>> Disp.text ".bb." -dispQualifier (QualAlias pn c alias) = pretty pn <<>> Disp.text ":" <<>> pretty c <<>> Disp.text ":" <<>> pretty alias <<>> Disp.text "." +dispQualifier (QualAlias pn alias) = pretty pn <<>> Disp.text ":" <<>> pretty alias <<>> Disp.text "." instance Pretty Qualifier where pretty = dispQualifier diff --git a/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/cabal.test.hs b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/cabal.test.hs index 8128995e676..aa32d62b765 100644 --- a/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/cabal.test.hs +++ b/cabal-testsuite/PackageTests/PrivateDeps/same-scope-name/cabal.test.hs @@ -17,13 +17,21 @@ because of the conflict too main = cabalTest $ recordMode DoNotRecord $ do -- withProjectFile "cabal.project.scenea" $ -- For some reason this doesn't work... + withRepo "repo" $ do -- Succeeds because SameName from pkgA and SameName from pkgB do not collide. - cabal "build" ["pkgA", "--project-file=cabal.project.scenea"] + out <- cabal' "build" ["pkgA", "--project-file=cabal.project.scenea"] + -- We build the two versions, one for each package's private deps. + assertOutputContains "- libA-0.1.0.0 (lib) (requires build)" out + assertOutputContains "- libA-0.2.0.0 (lib) (requires build)" out + withRepo "repo" $ do -- Fails because SameName from pkgC in its two separate components - cabal "build" ["pkgC", "--project-file=cabal.project.sceneb"] + fails (cabal' "build" ["pkgC", "--project-file=cabal.project.sceneb"]) + >>= assertOutputContains "rejecting: pkgC:SameName.libA-0.2.0.0 (conflict: pkgC => pkgC:SameName.libA==0.1.0.0)" + withRepo "repo" $ do -- Fails because SameName from pkgD in the same component - cabal "build" ["pkgD", "--project-file=cabal.project.scenec"] + fails (cabal' "build" ["pkgD", "--project-file=cabal.project.scenec"]) + >>= assertOutputContains "rejecting: pkgD:SameName.libA-0.2.0.0 (conflict: pkgD => pkgD:SameName.libA==0.1.0.0)" From 638a26b214863f3e0366f4f821cbc0aeb6c4618d Mon Sep 17 00:00:00 2001 From: Rodrigo Mesquita Date: Fri, 26 Apr 2024 13:44:42 +0100 Subject: [PATCH 10/12] priv deps: Drop ConstraintScope ScopePrivate Since we dropped the `Component` field of `ScopePrivate` in the previous commit, we can now use `ScopeQualified` instead of having a specific constructor `ScopePrivate`. This is mostly a clean up. --- .../Distribution/Solver/Types/PackageConstraint.hs | 14 ++------------ cabal-install/src/Distribution/Client/Targets.hs | 3 ++- .../Distribution/Solver/Modular/Solver.hs | 2 +- 3 files changed, 5 insertions(+), 14 deletions(-) diff --git a/cabal-install-solver/src/Distribution/Solver/Types/PackageConstraint.hs b/cabal-install-solver/src/Distribution/Solver/Types/PackageConstraint.hs index caa028e873e..b67eb771984 100644 --- a/cabal-install-solver/src/Distribution/Solver/Types/PackageConstraint.hs +++ b/cabal-install-solver/src/Distribution/Solver/Types/PackageConstraint.hs @@ -50,11 +50,6 @@ data ConstraintScope -- | The package with the specified name and qualifier. | ScopeQualified Namespace Qualifier PackageName - -- Apply a constraint to a private-build-depends scope - -- It is not sufficient to have ScopeQualified because we don't have enough - -- information in the constraint syntax to fill in the `Component` field of - -- `QualAlias` - | ScopePrivate PackageName PrivateAlias PackageName -- | The package with the specified name when it has a -- setup qualifier. | ScopeAnySetupQualifier PackageName @@ -75,7 +70,6 @@ scopeToPackageName (ScopeTarget pn) = pn scopeToPackageName (ScopeQualified _ _ pn) = pn scopeToPackageName (ScopeAnySetupQualifier pn) = pn scopeToPackageName (ScopeAnyQualifier pn) = pn -scopeToPackageName (ScopePrivate _ _ pn) = pn -- | Whether a ConstraintScope matches a qualified package name, the crucial -- function which determines the rules about when constraints apply. @@ -86,12 +80,8 @@ constraintScopeMatches (ScopeTarget pn) (Q (PackagePath ns q) pn') = namespaceMatches (IndependentComponent {}) = False namespaceMatches (IndependentBuildTool {}) = False in namespaceMatches ns && q == QualToplevel && pn == pn' -constraintScopeMatches (ScopePrivate spn alias c_pn) (Q (PackagePath _qual_ns q) c_pn') = - let qualMatches (QualAlias qual_pn qual_alias) = spn == qual_pn && alias == qual_alias - qualMatches _ = False - -- TODO: Check whether any ns should subsume qual_ns (if private constraint scopes grow namespaces...) - in qualMatches q && c_pn == c_pn' constraintScopeMatches (ScopeQualified ns cq cpn) (Q (PackagePath qual_ns q) cpn') = + -- Should we check whether ns subsumes qual_ns rather than equality? ns == qual_ns && cq == q && cpn == cpn' constraintScopeMatches (ScopeAnySetupQualifier pn) (Q pp pn') = @@ -103,8 +93,8 @@ constraintScopeMatches (ScopeAnyQualifier pn) (Q _ pn') = pn == pn' -- | Pretty-prints a constraint scope. dispConstraintScope :: ConstraintScope -> Disp.Doc dispConstraintScope (ScopeTarget pn) = pretty pn <<>> Disp.text "." <<>> pretty pn +dispConstraintScope (ScopeQualified _ (QualAlias apn alias) p) = Disp.text "private." <<>> pretty apn <<>> Disp.text "." <<>> pretty @PrivateAlias alias <<>> Disp.text ":" <<>> pretty p dispConstraintScope (ScopeQualified ns _q pn) = dispNamespace ns <<>> pretty pn -dispConstraintScope (ScopePrivate pn alias p) = Disp.text "private." <<>> pretty pn <<>> Disp.text "." <<>> pretty @PrivateAlias alias <<>> Disp.text ":" <<>> pretty p dispConstraintScope (ScopeAnySetupQualifier pn) = Disp.text "setup." <<>> pretty pn dispConstraintScope (ScopeAnyQualifier pn) = Disp.text "any." <<>> pretty pn diff --git a/cabal-install/src/Distribution/Client/Targets.hs b/cabal-install/src/Distribution/Client/Targets.hs index afef8c30223..bab0b0ded04 100644 --- a/cabal-install/src/Distribution/Client/Targets.hs +++ b/cabal-install/src/Distribution/Client/Targets.hs @@ -646,7 +646,8 @@ fromUserQualifier (UserQualComp pn cn) = IndependentComponent pn (componentNameT fromUserConstraintScope :: UserConstraintScope -> ConstraintScope fromUserConstraintScope (UserQualified q pn) = ScopeQualified (fromUserQualifier q) QualToplevel pn -fromUserConstraintScope (UserPrivateQualifier pn alias cpn) = ScopePrivate pn alias cpn +fromUserConstraintScope (UserPrivateQualifier pn alias cpn) = + ScopeQualified DefaultNamespace (QualAlias pn alias) cpn fromUserConstraintScope (UserAnySetupQualifier pn) = ScopeAnySetupQualifier pn fromUserConstraintScope (UserAnyQualifier pn) = ScopeAnyQualifier pn diff --git a/cabal-install/tests/UnitTests/Distribution/Solver/Modular/Solver.hs b/cabal-install/tests/UnitTests/Distribution/Solver/Modular/Solver.hs index be9863f9042..b555df8b3c3 100644 --- a/cabal-install/tests/UnitTests/Distribution/Solver/Modular/Solver.hs +++ b/cabal-install/tests/UnitTests/Distribution/Solver/Modular/Solver.hs @@ -2815,7 +2815,7 @@ privDep11 = privDep12 :: SolverTest privDep12 = setVerbose $ - constraints [ExVersionConstraint (ScopePrivate "P" "G0" "A") (V.thisVersion (V.mkVersion [2]))] $ + constraints [ExVersionConstraint (ScopeQualified P.DefaultNamespace (P.QualAlias "P" "G0") "A") (V.thisVersion (V.mkVersion [2]))] $ mkTest priv_db11 "private-dependencies-12" ["P"] (solverFailure ("constraint from unknown source requires ==2" `isInfixOf`)) -- Testing that `any` qualifier applies to private deps From 894c6c30e62d1120e331dc9aba281a616b0a308e Mon Sep 17 00:00:00 2001 From: Rodrigo Mesquita Date: Fri, 26 Apr 2024 18:47:29 +0100 Subject: [PATCH 11/12] priv deps: Test long bad closure This test makes a long chain of packages violate the private closure property. In particular, it ensures all of the packages that are missing from the private scope are listed in the error message. --- .../closure-property-long-chain/cabal.project | 1 + .../closure-property-long-chain/cabal.test.hs | 8 ++++++++ .../closure-property-long-chain/libA/libA.cabal | 12 ++++++++++++ .../closure-property-long-chain/libA/src/MyLib.hs | 4 ++++ .../closure-property-long-chain/libB/libB.cabal | 11 +++++++++++ .../closure-property-long-chain/libB/src/MyLib.hs | 4 ++++ .../closure-property-long-chain/libC/libC.cabal | 11 +++++++++++ .../closure-property-long-chain/libC/src/MyLib.hs | 4 ++++ .../closure-property-long-chain/libD/libD.cabal | 11 +++++++++++ .../closure-property-long-chain/libD/src/MyLib.hs | 4 ++++ .../closure-property-long-chain/libE/libE.cabal | 11 +++++++++++ .../closure-property-long-chain/libE/src/MyLib.hs | 4 ++++ .../closure-property-long-chain/libH/libH.cabal | 11 +++++++++++ .../closure-property-long-chain/libH/src/MyLib.hs | 4 ++++ 14 files changed, 100 insertions(+) create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/cabal.project create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/cabal.test.hs create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/libA/libA.cabal create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/libA/src/MyLib.hs create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/libB/libB.cabal create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/libB/src/MyLib.hs create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/libC/libC.cabal create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/libC/src/MyLib.hs create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/libD/libD.cabal create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/libD/src/MyLib.hs create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/libE/libE.cabal create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/libE/src/MyLib.hs create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/libH/libH.cabal create mode 100644 cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/libH/src/MyLib.hs diff --git a/cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/cabal.project b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/cabal.project new file mode 100644 index 00000000000..fb834e2c61d --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/cabal.project @@ -0,0 +1 @@ +packages: libA, libB, libC, libD, libE, libH diff --git a/cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/cabal.test.hs b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/cabal.test.hs new file mode 100644 index 00000000000..10020c453df --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/cabal.test.hs @@ -0,0 +1,8 @@ +import Test.Cabal.Prelude + +main = do + cabalTest $ recordMode DoNotRecord $ do + + -- Will violate closure property + fails (cabal' "v2-build" ["libA"]) + >>= assertOutputContains "a private scope must contain its closure, but packages libC, libD, libE are not included in the private scope libA:P0" diff --git a/cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/libA/libA.cabal b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/libA/libA.cabal new file mode 100644 index 00000000000..e628757e45c --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/libA/libA.cabal @@ -0,0 +1,12 @@ +cabal-version: 3.0 +name: libA +version: 0.1.0.0 +license: NONE +build-type: Simple + +library + exposed-modules: MyLib + build-depends: base + private-build-depends: P0 with (libB, libH) + hs-source-dirs: src + default-language: Haskell2010 diff --git a/cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/libA/src/MyLib.hs b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/libA/src/MyLib.hs new file mode 100644 index 00000000000..e657c4403f6 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/libA/src/MyLib.hs @@ -0,0 +1,4 @@ +module MyLib (someFunc) where + +someFunc :: IO () +someFunc = putStrLn "someFunc" diff --git a/cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/libB/libB.cabal b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/libB/libB.cabal new file mode 100644 index 00000000000..7d2d6377c14 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/libB/libB.cabal @@ -0,0 +1,11 @@ +cabal-version: 3.0 +name: libB +version: 0.1.0.0 +license: NONE +build-type: Simple + +library + exposed-modules: MyLib + build-depends: base, libC + hs-source-dirs: src + default-language: Haskell2010 diff --git a/cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/libB/src/MyLib.hs b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/libB/src/MyLib.hs new file mode 100644 index 00000000000..e657c4403f6 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/libB/src/MyLib.hs @@ -0,0 +1,4 @@ +module MyLib (someFunc) where + +someFunc :: IO () +someFunc = putStrLn "someFunc" diff --git a/cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/libC/libC.cabal b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/libC/libC.cabal new file mode 100644 index 00000000000..af91892fbff --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/libC/libC.cabal @@ -0,0 +1,11 @@ +cabal-version: 3.0 +name: libC +version: 0.1.0.0 +license: NONE +build-type: Simple + +library + exposed-modules: MyLib + build-depends: base, libD + hs-source-dirs: src + default-language: Haskell2010 diff --git a/cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/libC/src/MyLib.hs b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/libC/src/MyLib.hs new file mode 100644 index 00000000000..e657c4403f6 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/libC/src/MyLib.hs @@ -0,0 +1,4 @@ +module MyLib (someFunc) where + +someFunc :: IO () +someFunc = putStrLn "someFunc" diff --git a/cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/libD/libD.cabal b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/libD/libD.cabal new file mode 100644 index 00000000000..00db1977e99 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/libD/libD.cabal @@ -0,0 +1,11 @@ +cabal-version: 3.0 +name: libD +version: 0.1.0.0 +license: NONE +build-type: Simple + +library + exposed-modules: MyLib + build-depends: base, libE + hs-source-dirs: src + default-language: Haskell2010 diff --git a/cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/libD/src/MyLib.hs b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/libD/src/MyLib.hs new file mode 100644 index 00000000000..e657c4403f6 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/libD/src/MyLib.hs @@ -0,0 +1,4 @@ +module MyLib (someFunc) where + +someFunc :: IO () +someFunc = putStrLn "someFunc" diff --git a/cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/libE/libE.cabal b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/libE/libE.cabal new file mode 100644 index 00000000000..d1409af1997 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/libE/libE.cabal @@ -0,0 +1,11 @@ +cabal-version: 3.0 +name: libE +version: 0.1.0.0 +license: NONE +build-type: Simple + +library + exposed-modules: MyLib + build-depends: base, libH + hs-source-dirs: src + default-language: Haskell2010 diff --git a/cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/libE/src/MyLib.hs b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/libE/src/MyLib.hs new file mode 100644 index 00000000000..e657c4403f6 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/libE/src/MyLib.hs @@ -0,0 +1,4 @@ +module MyLib (someFunc) where + +someFunc :: IO () +someFunc = putStrLn "someFunc" diff --git a/cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/libH/libH.cabal b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/libH/libH.cabal new file mode 100644 index 00000000000..6f4daa3351f --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/libH/libH.cabal @@ -0,0 +1,11 @@ +cabal-version: 3.0 +name: libH +version: 0.1.0.0 +license: NONE +build-type: Simple + +library + exposed-modules: MyLib + build-depends: base + hs-source-dirs: src + default-language: Haskell2010 diff --git a/cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/libH/src/MyLib.hs b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/libH/src/MyLib.hs new file mode 100644 index 00000000000..e657c4403f6 --- /dev/null +++ b/cabal-testsuite/PackageTests/PrivateDeps/closure-property-long-chain/libH/src/MyLib.hs @@ -0,0 +1,4 @@ +module MyLib (someFunc) where + +someFunc :: IO () +someFunc = putStrLn "someFunc" From b7ff4a777a4e615c28c5ded06dc5ee19f7fe0404 Mon Sep 17 00:00:00 2001 From: Rodrigo Mesquita Date: Mon, 29 Apr 2024 20:41:12 +0100 Subject: [PATCH 12/12] priv deps: Fix long bad closure message We would previously include terminal nodes if these were not private. --- .../src/Distribution/Solver/Modular/PrivateScopeClosure.hs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cabal-install-solver/src/Distribution/Solver/Modular/PrivateScopeClosure.hs b/cabal-install-solver/src/Distribution/Solver/Modular/PrivateScopeClosure.hs index 1f70972e6bf..513e9aa1d77 100644 --- a/cabal-install-solver/src/Distribution/Solver/Modular/PrivateScopeClosure.hs +++ b/cabal-install-solver/src/Distribution/Solver/Modular/PrivateScopeClosure.hs @@ -191,7 +191,9 @@ findBadPrivClosures pkg rdm = do | stopAtPkg && x == pkg = (M.insert x (dontLook x) s, path) | otherwise - = foldl go (M.insert x (dontLook x) s, x:path) $ neighbors x + = let nbs = neighbors x + in foldl go (M.insert x (dontLook x) s, if null nbs then path else x:path) nbs + -- \^ We don't add x to the path if this is a terminal node. dontLook x = error $ "We should only lookup privately-qualified pkgs, but instead " ++ show x ++ " was looked up -- it is only inserted in the map for de-duplication purposes."