Skip to content

Commit 36fdc17

Browse files
committed
define rules without diagnostics
1 parent 2a99031 commit 36fdc17

File tree

5 files changed

+93
-51
lines changed

5 files changed

+93
-51
lines changed

ghcide/src/Development/IDE/Core/FileExists.hs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ fileExistsRules lspEnv vfs = do
200200
-- Requires an lsp client that provides WatchedFiles notifications, but assumes that this has already been checked.
201201
fileExistsRulesFast :: (NormalizedFilePath -> Action Bool) -> VFSHandle -> Rules ()
202202
fileExistsRulesFast isWatched vfs =
203-
defineEarlyCutoff $ \GetFileExists file -> do
203+
defineEarlyCutoff $ RuleNoDiagnostics $ \GetFileExists file -> do
204204
isWF <- isWatched file
205205
if isWF
206206
then fileExistsFast vfs file
@@ -222,7 +222,7 @@ For the VFS lookup, however, we won't get prompted to flush the result, so inste
222222
we use 'alwaysRerun'.
223223
-}
224224

225-
fileExistsFast :: VFSHandle -> NormalizedFilePath -> Action (Maybe BS.ByteString, ([a], Maybe Bool))
225+
fileExistsFast :: VFSHandle -> NormalizedFilePath -> Action (Maybe BS.ByteString, Maybe Bool)
226226
fileExistsFast vfs file = do
227227
-- Could in principle use 'alwaysRerun' here, but it's too slwo, See Note [Invalidating file existence results]
228228
mp <- getFileExistsMapUntracked
@@ -233,21 +233,21 @@ fileExistsFast vfs file = do
233233
-- We don't know about it: use the slow route.
234234
-- Note that we do *not* call 'fileExistsSlow', as that would trigger 'alwaysRerun'.
235235
Nothing -> liftIO $ getFileExistsVFS vfs file
236-
pure (summarizeExists exist, ([], Just exist))
236+
pure (summarizeExists exist, Just exist)
237237

238238
summarizeExists :: Bool -> Maybe BS.ByteString
239239
summarizeExists x = Just $ if x then BS.singleton 1 else BS.empty
240240

241241
fileExistsRulesSlow :: VFSHandle -> Rules ()
242242
fileExistsRulesSlow vfs =
243-
defineEarlyCutoff $ \GetFileExists file -> fileExistsSlow vfs file
243+
defineEarlyCutoff $ RuleNoDiagnostics $ \GetFileExists file -> fileExistsSlow vfs file
244244

245-
fileExistsSlow :: VFSHandle -> NormalizedFilePath -> Action (Maybe BS.ByteString, ([a], Maybe Bool))
245+
fileExistsSlow :: VFSHandle -> NormalizedFilePath -> Action (Maybe BS.ByteString, Maybe Bool)
246246
fileExistsSlow vfs file = do
247247
-- See Note [Invalidating file existence results]
248248
alwaysRerun
249249
exist <- liftIO $ getFileExistsVFS vfs file
250-
pure (summarizeExists exist, ([], Just exist))
250+
pure (summarizeExists exist, Just exist)
251251

252252
getFileExistsVFS :: VFSHandle -> NormalizedFilePath -> IO Bool
253253
getFileExistsVFS vfs file = do

ghcide/src/Development/IDE/Core/FileStore.hs

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,12 @@ module Development.IDE.Core.FileStore(
1414
VFSHandle,
1515
makeVFSHandle,
1616
makeLSPVFSHandle,
17-
isFileOfInterestRule
18-
,resetFileStore) where
17+
isFileOfInterestRule,
18+
resetFileStore,
19+
getModificationTimeImpl,
20+
addIdeGlobal,
21+
getFileContentsRule,
22+
) where
1923

