Skip to content

Commit 00f5d2c

Browse files
authored
Merge pull request #3480 from grayjay/stanza-preferences
Fix bug in dependency solver stanza preferences
2 parents 93c196a + 463ebb9 commit 00f5d2c

File tree

5 files changed

+44
-35
lines changed

5 files changed

+44
-35
lines changed

cabal-install/Distribution/Solver/Modular/Builder.hs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,13 +145,14 @@ build = ana go
145145
--
146146
-- TODO: Should we include the flag default in the tree?
147147
go bs@(BS { next = OneGoal (OpenGoal (Flagged qfn@(FN (PI qpn _) _) (FInfo b m w) t f) gr) }) =
148-
FChoiceF qfn gr (w || trivial) m (P.fromList (reorder b
148+
FChoiceF qfn gr weak m (P.fromList (reorder b
149149
[(True, (extendOpen qpn (L.map (flip OpenGoal (FDependency qfn True )) t) bs) { next = Goals }),
150150
(False, (extendOpen qpn (L.map (flip OpenGoal (FDependency qfn False)) f) bs) { next = Goals })]))
151151
where
152152
reorder True = id
153153
reorder False = reverse
154154
trivial = L.null t && L.null f
155+
weak = WeakOrTrivial $ unWeakOrTrivial w || trivial
155156

156157
-- For a stanza, we also create only two subtrees. The order is initially
157158
-- False, True. This can be changed later by constraints (force enabling
@@ -163,7 +164,7 @@ build = ana go
163164
[(False, bs { next = Goals }),
164165
(True, (extendOpen qpn (L.map (flip OpenGoal (SDependency qsn)) t) bs) { next = Goals })])
165166
where
166-
trivial = L.null t
167+
trivial = WeakOrTrivial (L.null t)
167168

168169
-- For a particular instance, we change the state: we update the scope,
169170
-- and furthermore we update the set of goals.

cabal-install/Distribution/Solver/Modular/Flag.hs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ module Distribution.Solver.Modular.Flag
77
, QFN
88
, QSN
99
, SN(..)
10+
, WeakOrTrivial(..)
1011
, mkFlag
1112
, showFBool
1213
, showQFN
@@ -40,7 +41,7 @@ mkFlag fn = FlagName fn
4041
-- | Flag info. Default value, whether the flag is manual, and
4142
-- whether the flag is weak. Manual flags can only be set explicitly.
4243
-- Weak flags are typically deferred by the solver.
43-
data FInfo = FInfo { fdefault :: Bool, fmanual :: Bool, fweak :: Bool }
44+
data FInfo = FInfo { fdefault :: Bool, fmanual :: Bool, fweak :: WeakOrTrivial }
4445
deriving (Eq, Ord, Show)
4546

4647
-- | Flag defaults.
@@ -56,6 +57,20 @@ data SN qpn = SN (PI qpn) OptionalStanza
5657
-- | Qualified stanza name.
5758
type QSN = SN QPN
5859

60+
-- | A property of flag and stanza choices that determines whether the
61+
-- choice should be deferred in the solving process.
62+
--
63+
-- A choice is called weak if we do want to defer it. This is the
64+
-- case for flags that should be implied by what's currently installed on
65+
-- the system, as opposed to flags that are used to explicitly enable or
66+
-- disable some functionality.
67+
--
68+
-- A choice is called trivial if it clearly does not matter. The
69+
-- special case of triviality we actually consider is if there are no new
70+
-- dependencies introduced by the choice.
71+
newtype WeakOrTrivial = WeakOrTrivial { unWeakOrTrivial :: Bool }
72+
deriving (Eq, Ord, Show)
73+
5974
unStanza :: OptionalStanza -> String
6075
unStanza TestStanzas = "test"
6176
unStanza BenchStanzas = "bench"

cabal-install/Distribution/Solver/Modular/IndexConversion.hs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,9 @@ prefix f fds = [f (concat fds)]
193193
-- unless strong flags have been selected explicitly.
194194
flagInfo :: StrongFlags -> [PD.Flag] -> FlagInfo
195195
flagInfo (StrongFlags strfl) =
196-
M.fromList . L.map (\ (MkFlag fn _ b m) -> (fn, FInfo b m (not (strfl || m))))
196+
M.fromList . L.map (\ (MkFlag fn _ b m) -> (fn, FInfo b m (weak m)))
197+
where
198+
weak m = WeakOrTrivial $ not (strfl || m)
197199

198200
-- | Internal package names, which should not be interpreted as true
199201
-- dependencies.

cabal-install/Distribution/Solver/Modular/Preference.hs

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -117,15 +117,19 @@ preferLatestOrdering (I v1 _) (I v2 _) = compare v1 v2
117117
preferPackageStanzaPreferences :: (PN -> PackagePreferences) -> Tree a -> Tree a
118118
preferPackageStanzaPreferences pcs = trav go
119119
where
120-
go (SChoiceF qsn@(SN (PI (Q pp pn) _) s) gr _tr ts) | primaryPP pp =
121-
let PackagePreferences _ _ spref = pcs pn
122-
enableStanzaPref = s `elem` spref
123-
-- move True case first to try enabling the stanza
124-
ts' | enableStanzaPref = P.sortByKeys (flip compare) ts
125-
| otherwise = ts
126-
in SChoiceF qsn gr True ts' -- True: now weak choice
120+
go (SChoiceF qsn@(SN (PI (Q pp pn) _) s) gr _tr ts)
121+
| primaryPP pp && enableStanzaPref pn s =
122+
-- move True case first to try enabling the stanza
123+
let ts' = P.sortByKeys (flip compare) ts
124+
-- defer the choice by setting it to weak
125+
in SChoiceF qsn gr (WeakOrTrivial True) ts'
127126
go x = x
128127

128+
enableStanzaPref :: PN -> OptionalStanza -> Bool
129+
enableStanzaPref pn s =
130+
let PackagePreferences _ _ spref = pcs pn
131+
in s `elem` spref
132+
129133
-- | Helper function that tries to enforce a single package constraint on a
130134
-- given instance for a P-node. Translates the constraint into a
131135
-- tree-transformer that either leaves the subtree untouched, or replaces it
@@ -341,12 +345,12 @@ deferWeakFlagChoices = trav go
341345
go x = x
342346

343347
noWeakStanza :: Tree a -> Bool
344-
noWeakStanza (SChoice _ _ True _) = False
345-
noWeakStanza _ = True
348+
noWeakStanza (SChoice _ _ (WeakOrTrivial True) _) = False
349+
noWeakStanza _ = True
346350

347351
noWeakFlag :: Tree a -> Bool
348-
noWeakFlag (FChoice _ _ True _ _) = False
349-
noWeakFlag _ = True
352+
noWeakFlag (FChoice _ _ (WeakOrTrivial True) _ _) = False
353+
noWeakFlag _ = True
350354

351355
-- | Transformation that sorts choice nodes so that
352356
-- child nodes with a small branching degree are preferred.

cabal-install/Distribution/Solver/Modular/Tree.hs

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -36,24 +36,11 @@ data Tree a =
3636

3737
-- | Choose a value for a flag
3838
--
39-
-- The first Bool indicates whether it's weak/trivial,
40-
-- the second Bool whether it's manual.
41-
--
42-
-- A choice is called trivial if it clearly does not matter. The
43-
-- special case of triviality we actually consider is if there are no new
44-
-- dependencies introduced by this node.
45-
--
46-
-- A (flag) choice is called weak if we do want to defer it. This is the
47-
-- case for flags that should be implied by what's currently installed on
48-
-- the system, as opposed to flags that are used to explicitly enable or
49-
-- disable some functionality.
50-
| FChoice QFN a Bool Bool (PSQ Bool (Tree a))
39+
-- The Bool indicates whether it's manual.
40+
| FChoice QFN a WeakOrTrivial Bool (PSQ Bool (Tree a))
5141

5242
-- | Choose whether or not to enable a stanza
53-
--
54-
-- The Bool indicates whether it's trivial (see 'FChoice' for a discussion
55-
-- of triviality).
56-
| SChoice QSN a Bool (PSQ Bool (Tree a))
43+
| SChoice QSN a WeakOrTrivial (PSQ Bool (Tree a))
5744

5845
-- | Choose which choice to make next
5946
--
@@ -116,10 +103,10 @@ data FailReason = InconsistentInitialConstraints
116103

117104
-- | Functor for the tree type.
118105
data TreeF a b =
119-
PChoiceF QPN a (PSQ POption b)
120-
| FChoiceF QFN a Bool Bool (PSQ Bool b)
121-
| SChoiceF QSN a Bool (PSQ Bool b)
122-
| GoalChoiceF (PSQ (Goal QPN) b)
106+
PChoiceF QPN a (PSQ POption b)
107+
| FChoiceF QFN a WeakOrTrivial Bool (PSQ Bool b)
108+
| SChoiceF QSN a WeakOrTrivial (PSQ Bool b)
109+
| GoalChoiceF (PSQ (Goal QPN) b)
123110
| DoneF RevDepMap
124111
| FailF (ConflictSet QPN) FailReason
125112
deriving (Functor, Foldable, Traversable)

0 commit comments

Comments
 (0)