Skip to content

Commit 8f6eb2d

Browse files
authored
remove unnecessary FileExists dependency in GetHiFile (#589)
* remove unnecessary FileExists dependency It is subsumed by the GetModificationTime dependency. One less dependency per .hi file, one less redundant file system access, five fewer lines of code. * Clarify modification time comparisons for .hi and .hie filesAddresses #591 * Fix staleness checking for .hie files (thanks @cocreature)
1 parent 0ff88c6 commit 8f6eb2d

File tree

1 file changed

+34
-33
lines changed

1 file changed

+34
-33
lines changed

src/Development/IDE/Core/Rules.hs

Lines changed: 34 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ import Data.Foldable
5252
import qualified Data.IntMap.Strict as IntMap
5353
import Data.IntMap.Strict (IntMap)
5454
import Data.List
55-
import Data.Ord
5655
import qualified Data.Set as Set
5756
import qualified Data.Text as T
5857
import Development.IDE.GHC.Error
@@ -76,6 +75,8 @@ import Data.ByteString (ByteString)
7675
import Control.Concurrent.Async (concurrently)
7776

7877
import Control.Monad.State
78+
import System.IO.Error (isDoesNotExistError)
79+
import Control.Exception.Safe (IOException, catch)
7980

8081
-- | This is useful for rules to convert rules that can only produce errors or
8182
-- a result into the more general IdeResult type that supports producing
@@ -136,22 +137,24 @@ getHieFile file mod = do
136137
_ -> getPackageHieFile mod file
137138

138139

139-
getHomeHieFile :: NormalizedFilePath -> Action ([a], Maybe HieFile)
140+
getHomeHieFile :: NormalizedFilePath -> Action ([IOException], Maybe HieFile)
140141
getHomeHieFile f = do
141142
ms <- use_ GetModSummary f
142-
let normal_hie_f = toNormalizedFilePath' hie_f
143-
hie_f = ml_hie_file $ ms_location ms
144-
mbHieTimestamp <- use GetModificationTime normal_hie_f
145-
srcTimestamp <- use_ GetModificationTime f
146-
let isUpToDate
147-
| Just d <- mbHieTimestamp = comparing modificationTime d srcTimestamp == GT
148-
| otherwise = False
149143

150-
unless isUpToDate $
151-
void $ use_ TypeCheck f
152-
153-
hf <- liftIO $ whenMaybe isUpToDate (loadHieFile hie_f)
154-
return ([], hf)
144+
-- .hi and .hie files are generated as a byproduct of typechecking.
145+
-- To avoid duplicating staleness checking already performed for .hi files,
146+
-- we overapproximate here by depending on the GetModIface rule.
147+
hiFile <- use GetModIface f
148+
149+
case hiFile of
150+
Nothing -> return ([], Nothing)
151+
Just _ -> liftIO $ do
152+
hf <- loadHieFile $ ml_hie_file $ ms_location ms
153+
return ([], Just hf)
154+
`catch` \e ->
155+
if isDoesNotExistError e
156+
then return ([], Nothing)
157+
else return ([e], Nothing)
155158

156159
getPackageHieFile :: Module -- ^ Package Module to load .hie file for
157160
-> NormalizedFilePath -- ^ Path of home module importing the package module
@@ -575,26 +578,24 @@ getHiFileRule = defineEarlyCutoff $ \GetHiFile f -> do
575578
case sequence depHis of
576579
Nothing -> pure (Nothing, ([], Nothing))
577580
Just deps -> do
578-
gotHiFile <- getFileExists hiFile
579-
if not gotHiFile
580-
then pure (Nothing, ([], Nothing))
581-
else do
582-
hiVersion <- use_ GetModificationTime hiFile
583-
modVersion <- use_ GetModificationTime f
584-
let sourceModified = modificationTime hiVersion < modificationTime modVersion
585-
if sourceModified
586-
then do
581+
mbHiVersion <- use GetModificationTime hiFile
582+
modVersion <- use_ GetModificationTime f
583+
case (mbHiVersion, modVersion) of
584+
(Just hiVersion, ModificationTime{})
585+
| modificationTime hiVersion >= modificationTime modVersion -> do
586+
session <- hscEnv <$> use_ GhcSession f
587+
r <- liftIO $ loadInterface session ms deps
588+
case r of
589+
Right iface -> do
590+
let result = HiFileResult ms iface
591+
return (Just (fingerprintToBS (getModuleHash iface)), ([], Just result))
592+
Left err -> do
593+
let diag = ideErrorWithSource (Just "interface file loading") (Just DsError) f . T.pack $ err
594+
return (Nothing, (pure diag, Nothing))
595+
(_, VFSVersion{}) ->
596+
error "internal error - GetHiFile of file of interest"
597+
_ ->
587598
pure (Nothing, ([], Nothing))
588-
else do
589-
session <- hscEnv <$> use_ GhcSession f
590-
r <- liftIO $ loadInterface session ms deps
591-
case r of
592-
Right iface -> do
593-
let result = HiFileResult ms iface
594-
return (Just (fingerprintToBS (getModuleHash iface)), ([], Just result))
595-
Left err -> do
596-
let diag = ideErrorWithSource (Just "interface file loading") (Just DsError) f . T.pack $ err
597-
return (Nothing, (pure diag, Nothing))
598599

599600
getModSummaryRule :: Rules ()
600601
getModSummaryRule = define $ \GetModSummary f -> do

0 commit comments

Comments
 (0)