2024
import Control.Concurrent.Extra
2125
import Control.Concurrent.STM (atomically)
@@ -31,7 +35,8 @@ import Data.Maybe
3135
import qualified Data.Rope.UTF16 as Rope
3236
import qualified Data.Text as T
3337
import Data.Time
34-
import Development.IDE.Core.OfInterest (getFilesOfInterest, OfInterestVar(..))
38+
import Development.IDE.Core.OfInterest (OfInterestVar (..),
39+
getFilesOfInterest)
3540
import Development.IDE.Core.RuleTypes
3641
import Development.IDE.Core.Shake
3742
import Development.IDE.GHC.Orphans ()
@@ -65,7 +70,8 @@ import Language.LSP.Server hiding
6570
import qualified Language.LSP.Server as LSP
6671
import Language.LSP.Types (FileChangeType (FcChanged),
6772
FileEvent (FileEvent),
68-
uriToFilePath, toNormalizedFilePath)
73+
toNormalizedFilePath,
74+
uriToFilePath)
6975
import Language.LSP.VFS
7076

7177
makeVFSHandle :: IO VFSHandle
@@ -91,14 +97,22 @@ makeLSPVFSHandle lspEnv = VFSHandle
9197

9298

9399
isFileOfInterestRule :: Rules ()
94-
isFileOfInterestRule = defineEarlyCutoff $ \IsFileOfInterest f -> do
100+
isFileOfInterestRule = defineEarlyCutoff $ RuleNoDiagnostics $ \IsFileOfInterest f -> do
95101
filesOfInterest <- getFilesOfInterest
96102
let res = maybe NotFOI IsFOI $ f `HM.lookup` filesOfInterest
97-
return (Just $ BS.pack $ show $ hash res, ([], Just res))
103+
return (Just $ BS.pack $ show $ hash res, Just res)
98104

99105
getModificationTimeRule :: VFSHandle -> (NormalizedFilePath -> Action Bool) -> Rules ()
100-
getModificationTimeRule vfs isWatched =
101-
defineEarlyCutoff $ \(GetModificationTime_ missingFileDiags) file -> do
106+
getModificationTimeRule vfs isWatched = defineEarlyCutoff $ Rule $ \(GetModificationTime_ missingFileDiags) file ->
107+
getModificationTimeImpl vfs isWatched missingFileDiags file
108+
109+
getModificationTimeImpl :: VFSHandle
110+
-> (NormalizedFilePath -> Action Bool)
111+
-> Bool
112+
-> NormalizedFilePath
113+
-> Action
114+
(Maybe BS.ByteString, ([FileDiagnostic], Maybe FileVersion))
115+
getModificationTimeImpl vfs isWatched missingFileDiags file = do
102116
let file' = fromNormalizedFilePath file
103117
let wrap time@(l,s) = (Just $ BS.pack $ show time, ([], Just $ ModificationTime l s))
104118
mbVirtual <- liftIO $ getVirtualFile vfs $ filePathToUri' file

ghcide/src/Development/IDE/Core/OfInterest.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,10 @@ instance Binary GetFilesOfInterest
5656
ofInterestRules :: Rules ()
5757
ofInterestRules = do
5858
addIdeGlobal . OfInterestVar =<< liftIO (newVar HashMap.empty)
59-
defineEarlyCutoff $ \GetFilesOfInterest _file -> assert (null $ fromNormalizedFilePath _file) $ do
59+
defineEarlyCutoff $ RuleNoDiagnostics $ \GetFilesOfInterest _file -> assert (null $ fromNormalizedFilePath _file) $ do
6060
alwaysRerun
6161
filesOfInterest <- getFilesOfInterestUntracked
62-
pure (Just $ BS.fromString $ show filesOfInterest, ([], Just filesOfInterest))
62+
pure (Just $ BS.fromString $ show filesOfInterest, Just filesOfInterest)
6363

6464

6565
-- | Get the files that are open in the IDE.

