@@ -644,23 +644,37 @@ getModIfaceFromDiskRule = defineEarlyCutoff $ \GetModIfaceFromDisk f -> do
644644 case mb_session of
645645 Nothing -> return (Nothing , (diags_session, Nothing ))
646646 Just session -> do
647- let hiFile = toNormalizedFilePath'
648- $ case ms_hsc_src ms of
649- HsBootFile -> addBootSuffix (ml_hi_file $ ms_location ms)
650- _ -> ml_hi_file $ ms_location ms
651- mbHiVersion <- use GetModificationTime_ {missingFileDiagnostics= False } hiFile
652- modVersion <- use_ GetModificationTime f
653- let sourceModified = case mbHiVersion of
654- Nothing -> SourceModified
655- Just x -> if modificationTime x >= modificationTime modVersion
656- then SourceUnmodified else SourceModified
647+ sourceModified <- use_ IsHiFileStable f
657648 r <- loadInterface (hscEnv session) ms sourceModified (regenerateHiFile session f)
658649 case r of
659650 (diags, Just x) -> do
660- let fp = fingerprintToBS (getModuleHash (hirModIface x) )
661- return (Just fp, (diags <> diags_session, Just x))
651+ let fp = Just (hiFileFingerPrint x )
652+ return (fp, (diags <> diags_session, Just x))
662653 (diags, Nothing ) -> return (Nothing , (diags ++ diags_session, Nothing ))
663654
655+ isHiFileStableRule :: Rules ()
656+ isHiFileStableRule = define $ \ IsHiFileStable f -> do
657+ ms <- use_ GetModSummary f
658+ let hiFile = toNormalizedFilePath'
659+ $ case ms_hsc_src ms of
660+ HsBootFile -> addBootSuffix (ml_hi_file $ ms_location ms)
661+ _ -> ml_hi_file $ ms_location ms
662+ mbHiVersion <- use GetModificationTime_ {missingFileDiagnostics= False } hiFile
663+ modVersion <- use_ GetModificationTime f
664+ sourceModified <- case mbHiVersion of
665+ Nothing -> pure SourceModified
666+ Just x ->
667+ if modificationTime x < modificationTime modVersion
668+ then pure SourceModified
669+ else do
670+ (fileImports, _) <- use_ GetLocatedImports f
671+ let imports = fmap artifactFilePath . snd <$> fileImports
672+ deps <- uses_ IsHiFileStable (catMaybes imports)
673+ pure $ if all (== SourceUnmodifiedAndStable ) deps
674+ then SourceUnmodifiedAndStable
675+ else SourceUnmodified
676+ return ([] , Just sourceModified)
677+
664678getModSummaryRule :: Rules ()
665679getModSummaryRule = defineEarlyCutoff $ \ GetModSummary f -> do
666680 dflags <- hsc_dflags . hscEnv <$> use_ GhcSession f
@@ -691,21 +705,25 @@ getModSummaryRule = defineEarlyCutoff $ \GetModSummary f -> do
691705 in BS. pack (show fp)
692706
693707getModIfaceRule :: Rules ()
694- getModIfaceRule = define $ \ GetModIface f -> do
708+ getModIfaceRule = defineEarlyCutoff $ \ GetModIface f -> do
695709#if MIN_GHC_API_VERSION(8,6,0) && !defined(GHC_LIB)
696710 fileOfInterest <- use_ IsFileOfInterest f
697711 if fileOfInterest
698712 then do
699713 -- Never load from disk for files of interest
700714 tmr <- use TypeCheck f
701- return ([] , extractHiFileResult tmr)
702- else
703- ([] ,) <$> use GetModIfaceFromDisk f
715+ let ! hiFile = extractHiFileResult tmr
716+ let fp = hiFileFingerPrint <$> hiFile
717+ return (fp, ([] , hiFile))
718+ else do
719+ hiFile <- use GetModIfaceFromDisk f
720+ let fp = hiFileFingerPrint <$> hiFile
721+ return (fp, ([] , hiFile))
704722#else
705723 tm <- use TypeCheck f
706- let modIface = hm_iface . tmrModInfo <$> tm
707- modSummary = tmrModSummary <$> tm
708- return ([] , HiFileResult <$> modSummary <*> modIface )
724+ let ! hiFile = extractHiFileResult tm
725+ let fp = hiFileFingerPrint <$> hiFile
726+ return (fp, ( [] , tmr_hiFileResult <$> tm) )
709727#endif
710728
711729regenerateHiFile :: HscEnvEq -> NormalizedFilePath -> Action ([FileDiagnostic ], Maybe HiFileResult )
@@ -738,7 +756,7 @@ extractHiFileResult :: Maybe TcModuleResult -> Maybe HiFileResult
738756extractHiFileResult Nothing = Nothing
739757extractHiFileResult (Just tmr) =
740758 -- Bang patterns are important to force the inner fields
741- Just $! HiFileResult (tmrModSummary tmr) (hm_iface $ tmrModInfo tmr)
759+ Just $! tmr_hiFileResult tmr
742760
743761isFileOfInterestRule :: Rules ()
744762isFileOfInterestRule = defineEarlyCutoff $ \ IsFileOfInterest f -> do
@@ -763,3 +781,15 @@ mainRule = do
763781 getModIfaceRule
764782 isFileOfInterestRule
765783 getModSummaryRule
784+ isHiFileStableRule
785+
786+ -- | Given the path to a module src file, this rule returns True if the
787+ -- corresponding `.hi` file is stable, that is, if it is newer
788+ -- than the src file, and all its dependencies are stable too.
789+ data IsHiFileStable = IsHiFileStable
790+ deriving (Eq , Show , Typeable , Generic )
791+ instance Hashable IsHiFileStable
792+ instance NFData IsHiFileStable
793+ instance Binary IsHiFileStable
794+
795+ type instance RuleResult IsHiFileStable = SourceModified
0 commit comments