Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RFC/Solver split (v2) #3222

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cabal-install/Distribution/Client/BuildReports/Storage.hs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import Distribution.Client.BuildReports.Anonymous (BuildReport)

import Distribution.Client.Types
import qualified Distribution.Client.InstallPlan as InstallPlan
import qualified Distribution.Client.ComponentDeps as CD
import qualified Distribution.Solver.ComponentDeps as CD
import Distribution.Client.InstallPlan
( InstallPlan )

Expand Down
6 changes: 3 additions & 3 deletions cabal-install/Distribution/Client/Configure.hs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ import qualified Distribution.Client.InstallPlan as InstallPlan
import Distribution.Client.InstallPlan (InstallPlan)
import Distribution.Client.IndexUtils as IndexUtils
( getSourcePackages, getInstalledPackages )
import Distribution.Client.PackageIndex ( PackageIndex, elemByPackageName )
import Distribution.Client.PkgConfigDb (PkgConfigDb, readPkgConfigDb)
import Distribution.Solver.PackageIndex ( PackageIndex, elemByPackageName )
import Distribution.Solver.PkgConfigDb (PkgConfigDb, readPkgConfigDb)
import Distribution.Client.Setup
( ConfigExFlags(..), configureCommand, filterConfigureFlags
, RepoContext(..) )
Expand All @@ -36,7 +36,7 @@ import Distribution.Client.SetupWrapper
( setupWrapper, SetupScriptOptions(..), defaultSetupScriptOptions )
import Distribution.Client.Targets
( userToPackageConstraint, userConstraintPackageName )
import qualified Distribution.Client.ComponentDeps as CD
import qualified Distribution.Solver.ComponentDeps as CD
import Distribution.Package (PackageId)
import Distribution.Client.JobControl (Lock)