ghcide/src/Development/IDE/Core/Rules.hs

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -169,13 +169,13 @@ usesE :: IdeRule k v => k -> [NormalizedFilePath] -> MaybeT IdeAction [(v,Positi
169169
usesE k = MaybeT . fmap sequence . mapM (useWithStaleFast k)
170170

171171
defineNoFile :: IdeRule k v => (k -> Action v) -> Rules ()
172-
defineNoFile f = define $ \k file -> do
173-
if file == emptyFilePath then do res <- f k; return ([], Just res) else
172+
defineNoFile f = defineNoDiagnostics $ \k file -> do
173+
if file == emptyFilePath then do res <- f k; return (Just res) else
174174
fail $ "Rule " ++ show k ++ " should always be called with the empty string for a file"
175175

176176
defineEarlyCutOffNoFile :: IdeRule k v => (k -> Action (BS.ByteString, v)) -> Rules ()
177-
defineEarlyCutOffNoFile f = defineEarlyCutoff $ \k file -> do
178-
if file == emptyFilePath then do (hash, res) <- f k; return (Just hash, ([], Just res)) else
177+
defineEarlyCutOffNoFile f = defineEarlyCutoff $ RuleNoDiagnostics $ \k file -> do
178+
if file == emptyFilePath then do (hash, res) <- f k; return (Just hash, Just res) else
179179
fail $ "Rule " ++ show k ++ " should always be called with the empty string for a file"
180180

181181
------------------------------------------------------------
@@ -308,7 +308,7 @@ priorityFilesOfInterest = Priority (-2)
308308
-- and https://github.com/mpickering/ghcide/pull/22#issuecomment-625070490
309309
-- GHC wiki about: https://gitlab.haskell.org/ghc/ghc/-/wikis/api-annotations
310310
getParsedModuleRule :: Rules ()
311-
getParsedModuleRule = defineEarlyCutoff $ \GetParsedModule file -> do
311+
getParsedModuleRule = defineEarlyCutoff $ Rule $ \GetParsedModule file -> do
312312
ModSummaryResult{msrModSummary = ms} <- use_ GetModSummary file
313313
sess <- use_ GhcSession file
314314
let hsc = hscEnv sess
@@ -372,8 +372,9 @@ mergeParseErrorsHaddock normal haddock = normal ++
372372
-- | This rule provides a ParsedModule preserving all annotations,
373373
-- including keywords, punctuation and comments.
374374
-- So it is suitable for use cases where you need a perfect edit.
375+
-- FIXME this rule should probably not produce diagnostics
375376
getParsedModuleWithCommentsRule :: Rules ()
376-
getParsedModuleWithCommentsRule = defineEarlyCutoff $ \GetParsedModuleWithComments file -> do
377+
getParsedModuleWithCommentsRule = defineEarlyCutoff $ Rule $ \GetParsedModuleWithComments file -> do
377378
ModSummaryResult{msrModSummary = ms} <- use_ GetModSummary file
378379
sess <- use_ GhcSession file
379380
opt <- getIdeOptions
@@ -569,13 +570,13 @@ reportImportCyclesRule =
569570
-- NOTE: result does not include the argument file.
570571
getDependenciesRule :: Rules ()
571572
getDependenciesRule =
572-
defineEarlyCutoff $ \GetDependencies file -> do
573+
defineEarlyCutoff $ RuleNoDiagnostics $ \GetDependencies file -> do
573574
depInfo <- use_ GetDependencyInformation file
574575
let allFiles = reachableModules depInfo
575576
_ <- uses_ ReportImportCycles allFiles
576577
opts <- getIdeOptions
577578
let mbFingerprints = map (fingerprintString . fromNormalizedFilePath) allFiles <$ optShakeFiles opts
578-
return (fingerprintToBS . fingerprintFingerprints <$> mbFingerprints, ([], transitiveDeps depInfo file))
579+
return (fingerprintToBS . fingerprintFingerprints <$> mbFingerprints, transitiveDeps depInfo file)
579580

580581
getHieAstsRule :: Rules ()
581582
getHieAstsRule =
@@ -739,7 +740,7 @@ loadGhcSession = do
739740
let fingerprint = hash (sessionVersion res)
740741
return (BS.pack (show fingerprint), res)
741742

742-
defineEarlyCutoff $ \GhcSession file -> do
743+
defineEarlyCutoff $ Rule $ \GhcSession file -> do
743744
IdeGhcSession{loadSessionFun} <- useNoFile_ GhcSessionIO
744745
(val,deps) <- liftIO $ loadSessionFun $ fromNormalizedFilePath file
745746

@@ -790,7 +791,7 @@ ghcSessionDepsDefinition file = do
790791
-- | Load a iface from disk, or generate it if there isn't one or it is out of date
791792
-- This rule also ensures that the `.hie` and `.o` (if needed) files are written out.
792793
getModIfaceFromDiskRule :: Rules ()
793-
getModIfaceFromDiskRule = defineEarlyCutoff $ \GetModIfaceFromDisk f -> do
794+
getModIfaceFromDiskRule = defineEarlyCutoff $ Rule $ \GetModIfaceFromDisk f -> do
794795
ms <- msrModSummary <$> use_ GetModSummary f
795796
(diags_session, mb_session) <- ghcSessionDepsDefinition f
796797
case mb_session of
@@ -814,7 +815,7 @@ getModIfaceFromDiskRule = defineEarlyCutoff $ \GetModIfaceFromDisk f -> do
814815
-- disk since we are careful to write out the `.hie` file before writing the
815816
-- `.hi` file
816817
getModIfaceFromDiskAndIndexRule :: Rules ()
817-
getModIfaceFromDiskAndIndexRule = defineEarlyCutoff $ \GetModIfaceFromDiskAndIndex f -> do
818+
getModIfaceFromDiskAndIndexRule = defineEarlyCutoff $ RuleNoDiagnostics $ \GetModIfaceFromDiskAndIndex f -> do
818819
x <- use_ GetModIfaceFromDisk f
819820
se@ShakeExtras{hiedb} <- getShakeExtras
820821

@@ -844,10 +845,10 @@ getModIfaceFromDiskAndIndexRule = defineEarlyCutoff $ \GetModIfaceFromDiskAndInd
844845
indexHieFile se ms f hash hf
845846

846847
let fp = hiFileFingerPrint x
847-
return (Just fp, ([], Just x))
848+
return (Just fp, Just x)
848849

849850
isHiFileStableRule :: Rules ()
850-
isHiFileStableRule = defineEarlyCutoff $ \IsHiFileStable f -> do
851+
isHiFileStableRule = defineEarlyCutoff $ RuleNoDiagnostics $ \IsHiFileStable f -> do
851852
ms <- msrModSummary <$> use_ GetModSummaryWithoutTimestamps f
852853
let hiFile = toNormalizedFilePath'
853854
$ ml_hi_file $ ms_location ms
@@ -865,11 +866,11 @@ isHiFileStableRule = defineEarlyCutoff $ \IsHiFileStable f -> do
865866
pure $ if all (== SourceUnmodifiedAndStable) deps
866867
then SourceUnmodifiedAndStable
867868
else SourceUnmodified
868-
return (Just (BS.pack $ show sourceModified), ([], Just sourceModified))
869+
return (Just (BS.pack $ show sourceModified), Just sourceModified)
869870

870871
getModSummaryRule :: Rules ()
871872
getModSummaryRule = do
872-
defineEarlyCutoff $ \GetModSummary f -> do
873+
defineEarlyCutoff $ Rule $ \GetModSummary f -> do
873874
session <- hscEnv <$> use_ GhcSession f
874875
(modTime, mFileContent) <- getFileContents f
875876
let fp = fromNormalizedFilePath f
@@ -884,7 +885,7 @@ getModSummaryRule = do
884885
return ( Just (fingerprintToBS fingerPrint) , ([], Just res))
885886
Left diags -> return (Nothing, (diags, Nothing))
886887

887-
defineEarlyCutoff $ \GetModSummaryWithoutTimestamps f -> do
888+
defineEarlyCutoff $ RuleNoDiagnostics $ \GetModSummaryWithoutTimestamps f -> do
888889
ms <- use GetModSummary f
889890
case ms of
890891
Just res@ModSummaryResult{..} -> do
@@ -893,8 +894,8 @@ getModSummaryRule = do
893894
ms_hspp_buf = error "use GetModSummary instead of GetModSummaryWithoutTimestamps"
894895
}
895896
fp = fingerprintToBS msrFingerprint
896-
return (Just fp, ([], Just res{msrModSummary = ms}))
897-
Nothing -> return (Nothing, ([], Nothing))
897+
return (Just fp, Just res{msrModSummary = ms})
898+
Nothing -> return (Nothing, Nothing)
898899

899900
generateCore :: RunSimplifier -> NormalizedFilePath -> Action (IdeResult ModGuts)
900901
generateCore runSimplifier file = do
@@ -908,7 +909,7 @@ generateCoreRule =
908909
define $ \GenerateCore -> generateCore (RunSimplifier True)
909910

910911
getModIfaceRule :: Rules ()
911-
getModIfaceRule = defineEarlyCutoff $ \GetModIface f -> do
912+
getModIfaceRule = defineEarlyCutoff $ Rule $ \GetModIface f -> do
912913
fileOfInterest <- use_ IsFileOfInterest f
913914
res@(_,(_,mhmi)) <- case fileOfInterest of
914915
IsFOI status -> do
@@ -937,11 +938,11 @@ getModIfaceRule = defineEarlyCutoff $ \GetModIface f -> do
937938
pure res
938939

939940
getModIfaceWithoutLinkableRule :: Rules ()
940-
getModIfaceWithoutLinkableRule = defineEarlyCutoff $ \GetModIfaceWithoutLinkable f -> do
941+
getModIfaceWithoutLinkableRule = defineEarlyCutoff $ RuleNoDiagnostics $ \GetModIfaceWithoutLinkable f -> do
941942
mhfr <- use GetModIface f
942943
let mhfr' = fmap (\x -> x{ hirHomeMod = (hirHomeMod x){ hm_linkable = Just (error msg) } }) mhfr
943944
msg = "tried to look at linkable for GetModIfaceWithoutLinkable for " ++ show f
944-
pure (fingerprintToBS . getModuleHash . hirModIface <$> mhfr', ([],mhfr'))
945+
pure (fingerprintToBS . getModuleHash . hirModIface <$> mhfr', mhfr')
945946

