Skip to content

Commit 15902b1

Browse files
Fix space leak where EPS retained HPTs from old HscEnv (#2553)
The issue here is that the `ModuleGraph` value is not forced eagerly, so the EPS ends up loading an interface file for an external package and retains a stale reference to the old HPT for the rest of the session. The heap should always satisfy the invariant that no HomeModInfo are reachable via the EPS. See GHC issue #20509 for something similar. Co-authored-by: Anton Latukha <[email protected]>
1 parent 65a8512 commit 15902b1

File tree

1 file changed

+13
-6
lines changed

1 file changed

+13
-6
lines changed

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

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,9 @@ import HieDb
5656
import Language.LSP.Types (DiagnosticTag (..))
5757

5858
#if MIN_VERSION_ghc(8,10,0)
59-
import Control.DeepSeq (force, rnf)
59+
import Control.DeepSeq (force, rnf, liftRnf, rwhnf)
6060
#else
61-
import Control.DeepSeq (rnf)
61+
import Control.DeepSeq (rnf, liftRnf, rwhnf)
6262
import ErrUtils
6363
#endif
6464

@@ -691,7 +691,8 @@ loadModulesHome
691691
-> HscEnv
692692
-> HscEnv
693693
loadModulesHome mod_infos e =
694-
e { hsc_HPT = addListToHpt (hsc_HPT e) [(mod_name x, x) | x <- mod_infos]
694+
let !new_modules = addListToHpt (hsc_HPT e) [(mod_name x, x) | x <- mod_infos]
695+
in e { hsc_HPT = new_modules
695696
, hsc_type_env_var = Nothing }
696697
where
697698
mod_name = moduleName . mi_module . hm_iface
@@ -702,15 +703,21 @@ mergeEnvs env extraModSummaries extraMods envs = do
702703
prevFinderCache <- concatFC <$> mapM (readIORef . hsc_FC) envs
703704
let ims = map (Compat.installedModule (homeUnitId_ $ hsc_dflags env) . moduleName . ms_mod) extraModSummaries
704705
ifrs = zipWith (\ms -> InstalledFound (ms_location ms)) extraModSummaries ims
706+
-- Very important to force this as otherwise the hsc_mod_graph field is not
707+
-- forced and ends up retaining a reference to all the old hsc_envs we have merged to get
708+
-- this new one, which in turn leads to the EPS referencing the HPT.
709+
module_graph_nodes =
710+
extraModSummaries ++ nubOrdOn ms_mod (concatMap (mgModSummaries . hsc_mod_graph) envs)
711+
705712
newFinderCache <- newIORef $
706713
foldl'
707714
(\fc (im, ifr) -> Compat.extendInstalledModuleEnv fc im ifr) prevFinderCache
708715
$ zip ims ifrs
709-
return $ loadModulesHome extraMods $ env{
716+
liftRnf rwhnf module_graph_nodes `seq` (return $ loadModulesHome extraMods $ env{
710717
hsc_HPT = foldMapBy mergeUDFM emptyUDFM hsc_HPT envs,
711718
hsc_FC = newFinderCache,
712-
hsc_mod_graph = mkModuleGraph $ extraModSummaries ++ nubOrdOn ms_mod (concatMap (mgModSummaries . hsc_mod_graph) envs)
713-
}
719+
hsc_mod_graph = mkModuleGraph module_graph_nodes
720+
})
714721
where
715722
mergeUDFM = plusUDFM_C combineModules
716723
combineModules a b

0 commit comments

Comments
 (0)