Expand Down
12 changes: 6 additions & 6 deletions cabal-install/Distribution/Client/Dependency.hs
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,14 @@ module Distribution.Client.Dependency (

import Distribution.Client.Dependency.TopDown
( topDownResolver )
import Distribution.Client.Dependency.Modular
import Distribution.Solver.Modular
( modularResolver, SolverConfig(..) )
import qualified Distribution.Client.PackageIndex as PackageIndex
import qualified Distribution.Solver.PackageIndex as PackageIndex
import Distribution.Simple.PackageIndex (InstalledPackageIndex)
import qualified Distribution.Simple.PackageIndex as InstalledPackageIndex
import qualified Distribution.Client.InstallPlan as InstallPlan
import Distribution.Client.InstallPlan (InstallPlan)
import Distribution.Client.PkgConfigDb (PkgConfigDb)
import Distribution.Solver.PkgConfigDb (PkgConfigDb)
import Distribution.Client.Types
( SourcePackageDb(SourcePackageDb), SourcePackage(..)
, ConfiguredPackage(..), ConfiguredId(..)
Expand All @@ -86,8 +86,8 @@ import Distribution.Client.Dependency.Types
import Distribution.Client.Sandbox.Types
( SandboxPackageInfo(..) )
import Distribution.Client.Targets
import Distribution.Client.ComponentDeps (ComponentDeps)
import qualified Distribution.Client.ComponentDeps as CD
import Distribution.Solver.ComponentDeps (ComponentDeps)
import qualified Distribution.Solver.ComponentDeps as CD
import qualified Distribution.InstalledPackageInfo as Installed
import Distribution.Package
( PackageName(..), PackageIdentifier(PackageIdentifier), PackageId
Expand All @@ -99,7 +99,7 @@ import qualified Distribution.PackageDescription as PD
, Flag(flagName), FlagName(..) )
import Distribution.PackageDescription.Configuration
( finalizePackageDescription )
import Distribution.Client.PackageUtils
import Distribution.Solver.PackageUtils
( externalBuildDepends )
import Distribution.Version
( VersionRange, anyVersion, thisVersion, withinRange
Expand Down
10 changes: 5 additions & 5 deletions cabal-install/Distribution/Client/Dependency/TopDown.hs
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,14 @@ import Distribution.Client.Dependency.Types
, PackagePreferences(..), InstalledPreference(..)
, Progress(..), foldProgress )

import qualified Distribution.Client.PackageIndex as PackageIndex
import qualified Distribution.Solver.PackageIndex as PackageIndex
import qualified Distribution.Simple.PackageIndex as InstalledPackageIndex
import Distribution.Simple.PackageIndex (InstalledPackageIndex)
import qualified Distribution.InstalledPackageInfo as InstalledPackageInfo
import Distribution.Client.ComponentDeps
import Distribution.Solver.ComponentDeps
( ComponentDeps )
import qualified Distribution.Client.ComponentDeps as CD
import Distribution.Client.PackageIndex
import qualified Distribution.Solver.ComponentDeps as CD
import Distribution.Solver.PackageIndex
( PackageIndex )
import Distribution.Package
( PackageName(..), PackageId, PackageIdentifier(..)
Expand All @@ -45,7 +45,7 @@ import Distribution.Package
, Dependency(Dependency), thisPackageVersion, simplifyDependency )
import Distribution.PackageDescription
( PackageDescription(buildDepends) )
import Distribution.Client.PackageUtils
import Distribution.Solver.PackageUtils
( externalBuildDepends )
import Distribution.PackageDescription.Configuration
( finalizePackageDescription, flattenPackageDescription )
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ module Distribution.Client.Dependency.TopDown.Constraints (
) where

import Distribution.Client.Dependency.TopDown.Types
import qualified Distribution.Client.PackageIndex as PackageIndex
import Distribution.Client.PackageIndex
import qualified Distribution.Solver.PackageIndex as PackageIndex
import Distribution.Solver.PackageIndex
( PackageIndex )
import Distribution.Package
( PackageName, PackageId, PackageIdentifier(..)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import Distribution.Client.Types
, OptionalStanza, ConfiguredId(..) )
import Distribution.InstalledPackageInfo
( InstalledPackageInfo )
import qualified Distribution.Client.ComponentDeps as CD
import qualified Distribution.Solver.ComponentDeps as CD

import Distribution.Package
( PackageId, PackageIdentifier, Dependency
Expand Down
217 changes: 2 additions & 215 deletions cabal-install/Distribution/Client/Dependency/Types.hs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
{-# LANGUAGE CPP #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE DeriveGeneric #-}
-----------------------------------------------------------------------------
Expand Down Expand Up @@ -35,44 +34,14 @@ module Distribution.Client.Dependency.Types (

) where

#if !MIN_VERSION_base(4,8,0)
import Control.Applicative
( Applicative(..) )
#endif
import Control.Applicative
( Alternative(..) )

import Data.Char
( isAlpha, toLower )
#if !MIN_VERSION_base(4,8,0)
import Data.Monoid
( Monoid(..) )
#endif

import Distribution.Client.PkgConfigDb
( PkgConfigDb )
import Distribution.Client.Types
( OptionalStanza(..), SourcePackage(..), ConfiguredPackage )

import Distribution.Solver.Types
import qualified Distribution.Compat.ReadP as Parse
( pfail, munch1 )
import Distribution.PackageDescription
( FlagAssignment, FlagName(..) )
import Distribution.InstalledPackageInfo
( InstalledPackageInfo )
import qualified Distribution.Client.PackageIndex as PackageIndex
( PackageIndex )
import Distribution.Simple.PackageIndex ( InstalledPackageIndex )
import Distribution.Package
( PackageName )
import Distribution.Version
( VersionRange, simplifyVersionRange )
import Distribution.Compiler
( CompilerInfo )
import Distribution.System
( Platform )
import Distribution.Text
( Text(..), display )
( Text(..) )

import Text.PrettyPrint
( text )
Expand Down Expand Up @@ -105,89 +74,6 @@ instance Text PreSolver where
"choose" -> return Choose
_ -> Parse.pfail

-- | A dependency resolver is a function that works out an installation plan
-- given the set of installed and available packages and a set of deps to
-- solve for.
--
-- The reason for this interface is because there are dozens of approaches to
-- solving the package dependency problem and we want to make it easy to swap
-- in alternatives.
--
type DependencyResolver loc = Platform
-> CompilerInfo
-> InstalledPackageIndex
-> PackageIndex.PackageIndex (SourcePackage loc)
-> PkgConfigDb
-> (PackageName -> PackagePreferences)
-> [LabeledPackageConstraint]
-> [PackageName]
-> Progress String String [ResolverPackage loc]

-- | The dependency resolver picks either pre-existing installed packages
-- or it picks source packages along with package configuration.
--
-- This is like the 'InstallPlan.PlanPackage' but with fewer cases.
--
data ResolverPackage loc = PreExisting InstalledPackageInfo
| Configured (ConfiguredPackage loc)

-- | Per-package constraints. Package constraints must be respected by the
-- solver. Multiple constraints for each package can be given, though obviously
-- it is possible to construct conflicting constraints (eg impossible version
-- range or inconsistent flag assignment).
--
data PackageConstraint
= PackageConstraintVersion PackageName VersionRange
| PackageConstraintInstalled PackageName
| PackageConstraintSource PackageName
| PackageConstraintFlags PackageName FlagAssignment
| PackageConstraintStanzas PackageName [OptionalStanza]
deriving (Eq,Show,Generic)

instance Binary PackageConstraint

-- | Provide a textual representation of a package constraint
-- for debugging purposes.
--
showPackageConstraint :: PackageConstraint -> String
showPackageConstraint (PackageConstraintVersion pn vr) =
display pn ++ " " ++ display (simplifyVersionRange vr)
showPackageConstraint (PackageConstraintInstalled pn) =
display pn ++ " installed"
showPackageConstraint (PackageConstraintSource pn) =
display pn ++ " source"
showPackageConstraint (PackageConstraintFlags pn fs) =
"flags " ++ display pn ++ " " ++ unwords (map (uncurry showFlag) fs)
where
showFlag (FlagName f) True = "+" ++ f
showFlag (FlagName f) False = "-" ++ f
showPackageConstraint (PackageConstraintStanzas pn ss) =
"stanzas " ++ display pn ++ " " ++ unwords (map showStanza ss)
where
showStanza TestStanzas = "test"
showStanza BenchStanzas = "bench"

-- | Per-package preferences on the version. It is a soft constraint that the
-- 'DependencyResolver' should try to respect where possible. It consists of
-- an 'InstalledPreference' which says if we prefer versions of packages
-- that are already installed. It also has (possibly multiple)
-- 'PackageVersionPreference's which are suggested constraints on the version
-- number. The resolver should try to use package versions that satisfy
-- the maximum number of the suggested version constraints.
--
-- It is not specified if preferences on some packages are more important than
-- others.
--
data PackagePreferences = PackagePreferences [VersionRange]
InstalledPreference
[OptionalStanza]

-- | Whether we prefer an installed version of a package or simply the latest
-- version.
--
data InstalledPreference = PreferInstalled | PreferLatest
deriving Show

-- | Global policy for all packages to say if we prefer package versions that
-- are already installed locally or if we just prefer the latest available.
--
Expand All @@ -212,102 +98,3 @@ data PackagesPreferenceDefault =
--
| PreferLatestForSelected
deriving Show

-- | A type to represent the unfolding of an expensive long running
-- calculation that may fail. We may get intermediate steps before the final
-- result which may be used to indicate progress and\/or logging messages.
--
data Progress step fail done = Step step (Progress step fail done)
| Fail fail
| Done done
deriving Functor

-- | Consume a 'Progress' calculation. Much like 'foldr' for lists but with two
-- base cases, one for a final result and one for failure.
--
-- Eg to convert into a simple 'Either' result use:
--
-- > foldProgress (flip const) Left Right
--
foldProgress :: (step -> a -> a) -> (fail -> a) -> (done -> a)
-> Progress step fail done -> a
foldProgress step fail done = fold
where fold (Step s p) = step s (fold p)
fold (Fail f) = fail f
fold (Done r) = done r

instance Monad (Progress step fail) where
return = pure
p >>= f = foldProgress Step Fail f p

instance Applicative (Progress step fail) where
pure a = Done a
p <*> x = foldProgress Step Fail (flip fmap x) p

instance Monoid fail => Alternative (Progress step fail) where
empty = Fail mempty
p <|> q = foldProgress Step (const q) Done p

-- | 'PackageConstraint' labeled with its source.
data LabeledPackageConstraint
= LabeledPackageConstraint PackageConstraint ConstraintSource

unlabelPackageConstraint :: LabeledPackageConstraint -> PackageConstraint
unlabelPackageConstraint (LabeledPackageConstraint pc _) = pc

-- | Source of a 'PackageConstraint'.
data ConstraintSource =

-- | Main config file, which is ~/.cabal/config by default.
ConstraintSourceMainConfig FilePath

-- | Sandbox config file, which is ./cabal.sandbox.config by default.
| ConstraintSourceSandboxConfig FilePath

-- | User config file, which is ./cabal.config by default.
| ConstraintSourceUserConfig FilePath

-- | Flag specified on the command line.
| ConstraintSourceCommandlineFlag

-- | Target specified by the user, e.g., @cabal install package-0.1.0.0@
-- implies @package==0.1.0.0@.
| ConstraintSourceUserTarget

-- | Internal requirement to use installed versions of packages like ghc-prim.
| ConstraintSourceNonUpgradeablePackage

-- | Internal requirement to use the add-source version of a package when that
-- version is installed and the source is modified.
| ConstraintSourceModifiedAddSourceDep

-- | Internal constraint used by @cabal freeze@.
| ConstraintSourceFreeze

-- | Constraint specified by a config file, a command line flag, or a user
-- target, when a more specific source is not known.
| ConstraintSourceConfigFlagOrTarget

-- | The source of the constraint is not specified.
| ConstraintSourceUnknown
deriving (Eq, Show, Generic)

instance Binary ConstraintSource

-- | Description of a 'ConstraintSource'.
showConstraintSource :: ConstraintSource -> String
showConstraintSource (ConstraintSourceMainConfig path) =
"main config " ++ path
showConstraintSource (ConstraintSourceSandboxConfig path) =
"sandbox config " ++ path
showConstraintSource (ConstraintSourceUserConfig path)= "user config " ++ path
showConstraintSource ConstraintSourceCommandlineFlag = "command line flag"
showConstraintSource ConstraintSourceUserTarget = "user target"
showConstraintSource ConstraintSourceNonUpgradeablePackage =
"non-upgradeable package"
showConstraintSource ConstraintSourceModifiedAddSourceDep =
"modified add-source dependency"
showConstraintSource ConstraintSourceFreeze = "cabal freeze"
showConstraintSource ConstraintSourceConfigFlagOrTarget =
"config file, command line flag, or user target"
showConstraintSource ConstraintSourceUnknown = "unknown source"
2 changes: 1 addition & 1 deletion cabal-install/Distribution/Client/Fetch.hs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import Distribution.Client.Dependency
import Distribution.Client.IndexUtils as IndexUtils
( getSourcePackages, getInstalledPackages )
import qualified Distribution.Client.InstallPlan as InstallPlan
import Distribution.Client.PkgConfigDb
import Distribution.Solver.PkgConfigDb
( PkgConfigDb, readPkgConfigDb )
import Distribution.Client.Setup
( GlobalFlags(..), FetchFlags(..), RepoContext(..) )
Expand Down
2 changes: 1 addition & 1 deletion cabal-install/Distribution/Client/Freeze.hs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import Distribution.Client.IndexUtils as IndexUtils
import Distribution.Client.InstallPlan
( InstallPlan, PlanPackage )
import qualified Distribution.Client.InstallPlan as InstallPlan
import Distribution.Client.PkgConfigDb
import Distribution.Solver.PkgConfigDb
( PkgConfigDb, readPkgConfigDb )
import Distribution.Client.Setup
( GlobalFlags(..), FreezeFlags(..), ConfigExFlags(..)
Expand Down
4 changes: 2 additions & 2 deletions cabal-install/Distribution/Client/IndexUtils.hs
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ import Distribution.Package
( PackageId, PackageIdentifier(..), PackageName(..)
, Package(..), packageVersion, packageName
, Dependency(Dependency) )
import Distribution.Client.PackageIndex (PackageIndex)
import qualified Distribution.Client.PackageIndex as PackageIndex
import Distribution.Solver.PackageIndex (PackageIndex)
import qualified Distribution.Solver.PackageIndex as PackageIndex
import Distribution.Simple.PackageIndex (InstalledPackageIndex)
import qualified Distribution.PackageDescription.Parse as PackageDesc.Parse
import Distribution.PackageDescription
Expand Down
2 changes: 1 addition & 1 deletion cabal-install/Distribution/Client/Init.hs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ import Distribution.Simple.PackageIndex
import Distribution.Text
( display, Text(..) )

import Distribution.Client.PackageIndex
import Distribution.Solver.PackageIndex
( elemByPackageName )
import Distribution.Client.IndexUtils
( getSourcePackages )
Expand Down
Loading