Skip to content

Commit bb19424

Browse files
committed
GHC 9.12 support
wip disable all plugins for 9.12.0 wip
1 parent 9cca428 commit bb19424

File tree

29 files changed

+566
-153
lines changed

29 files changed

+566
-153
lines changed

cabal.project

+11-2
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@ packages:
88
./hls-test-utils
99

1010

11-
index-state: 2024-12-02T00:00:00Z
11+
index-state: 2025-03-20T00:00:00Z
1212

1313
tests: True
1414
test-show-details: direct
1515

16-
benchmarks: True
16+
benchmarks: False
1717

1818
write-ghc-environment-files: never
1919

@@ -59,3 +59,12 @@ if impl(ghc >= 9.8.4) && impl(ghc < 9.8.5)
5959
ghc-lib-parser:filepath
6060
constraints:
6161
ghc-lib-parser==9.8.4.20241130
62+
63+
if impl(ghc >= 9.11)
64+
benchmarks: False
65+
allow-newer:
66+
hiedb:base,
67+
hiedb:ghc,
68+
hie-bios:ghc,
69+
ghc-trace-events:base,
70+
tasty-hspec:base,

ghcide/ghcide.cabal

+1
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ library
9292
, mtl
9393
, opentelemetry >=0.6.1
9494
, optparse-applicative
95+
, os-string
9596
, parallel
9697
, prettyprinter >=1.7
9798
, prettyprinter-ansi-terminal

ghcide/session-loader/Development/IDE/Session.hs

+10
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,10 @@ import GHC.Types.Error (errMsgDiagnostic,
124124
singleMessage)
125125
import GHC.Unit.State
126126

127+
#if MIN_VERSION_ghc(9,13,0)
128+
import GHC.Driver.Make (checkHomeUnitsClosed)
129+
#endif
130+
127131
data Log
128132
= LogSettingInitialDynFlags
129133
| LogGetInitialGhcLibDirDefaultCradleFail !CradleError !FilePath !(Maybe FilePath) !(Cradle Void)
@@ -782,6 +786,11 @@ toFlagsMap TargetDetails{..} =
782786
setNameCache :: NameCache -> HscEnv -> HscEnv
783787
setNameCache nc hsc = hsc { hsc_NC = nc }
784788

789+
#if MIN_VERSION_ghc(9,13,0)
790+
-- Moved back to implementation in GHC.
791+
checkHomeUnitsClosed' :: UnitEnv -> OS.Set UnitId -> [DriverMessages]
792+
checkHomeUnitsClosed' ue _ = checkHomeUnitsClosed ue
793+
#elif MIN_VERSION_ghc(9,3,0)
785794
-- This function checks the important property that if both p and q are home units
786795
-- then any dependency of p, which transitively depends on q is also a home unit.
787796
-- GHC had an implementation of this function, but it was horribly inefficient
@@ -838,6 +847,7 @@ checkHomeUnitsClosed' ue home_id_set
838847
Just depends ->
839848
let todo'' = (depends OS.\\ done) `OS.union` todo'
840849
in DigraphNode uid uid (OS.toList depends) : go (OS.insert uid done) todo''
850+
#endif
841851

842852
-- | Create a mapping from FilePaths to HscEnvEqs
843853
-- This combines all the components we know about into

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

+154-35
Large diffs are not rendered by default.

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,8 @@ import Development.IDE.Types.Location (NormalizedFilePath)
5656
import qualified Development.IDE.Types.Location as Location
5757
import qualified Ide.Logger as Logger
5858
import Ide.Plugin.Error
59-
import Ide.PluginUtils (rangesOverlap)
6059
import Ide.Types
60+
import Ide.PluginUtils (rangesOverlap)
6161
import qualified Language.LSP.Protocol.Lens as LSP
6262
import Language.LSP.Protocol.Message (SMethod (..))
6363
import qualified Language.LSP.Protocol.Types as LSP

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

+9-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import qualified Data.Map as M
2424
import Data.Time.Clock.POSIX
2525
import Data.Typeable
2626
import Development.IDE.GHC.Compat hiding
27-
(HieFileResult)
27+
(HieFileResult, assert)
2828
import Development.IDE.GHC.Compat.Util
2929
import Development.IDE.GHC.CoreFile
3030
import Development.IDE.GHC.Util
@@ -282,6 +282,8 @@ type instance RuleResult GetFileContents = (FileVersion, Maybe Rope)
282282

