Skip to content

Commit 3dbdfaf

Browse files
committed
Improve GhcSessionDeps and lay out assumptions
1 parent 5d3b0a4 commit 3dbdfaf

File tree

3 files changed

+40
-37
lines changed

3 files changed

+40
-37
lines changed

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

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1029,21 +1029,21 @@ loadModulesHome mod_infos e =
10291029
#endif
10301030

10311031
-- Merge the HPTs, module graphs and FinderCaches
1032+
-- See Note [GhcSessionDeps] in Development.IDE.Core.Rules
1033+
-- Add the current ModSummary to the graph, along with the
1034+
-- HomeModInfo's of all direct dependencies (by induction hypothesis all
1035+
-- transitive dependencies will be contained in envs)
10321036
#if MIN_VERSION_ghc(9,3,0)
1033-
mergeEnvs :: HscEnv -> [ModuleGraphNode] -> [HomeModInfo] -> [HscEnv] -> IO HscEnv
1034-
mergeEnvs env extraNodes extraMods envs = do
1035-
let extraModSummaries = mapMaybe moduleGraphNodeModSum extraNodes
1036-
ims = map (\ms -> Compat.installedModule (toUnitId $ moduleUnit $ ms_mod ms) (moduleName (ms_mod ms))) extraModSummaries
1037-
ifrs = zipWith (\ms -> InstalledFound (ms_location ms)) extraModSummaries ims
1038-
curFinderCache =
1039-
foldl'
1040-
(\fc (im, ifr) -> Compat.extendInstalledModuleEnv fc im ifr) Compat.emptyInstalledModuleEnv
1041-
$ zip ims ifrs
1037+
mergeEnvs :: HscEnv -> (ModSummary, [NodeKey]) -> [HomeModInfo] -> [HscEnv] -> IO HscEnv
1038+
mergeEnvs env (ms, deps) extraMods envs = do
1039+
let im = Compat.installedModule (toUnitId $ moduleUnit $ ms_mod ms) (moduleName (ms_mod ms))
1040+
ifr = InstalledFound (ms_location ms) im
1041+
curFinderCache = Compat.extendInstalledModuleEnv Compat.emptyInstalledModuleEnv im ifr
10421042
-- Very important to force this as otherwise the hsc_mod_graph field is not
10431043
-- forced and ends up retaining a reference to all the old hsc_envs we have merged to get
10441044
-- this new one, which in turn leads to the EPS referencing the HPT.
10451045
module_graph_nodes =
1046-
extraNodes ++ nubOrdOn mkNodeKey (concatMap (mgModSummaries' . hsc_mod_graph) envs)
1046+
nubOrdOn mkNodeKey (ModuleNode deps ms : concatMap (mgModSummaries' . hsc_mod_graph) envs)
10471047

10481048
newFinderCache <- concatFC curFinderCache (map hsc_FC envs)
10491049
liftRnf rwhnf module_graph_nodes `seq` (return $ loadModulesHome extraMods $
@@ -1070,11 +1070,11 @@ mergeEnvs env extraNodes extraMods envs = do
10701070
pure $ FinderCache fcModules' fcFiles'
10711071

10721072
#else
1073-
mergeEnvs :: HscEnv -> [ModSummary] -> [HomeModInfo] -> [HscEnv] -> IO HscEnv
1074-
mergeEnvs env extraModSummaries extraMods envs = do
1073+
mergeEnvs :: HscEnv -> ModSummary -> [HomeModInfo] -> [HscEnv] -> IO HscEnv
1074+
mergeEnvs env ms extraMods envs = do
10751075
prevFinderCache <- concatFC <$> mapM (readIORef . hsc_FC) envs
1076-
let ims = map (\ms -> Compat.installedModule (toUnitId $ moduleUnit $ ms_mod ms) (moduleName (ms_mod ms))) extraModSummaries
1077-
ifrs = zipWith (\ms -> InstalledFound (ms_location ms)) extraModSummaries ims
1076+
let im = Compat.installedModule (toUnitId $ moduleUnit $ ms_mod ms) (moduleName (ms_mod ms))
1077+
ifr = InstalledFound (ms_location ms) im
10781078
-- Very important to force this as otherwise the hsc_mod_graph field is not
10791079
-- forced and ends up retaining a reference to all the old hsc_envs we have merged to get
10801080
-- this new one, which in turn leads to the EPS referencing the HPT.
@@ -1085,12 +1085,9 @@ mergeEnvs env extraModSummaries extraMods envs = do
10851085
-- This may have to change in the future.
10861086
map extendModSummaryNoDeps $
10871087
#endif
1088-
extraModSummaries ++ nubOrdOn ms_mod (concatMap (mgModSummaries . hsc_mod_graph) envs)
1088+
nubOrdOn ms_mod (ms : concatMap (mgModSummaries . hsc_mod_graph) envs)
10891089

1090-
newFinderCache <- newIORef $
1091-
foldl'
1092-
(\fc (im, ifr) -> Compat.extendInstalledModuleEnv fc im ifr) prevFinderCache
1093-
$ zip ims ifrs
1090+
newFinderCache <- newIORef $ Compat.extendInstalledModuleEnv prevFinderCache im ifr
10941091
liftRnf rwhnf module_graph_nodes `seq` (return $ loadModulesHome extraMods $
10951092
env{
10961093
hsc_HPT = foldMapBy mergeUDFM emptyUDFM hsc_HPT envs,

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

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ import Control.Applicative (liftA2)
6767
#endif
6868
import Control.Concurrent.Async (concurrently)
6969
import Control.Concurrent.Strict
70+
import Control.DeepSeq
7071
import Control.Exception.Safe
7172
import Control.Monad.Extra
7273
import Control.Monad.Reader
@@ -668,7 +669,7 @@ typeCheckRule recorder = define (cmapWithPrio LogShake recorder) $ \TypeCheck fi
668669
-- very expensive.
669670
when (foi == NotFOI) $
670671
logWith recorder Logger.Warning $ LogTypecheckedFOI file
671-
typeCheckRuleDefinition hsc pm file
672+
typeCheckRuleDefinition hsc pm
672673

673674
knownFilesRule :: Recorder (WithPriority Log) -> Rules ()
674675
knownFilesRule recorder = defineEarlyCutOffNoFile (cmapWithPrio LogShake recorder) $ \GetKnownTargets -> do
@@ -689,9 +690,8 @@ getModuleGraphRule recorder = defineNoFile (cmapWithPrio LogShake recorder) $ \G
689690
typeCheckRuleDefinition
690691
:: HscEnv
691692
-> ParsedModule
692-
-> NormalizedFilePath
693693
-> Action (IdeResult TcModuleResult)
694-
typeCheckRuleDefinition hsc pm file = do
694+
typeCheckRuleDefinition hsc pm = do
695695
setPriority priorityTypeCheck
696696
IdeOptions { optDefer = defer } <- getIdeOptions
697697

@@ -759,6 +759,11 @@ instance Default GhcSessionDepsConfig where
759759
{ checkForImportCycles = True
760760
}
761761

762+
-- | Note [GhcSessionDeps]
763+
-- For a file 'Foo', GhcSessionDeps "Foo.hs" results in an HscEnv which includes
764+
-- 1. HomeModInfo's (in the HUG/HPT) for all modules in the transitive closure of "Foo", **NOT** including "Foo" itself.
765+
-- 2. ModSummary's (in the ModuleGraph) for all modules in the transitive closure of "Foo", including "Foo" itself.
766+
-- 3. ModLocation's (in the FinderCache) all modules in the transitive closure of "Foo", including "Foo" itself.
762767
ghcSessionDepsDefinition
763768
:: -- | full mod summary
764769
Bool ->
@@ -771,27 +776,25 @@ ghcSessionDepsDefinition fullModSummary GhcSessionDepsConfig{..} env file = do
771776
Nothing -> return Nothing
772777
Just deps -> do
773778
when checkForImportCycles $ void $ uses_ ReportImportCycles deps
774-
mss <- map msrModSummary <$> if fullModSummary
775-
then uses_ GetModSummary deps
776-
else uses_ GetModSummaryWithoutTimestamps deps
779+
ms <- msrModSummary <$> if fullModSummary
780+
then use_ GetModSummary file
781+
else use_ GetModSummaryWithoutTimestamps file
777782

778783
depSessions <- map hscEnv <$> uses_ (GhcSessionDeps_ fullModSummary) deps
779784
ifaces <- uses_ GetModIface deps
780785
let inLoadOrder = map (\HiFileResult{..} -> HomeModInfo hirModIface hirModDetails Nothing) ifaces
781786
#if MIN_VERSION_ghc(9,3,0)
782-
mss_imports <- uses_ GetLocatedImports (file : deps)
783-
final_deps <- forM mss_imports $ \imports -> do
784-
let fs = mapMaybe (fmap artifactFilePath . snd) imports
785-
dep_mss <- map msrModSummary <$> if fullModSummary
786-
then uses_ GetModSummary fs
787-
else uses_ GetModSummaryWithoutTimestamps fs
788-
return (map (NodeKey_Module . msKey) dep_mss)
789-
ms <- msrModSummary <$> use_ GetModSummary file
790-
let moduleNodes = zipWith ModuleNode final_deps (ms : mss)
787+
-- On GHC 9.4+, the module graph contains not only ModSummary's but each `ModuleNode` in the graph
788+
-- also points to all the direct descendents of the current module. To get the keys for the descendents
789+
-- we must get their `ModSummary`s
790+
!final_deps <- do
791+
dep_mss <- map msrModSummary <$> uses_ GetModSummaryWithoutTimestamps deps
792+
return $!! map (NodeKey_Module . msKey) dep_mss
793+
let moduleNode = (ms, final_deps)
791794
#else
792-
let moduleNodes = mss
795+
let moduleNode = ms
793796
#endif
794-
session' <- liftIO $ mergeEnvs hsc moduleNodes inLoadOrder depSessions
797+
session' <- liftIO $ mergeEnvs hsc moduleNode inLoadOrder depSessions
795798

796799
Just <$> liftIO (newHscEnvEqWithImportPaths (envImportPaths env) session' [])
797800

@@ -996,7 +999,7 @@ regenerateHiFile sess f ms compNeeded = do
996999
Just pm -> do
9971000
-- Invoke typechecking directly to update it without incurring a dependency
9981001
-- on the parsed module and the typecheck rules
999-
(diags', mtmr) <- typeCheckRuleDefinition hsc pm f
1002+
(diags', mtmr) <- typeCheckRuleDefinition hsc pm
10001003
case mtmr of
10011004
Nothing -> pure (diags', Nothing)
10021005
Just tmr -> do

ghcide/src/Development/IDE/GHC/Orphans.hs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,4 +223,7 @@ instance NFData PkgQual where
223223

224224
instance NFData UnitId where
225225
rnf = rwhnf
226+
227+
instance NFData NodeKey where
228+
rnf = rwhnf
226229
#endif

0 commit comments

Comments
 (0)