@@ -3,9 +3,10 @@ module Distribution.Solver.Modular.Log
3
3
, logToProgress
4
4
) where
5
5
6
- import Control.Applicative
6
+ import Prelude ()
7
+ import Distribution.Client.Compat.Prelude
8
+
7
9
import Data.List as L
8
- import Data.Maybe (isNothing )
9
10
10
11
import Distribution.Solver.Types.PackagePath
11
12
import Distribution.Solver.Types.Progress
@@ -20,69 +21,68 @@ import qualified Distribution.Solver.Modular.ConflictSet as CS
20
21
-- Represents the progress of a computation lazily.
21
22
--
22
23
-- Parameterized over the type of actual messages and the final result.
23
- type Log m a = Progress m () a
24
+ type Log m a = Progress m (ConflictSet QPN , ConflictMap ) a
24
25
25
26
messages :: Progress step fail done -> [step ]
26
27
messages = foldProgress (:) (const [] ) (const [] )
27
28
29
+ data Exhaustiveness = Exhaustive | BackjumpLimitReached
30
+
28
31
-- | Postprocesses a log file. Takes as an argument a limit on allowed backjumps.
29
32
-- If the limit is 'Nothing', then infinitely many backjumps are allowed. If the
30
33
-- limit is 'Just 0', backtracking is completely disabled.
31
34
logToProgress :: Maybe Int -> Log Message a -> Progress String String a
32
35
logToProgress mbj l = let
33
36
es = proc (Just 0 ) l -- catch first error (always)
34
- ms = useFirstError ( proc mbj l)
37
+ ms = proc mbj l
35
38
in go es es -- trace for first error
36
39
(showMessages (const True ) True ms) -- run with backjump limit applied
37
40
where
38
41
-- Proc takes the allowed number of backjumps and a 'Progress' and explores the
39
42
-- messages until the maximum number of backjumps has been reached. It filters out
40
43
-- and ignores repeated backjumps. If proc reaches the backjump limit, it truncates
41
44
-- the 'Progress' and ends it with the last conflict set. Otherwise, it leaves the
42
- -- original success result or replaces the original failure with 'Nothing' .
43
- proc :: Maybe Int -> Progress Message a b -> Progress Message (Maybe ( ConflictSet QPN ) ) b
45
+ -- original result.
46
+ proc :: Maybe Int -> Log Message b -> Progress Message (Exhaustiveness , ConflictSet QPN , ConflictMap ) b
44
47
proc _ (Done x) = Done x
45
- proc _ (Fail _) = Fail Nothing
48
+ proc _ (Fail (cs, cm)) = Fail ( Exhaustive , cs, cm)
46
49
proc mbj' (Step x@ (Failure cs Backjump ) xs@ (Step Leave (Step (Failure cs' Backjump ) _)))
47
50
| cs == cs' = Step x (proc mbj' xs) -- repeated backjumps count as one
48
- proc (Just 0 ) (Step (Failure cs Backjump ) _) = Fail (Just cs)
51
+ proc (Just 0 ) (Step (Failure cs Backjump ) _) = Fail (BackjumpLimitReached , cs, mempty ) -- No final conflict map available
49
52
proc (Just n) (Step x@ (Failure _ Backjump ) xs) = Step x (proc (Just (n - 1 )) xs)
50
53
proc mbj' (Step x xs) = Step x (proc mbj' xs)
51
54
52
- -- Sets the conflict set from the first backjump as the final error, and records
53
- -- whether the search was exhaustive.
54
- useFirstError :: Progress Message (Maybe (ConflictSet QPN )) b
55
- -> Progress Message (Bool , Maybe (ConflictSet QPN )) b
56
- useFirstError = replace Nothing
57
- where
58
- replace _ (Done x) = Done x
59
- replace cs' (Fail cs) = -- 'Nothing' means backjump limit not reached.
60
- -- Prefer first error over later error.
61
- Fail (isNothing cs, cs' <|> cs)
62
- replace Nothing (Step x@ (Failure cs Backjump ) xs) = Step x $ replace (Just cs) xs
63
- replace cs' (Step x xs) = Step x $ replace cs' xs
64
-
65
55
-- The first two arguments are both supposed to be the log up to the first error.
66
56
-- That's the error that will always be printed in case we do not find a solution.
67
57
-- We pass this log twice, because we evaluate it in parallel with the full log,
68
58
-- but we also want to retain the reference to its beginning for when we print it.
69
59
-- This trick prevents a space leak!
70
60
--
71
61
-- The third argument is the full log, ending with either the solution or the
72
- -- exhaustiveness and first conflict set.
73
- go :: Progress Message a b
74
- -> Progress Message a b
75
- -> Progress String (Bool , Maybe ( ConflictSet QPN ) ) b
62
+ -- exhaustiveness and final conflict set.
63
+ go :: Progress Message ( Exhaustiveness , ConflictSet QPN , ConflictMap ) b
64
+ -> Progress Message ( Exhaustiveness , ConflictSet QPN , ConflictMap ) b
65
+ -> Progress String (Exhaustiveness , ConflictSet QPN , ConflictMap ) b
76
66
-> Progress String String b
77
- go ms (Step _ ns) (Step x xs) = Step x (go ms ns xs)
78
- go ms r (Step x xs) = Step x (go ms r xs)
79
- go ms _ (Fail (exh, Just cs)) = Fail $
80
- " Could not resolve dependencies:\n " ++
81
- unlines (messages $ showMessages (L. foldr (\ v _ -> v `CS.member` cs) True ) False ms) ++
82
- (if exh then " Dependency tree exhaustively searched.\n "
83
- else " Backjump limit reached (" ++ currlimit mbj ++
84
- " change with --max-backjumps or try to run with --reorder-goals).\n " )
85
- where currlimit (Just n) = " currently " ++ show n ++ " , "
86
- currlimit Nothing = " "
87
- go _ _ (Done s) = Done s
88
- go _ _ (Fail (_, Nothing )) = Fail (" Could not resolve dependencies; something strange happened." ) -- should not happen
67
+ go ms (Step _ ns) (Step x xs) = Step x (go ms ns xs)
68
+ go ms r (Step x xs) = Step x (go ms r xs)
69
+ go ms (Step _ ns) r = go ms ns r
70
+ go ms (Fail (_, cs', _)) (Fail (exh, cs, cm)) = Fail $
71
+ " Could not resolve dependencies:\n " ++
72
+ unlines (messages $ showMessages (L. foldr (\ v _ -> v `CS.member` cs') True ) False ms) ++
73
+ case exh of
74
+ Exhaustive ->
75
+ " After searching the rest of the dependency tree exhaustively, "
76
+ ++ " these were the goals I've had most trouble fulfilling: "
77
+ ++ CS. showCSWithFrequency cm cs
78
+ BackjumpLimitReached ->
79
+ " Backjump limit reached (" ++ currlimit mbj ++
80
+ " change with --max-backjumps or try to run with --reorder-goals).\n "
81
+ where currlimit (Just n) = " currently " ++ show n ++ " , "
82
+ currlimit Nothing = " "
83
+ go _ _ (Done s) = Done s
84
+ go _ (Done _) (Fail _) = Fail $
85
+ -- Should not happen: Second argument is the log up to first error,
86
+ -- third one is the entire log. Therefore it should never happen that
87
+ -- the second log finishes with 'Done' and the third log with 'Fail'.
88
+ " Could not resolve dependencies; something strange happened."
0 commit comments