283283
type instance RuleResult GetFileExists = Bool
284284

285+
type instance RuleResult GetFileHash = Fingerprint
286+
285287
type instance RuleResult AddWatchedFile = Bool
286288

287289

@@ -337,6 +339,12 @@ data GetFileExists = GetFileExists
337339
instance NFData GetFileExists
338340
instance Hashable GetFileExists
339341

342+
data GetFileHash = GetFileHash
343+
deriving (Eq, Show, Typeable, Generic)
344+
345+
instance NFData GetFileHash
346+
instance Hashable GetFileHash
347+
340348
data FileOfInterestStatus
341349
= OnDisk
342350
| Modified { firstOpen :: !Bool -- ^ was this file just opened

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

+56-13
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ import System.Info.Extra (isWindows)
174174
import qualified Data.IntMap as IM
175175
import GHC.Fingerprint
176176

177+
import GHC.Driver.Env (hsc_all_home_unit_ids)
177178

178179
data Log
179180
= LogShake Shake.Log
@@ -519,7 +520,12 @@ persistentHieFileRule recorder = addPersistentRule GetHieAst $ \file -> runMaybe
519520

520521
getHieAstRuleDefinition :: NormalizedFilePath -> HscEnv -> TcModuleResult -> Action (IdeResult HieAstResult)
521522
getHieAstRuleDefinition f hsc tmr = do
522-
(diags, masts) <- liftIO $ generateHieAsts hsc tmr
523+
(diags, masts') <- liftIO $ generateHieAsts hsc tmr
524+
#if MIN_VERSION_ghc(9,11,0)
525+
let masts = fst <$> masts'
526+
#else
527+
let masts = masts'
528+
#endif
523529
se <- getShakeExtras
524530

525531
isFoi <- use_ IsFileOfInterest f
@@ -529,7 +535,7 @@ getHieAstRuleDefinition f hsc tmr = do
529535
LSP.sendNotification (SMethod_CustomMethod (Proxy @"ghcide/reference/ready")) $
530536
toJSON $ fromNormalizedFilePath f
531537
pure []
532-
_ | Just asts <- masts -> do
538+
_ | Just asts <- masts' -> do
533539
source <- getSourceFileSource f
534540
let exports = tcg_exports $ tmrTypechecked tmr
535541
modSummary = tmrModSummary tmr
@@ -610,6 +616,13 @@ knownFilesRule recorder = defineEarlyCutOffNoFile (cmapWithPrio LogShake recorde
610616
fs <- knownTargets
611617
pure (LBS.toStrict $ B.encode $ hash fs, unhashed fs)
612618

619+
getFileHashRule :: Recorder (WithPriority Log) -> Rules ()
620+
getFileHashRule recorder =
621+
defineEarlyCutoff (cmapWithPrio LogShake recorder) $ Rule $ \GetFileHash file -> do
622+
void $ use_ GetModificationTime file
623+
fileHash <- liftIO $ Util.getFileHash (fromNormalizedFilePath file)
624+
return (Just (fingerprintToBS fileHash), ([], Just fileHash))
625+
613626
getModuleGraphRule :: Recorder (WithPriority Log) -> Rules ()
614627
getModuleGraphRule recorder = defineEarlyCutOffNoFile (cmapWithPrio LogShake recorder) $ \GetModuleGraph -> do
615628
fs <- toKnownFiles <$> useNoFile_ GetKnownTargets
@@ -646,6 +659,7 @@ typeCheckRuleDefinition hsc pm = do
646659
unlift <- askUnliftIO
647660
let dets = TypecheckHelpers
648661
{ getLinkables = unliftIO unlift . uses_ GetLinkable
662+
, getModuleGraph = unliftIO unlift $ useNoFile_ GetModuleGraph
649663
}
650664
addUsageDependencies $ liftIO $
651665
typecheckModule defer hsc dets pm
@@ -757,7 +771,8 @@ ghcSessionDepsDefinition fullModSummary GhcSessionDepsConfig{..} env file = do
757771
nubOrdOn mkNodeKey (ModuleNode final_deps ms : concatMap mgModSummaries' mgs)
758772
liftIO $ evaluate $ liftRnf rwhnf module_graph_nodes
759773
return $ mkModuleGraph module_graph_nodes
760-
session' <- liftIO $ mergeEnvs hsc mg ms inLoadOrder depSessions
774+
de <- useNoFile_ GetModuleGraph
775+
session' <- liftIO $ mergeEnvs hsc mg de ms inLoadOrder depSessions
761776

762777
-- Here we avoid a call to to `newHscEnvEqWithImportPaths`, which creates a new
763778
-- ExportsMap when it is called. We only need to create the ExportsMap once per
@@ -786,9 +801,11 @@ getModIfaceFromDiskRule recorder = defineEarlyCutoff (cmapWithPrio LogShake reco
786801
, old_value = m_old
787802
, get_file_version = use GetModificationTime_{missingFileDiagnostics = False}
788803
, get_linkable_hashes = \fs -> map (snd . fromJust . hirCoreFp) <$> uses_ GetModIface fs
804+
, get_module_graph = useNoFile_ GetModuleGraph
789805
, regenerate = regenerateHiFile session f ms
790806
}
791-
r <- loadInterface (hscEnv session) ms linkableType recompInfo
807+
hsc_env' <- setFileCacheHook (hscEnv session)
808+
r <- loadInterface hsc_env' ms linkableType recompInfo
792809
case r of
793810
(diags, Nothing) -> return (Nothing, (diags, Nothing))
794811
(diags, Just x) -> do
@@ -856,7 +873,7 @@ getModSummaryRule displayTHWarning recorder = do
856873
defineEarlyCutoff (cmapWithPrio LogShake recorder) $ Rule $ \GetModSummary f -> do
857874
session' <- hscEnv <$> use_ GhcSession f
858875
modify_dflags <- getModifyDynFlags dynFlagsModifyGlobal
859-
let session = hscSetFlags (modify_dflags $ hsc_dflags session') session'
876+
let session = setNonHomeFCHook $ hscSetFlags (modify_dflags $ hsc_dflags session') session' -- TODO wz1000
860877
(modTime, mFileContent) <- getFileModTimeContents f
861878
let fp = fromNormalizedFilePath f
862879
modS <- liftIO $ runExceptT $
@@ -887,8 +904,9 @@ getModSummaryRule displayTHWarning recorder = do
887904
generateCore :: RunSimplifier -> NormalizedFilePath -> Action (IdeResult ModGuts)
888905
generateCore runSimplifier file = do
889906
packageState <- hscEnv <$> use_ GhcSessionDeps file
907+
hsc' <- setFileCacheHook packageState
890908
tm <- use_ TypeCheck file
891-
liftIO $ compileModule runSimplifier packageState (tmrModSummary tm) (tmrTypechecked tm)
909+
liftIO $ compileModule runSimplifier hsc' (tmrModSummary tm) (tmrTypechecked tm)
892910

893911
generateCoreRule :: Recorder (WithPriority Log) -> Rules ()
894912
generateCoreRule recorder =
@@ -903,14 +921,15 @@ getModIfaceRule recorder = defineEarlyCutoff (cmapWithPrio LogShake recorder) $
903921
tmr <- use_ TypeCheck f
904922
linkableType <- getLinkableType f
905923
hsc <- hscEnv <$> use_ GhcSessionDeps f
924+
hsc' <- setFileCacheHook hsc
906925
let compile = fmap ([],) $ use GenerateCore f
907926
se <- getShakeExtras
908-
(diags, !mbHiFile) <- writeCoreFileIfNeeded se hsc linkableType compile tmr
927+
(diags, !mbHiFile) <- writeCoreFileIfNeeded se hsc' linkableType compile tmr
909928
let fp = hiFileFingerPrint <$> mbHiFile
910929
hiDiags <- case mbHiFile of
911930
Just hiFile
912931
| OnDisk <- status
913-
, not (tmrDeferredError tmr) -> liftIO $ writeHiFile se hsc hiFile
932+
, not (tmrDeferredError tmr) -> liftIO $ writeHiFile se hsc' hiFile
914933
_ -> pure []
915934
return (fp, (diags++hiDiags, mbHiFile))
916935
NotFOI -> do
@@ -934,12 +953,21 @@ incrementRebuildCount = do
934953
count <- getRebuildCountVar <$> getIdeGlobalAction
935954
liftIO $ atomically $ modifyTVar' count (+1)
936955

956+
setFileCacheHook :: HscEnv -> Action HscEnv
957+
setFileCacheHook old_hsc_env = do
958+
#if MIN_VERSION_ghc(9,11,0)
959+
unlift <- askUnliftIO
960+
return $ old_hsc_env { hsc_FC = (hsc_FC old_hsc_env) { lookupFileCache = unliftIO unlift . use_ GetFileHash . toNormalizedFilePath' } }
961+
#else
962+
return old_hsc_env
963+
#endif
964+
937965
-- | Also generates and indexes the `.hie` file, along with the `.o` file if needed
938966
-- Invariant maintained is that if the `.hi` file was successfully written, then the
939967
-- `.hie` and `.o` file (if needed) were also successfully written
940968
regenerateHiFile :: HscEnvEq -> NormalizedFilePath -> ModSummary -> Maybe LinkableType -> Action ([FileDiagnostic], Maybe HiFileResult)
941969
regenerateHiFile sess f ms compNeeded = do
942-
let hsc = hscEnv sess
970+
hsc <- setFileCacheHook (hscEnv sess)
943971
opt <- getIdeOptions
944972

945973
-- Embed haddocks in the interface file
@@ -1038,6 +1066,13 @@ getLinkableRule recorder =
10381066
HiFileResult{hirModSummary, hirModIface, hirModDetails, hirCoreFp} <- use_ GetModIface f
10391067
let obj_file = ml_obj_file (ms_location hirModSummary)
10401068
core_file = ml_core_file (ms_location hirModSummary)
1069+
#if MIN_VERSION_ghc(9,11,0)
1070+
mkLinkable t mod l = Linkable t mod (pure l)
1071+
dotO o = DotO o ModuleObject
1072+
#else
1073+
mkLinkable t mod l = LM t mod [l]
1074+
dotO = DotO
1075+
#endif
10411076
case hirCoreFp of
10421077
Nothing -> error $ "called GetLinkable for a file without a linkable: " ++ show f
10431078
Just (bin_core, fileHash) -> do
@@ -1063,10 +1098,15 @@ getLinkableRule recorder =
10631098
else pure Nothing
10641099
case mobj_time of
10651100
Just obj_t
1066-
| obj_t >= core_t -> pure ([], Just $ HomeModInfo hirModIface hirModDetails (justObjects $ LM (posixSecondsToUTCTime obj_t) (ms_mod hirModSummary) [DotO obj_file]))
1101+
| obj_t >= core_t -> pure ([], Just $ HomeModInfo hirModIface hirModDetails (justObjects $ mkLinkable (posixSecondsToUTCTime obj_t) (ms_mod hirModSummary) (dotO obj_file)))
10671102
_ -> liftIO $ coreFileToLinkable linkableType (hscEnv session) hirModSummary hirModIface hirModDetails bin_core (error "object doesn't have time")
10681103
-- Record the linkable so we know not to unload it, and unload old versions
1069-
whenJust ((homeModInfoByteCode =<< hmi) <|> (homeModInfoObject =<< hmi)) $ \(LM time mod _) -> do
1104+
whenJust ((homeModInfoByteCode =<< hmi) <|> (homeModInfoObject =<< hmi))
1105+
#if MIN_VERSION_ghc(9,11,0)
1106+
$ \(Linkable time mod _) -> do
1107+
#else
1108+
$ \(LM time mod _) -> do
1109+
#endif
10701110
compiledLinkables <- getCompiledLinkables <$> getIdeGlobalAction
10711111
liftIO $ modifyVar compiledLinkables $ \old -> do
10721112
let !to_keep = extendModuleEnv old mod time
@@ -1080,7 +1120,9 @@ getLinkableRule recorder =
10801120
--just before returning it to be loaded. This has a substantial effect on recompile
10811121
--times as the number of loaded modules and splices increases.
10821122
--
1083-
unload (hscEnv session) (map (\(mod', time') -> LM time' mod' []) $ moduleEnvToList to_keep)
1123+
--We use a dummy DotA linkable part to fake a NativeCode linkable.
1124+
--The unload function doesn't care about the exact linkable parts.
1125+
unload (hscEnv session) (map (\(mod', time') -> mkLinkable time' mod' (DotA "dummy")) $ moduleEnvToList to_keep)
10841126
return (to_keep, ())
10851127
return (fileHash <$ hmi, (warns, LinkableResult <$> hmi <*> pure fileHash))
10861128

@@ -1178,12 +1220,13 @@ mainRule recorder RulesConfig{..} = do
11781220
reportImportCyclesRule recorder
11791221
typeCheckRule recorder
11801222
getDocMapRule recorder
1181-
loadGhcSession recorder GhcSessionDepsConfig{fullModuleGraph}
1223+
loadGhcSession recorder def{fullModuleGraph}
11821224
getModIfaceFromDiskRule recorder
11831225
getModIfaceFromDiskAndIndexRule recorder
11841226
getModIfaceRule recorder
11851227
getModSummaryRule templateHaskellWarning recorder
11861228
getModuleGraphRule recorder
1229+
getFileHashRule recorder
11871230
knownFilesRule recorder
11881231
getClientSettingsRule recorder
11891232
getHieAstsRule recorder

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -1246,7 +1246,7 @@ defineEarlyCutoff' doDiagnostics cmp key file mbOld mode action = do
12461246
(mbBs, (diags, mbRes)) <- actionCatch
12471247
(do v <- action staleV; liftIO $ evaluate $ force v) $
12481248
\(e :: SomeException) -> do
1249-
pure (Nothing, ([ideErrorText file (T.pack $ show e) | not $ isBadDependency e],Nothing))
1249+
pure (Nothing, ([ideErrorText file (T.pack $ show (key, file) ++ show e) | not $ isBadDependency e],Nothing))
12501250

12511251
ver <- estimateFileVersionUnsafely key mbRes file
12521252
(bs, res) <- case mbRes of

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

+4
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ import qualified GHC.SysTools.Cpp as Pipeline
3434
import qualified GHC.SysTools.Tasks as Pipeline
3535
#endif
3636

37+
#if MIN_VERSION_ghc(9,11,0)
38+
import qualified GHC.SysTools.Tasks as Pipeline
39+
#endif
40+
3741
addOptP :: String -> DynFlags -> DynFlags
3842
addOptP f = alterToolSettings $ \s -> s
3943
{ toolSettings_opt_P = f : toolSettings_opt_P s

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

+18-2
Original file line numberDiff line numberDiff line change
@@ -338,17 +338,30 @@ type NameCacheUpdater = NameCache
338338

339339
mkHieFile' :: ModSummary
340340
-> [Avail.AvailInfo]
341+
#if MIN_VERSION_ghc(9,11,0)
342+
-> (HieASTs Type, NameEntityInfo)
343+
#else
341344
-> HieASTs Type
345+
#endif
342346
-> BS.ByteString
343347
-> Hsc HieFile
344-
mkHieFile' ms exports asts src = do
348+
mkHieFile' ms exports
349+
#if MIN_VERSION_ghc(9,11,0)
350+
(asts, entityInfo)
351+
#else
352+
asts
353+
#endif
354+
src = do
345355
let Just src_file = ml_hs_file $ ms_location ms
346356
(asts',arr) = compressTypes asts
347357
return $ HieFile
348358
{ hie_hs_file = src_file
349359
, hie_module = ms_mod ms
350360
, hie_types = arr
351361
, hie_asts = asts'
362+
#if MIN_VERSION_ghc(9,11,0)
363+
, hie_entity_infos = entityInfo
364+
#endif
352365
-- mkIfaceExports sorts the AvailInfos for stability
353366
, hie_exports = mkIfaceExports exports
354367
, hie_hs_src = src
@@ -444,13 +457,16 @@ data GhcVersion
444457
| GHC96
445458
| GHC98
446459
| GHC910
460+
| GHC912
447461
deriving (Eq, Ord, Show, Enum)
448462

449463
ghcVersionStr :: String
450464
ghcVersionStr = VERSION_ghc
451465

452466
ghcVersion :: GhcVersion
453-
#if MIN_VERSION_GLASGOW_HASKELL(9,10,0,0)
467+
#if MIN_VERSION_GLASGOW_HASKELL(9,12,0,0)
468+
ghcVersion = GHC912
469+
#elif MIN_VERSION_GLASGOW_HASKELL(9,10,0,0)
454470
ghcVersion = GHC910
455471
#elif MIN_VERSION_GLASGOW_HASKELL(9,8,0,0)
456472
ghcVersion = GHC98

0 commit comments

Comments
 (0)