946947
-- | Also generates and indexes the `.hie` file, along with the `.o` file if needed
947948
-- Invariant maintained is that if the `.hi` file was successfully written, then the
@@ -1037,7 +1038,7 @@ getLinkableType :: NormalizedFilePath -> Action (Maybe LinkableType)
10371038
getLinkableType f = use_ NeedsCompilation f
10381039

10391040
needsCompilationRule :: Rules ()
1040-
needsCompilationRule = defineEarlyCutoff $ \NeedsCompilation file -> do
1041+
needsCompilationRule = defineEarlyCutoff $ RuleNoDiagnostics $ \NeedsCompilation file -> do
10411042
graph <- useNoFile GetModuleGraph
10421043
res <- case graph of
10431044
-- Treat as False if some reverse dependency header fails to parse
@@ -1061,7 +1062,7 @@ needsCompilationRule = defineEarlyCutoff $ \NeedsCompilation file -> do
10611062
(uses NeedsCompilation revdeps)
10621063
pure $ computeLinkableType ms modsums (map join needsComps)
10631064

1064-
pure (Just $ BS.pack $ show $ hash res, ([], Just res))
1065+
pure (Just $ BS.pack $ show $ hash res, Just res)
10651066
where
10661067
uses_th_qq (ms_hspp_opts -> dflags) =
10671068
xopt LangExt.TemplateHaskell dflags || xopt LangExt.QuasiQuotes dflags

ghcide/src/Development/IDE/Core/Shake.hs

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,10 @@ module Development.IDE.Core.Shake(
3838
useWithStale, usesWithStale,
3939
useWithStale_, usesWithStale_,
4040
BadDependency(..),
41-
define, defineEarlyCutoff, defineOnDisk, needOnDisk, needOnDisks,
41+
RuleBody(..),
42+
define, defineNoDiagnostics,
43+
defineEarlyCutoff,
44+
defineOnDisk, needOnDisk, needOnDisks,
4245
getDiagnostics,
4346
mRunLspT, mRunLspTCallback,
4447
getHiddenDiagnostics,
@@ -796,7 +799,12 @@ garbageCollect keep = do
796799
define
797800
:: IdeRule k v
798801
=> (k -> NormalizedFilePath -> Action (IdeResult v)) -> Rules ()
799-
define op = defineEarlyCutoff $ \k v -> (Nothing,) <$> op k v
802+
define op = defineEarlyCutoff $ Rule $ \k v -> (Nothing,) <$> op k v
803+
804+
defineNoDiagnostics
805+
:: IdeRule k v
806+
=> (k -> NormalizedFilePath -> Action (Maybe v)) -> Rules ()
807+
defineNoDiagnostics op = defineEarlyCutoff $ RuleNoDiagnostics $ \k v -> (Nothing,) <$> op k v
800808

801809
-- | Request a Rule result if available
802810
use :: IdeRule k v
@@ -905,12 +913,30 @@ usesWithStale key files = do
905913
-- whether the rule succeeded or not.
906914
mapM (lastValue key) files
907915

916+
data RuleBody k v
917+
= Rule (k -> NormalizedFilePath -> Action (Maybe BS.ByteString, IdeResult v))
918+
| RuleNoDiagnostics (k -> NormalizedFilePath -> Action (Maybe BS.ByteString, Maybe v))
919+
920+
908921
-- | Define a new Rule with early cutoff
909922
defineEarlyCutoff
910923
:: IdeRule k v
911-
=> (k -> NormalizedFilePath -> Action (Maybe BS.ByteString, IdeResult v))
924+
=> RuleBody k v
912925
-> Rules ()
913-
defineEarlyCutoff op = addBuiltinRule noLint noIdentity $ \(Q (key, file)) (old :: Maybe BS.ByteString) mode -> otTracedAction key file isSuccess $ do
926+
defineEarlyCutoff (Rule op) = addBuiltinRule noLint noIdentity $ \(Q (key, file)) (old :: Maybe BS.ByteString) mode -> otTracedAction key file isSuccess $ do
927+
defineEarlyCutoff' key file old mode $ op key file
928+
defineEarlyCutoff (RuleNoDiagnostics op) = addBuiltinRule noLint noIdentity $ \(Q (key, file)) (old :: Maybe BS.ByteString) mode -> otTracedAction key file isSuccess $ do
929+
defineEarlyCutoff' key file old mode $ second (mempty,) <$> op key file
930+
931+
defineEarlyCutoff'
932+
:: IdeRule k v
933+
=> k
934+
-> NormalizedFilePath
935+
-> Maybe BS.ByteString
936+
-> RunMode
937+
-> Action (Maybe BS.ByteString, IdeResult v)
938+
-> Action (RunResult (A (RuleResult k)))
939+
defineEarlyCutoff' key file old mode action = do
914940
extras@ShakeExtras{state, inProgress} <- getShakeExtras
915941
-- don't do progress for GetFileExists, as there are lots of non-nodes for just that one key
916942
(if show key == "GetFileExists" then id else withProgressVar inProgress file) $ do
@@ -929,7 +955,7 @@ defineEarlyCutoff op = addBuiltinRule noLint noIdentity $ \(Q (key, file)) (old
929955
Just res -> return res
930956
Nothing -> do
931957
(bs, (diags, res)) <- actionCatch
932-
(do v <- op key file; liftIO $ evaluate $ force v) $
958+
(do v <- action; liftIO $ evaluate $ force v) $
933959
\(e :: SomeException) -> pure (Nothing, ([ideErrorText file $ T.pack $ show e | not $ isBadDependency e],Nothing))
934960
modTime <- liftIO $ (currentValue . fst =<<) <$> getValues state GetModificationTime file
935961
(bs, res) <- case res of
@@ -957,13 +983,14 @@ defineEarlyCutoff op = addBuiltinRule noLint noIdentity $ \(Q (key, file)) (old
957983
(if eq then ChangedRecomputeSame else ChangedRecomputeDiff)
958984
(encodeShakeValue bs) $
959985
A res
960-
where
961-
withProgressVar :: (Eq a, Hashable a) => Var (HMap.HashMap a Int) -> a -> Action b -> Action b
962-
withProgressVar var file = actionBracket (f succ) (const $ f pred) . const
963-
-- This functions are deliberately eta-expanded to avoid space leaks.
964-
-- Do not remove the eta-expansion without profiling a session with at
965-
-- least 1000 modifications.
966-
where f shift = modifyVar_ var $ \x -> evaluate $ HMap.insertWith (\_ x -> shift x) file (shift 0) x
986+
where
987+
988+
withProgressVar :: (Eq a, Hashable a) => Var (HMap.HashMap a Int) -> a -> Action b -> Action b
989+
withProgressVar var file = actionBracket (f succ) (const $ f pred) . const
990+
-- This functions are deliberately eta-expanded to avoid space leaks.
991+
-- Do not remove the eta-expansion without profiling a session with at
992+
-- least 1000 modifications.
993+
where f shift = modifyVar_ var $ \x -> evaluate $ HMap.insertWith (\_ x -> shift x) file (shift 0) x
967994

968995
isSuccess :: RunResult (A v) -> Bool
969996
isSuccess (RunResult _ _ (A Failed{})) = False

0 commit comments

Comments
 (0)