Skip to content

Commit 72b3698

Browse files
jimbob88waddlaw
andauthored
Add support for GHC 9-9.12 (#20)
* wip * wip * wip * wip * fix: replace HsIB with HsSig on GHC >= 9.2 * fix: add back pass to module on ghc >= 9.6 * fix: plugin function for ghc >= 9.4.0 * fix: stack import on ghc >= 9 (location replaced by xrec) * fix: src span on ghc >= 9.10 (requires strict maybe) * fix: ghc stack import type on ghc >= 9 * fix: ghc stack import location * fix: update l matches (replace location with xrec) * style: make update l matches point free * fix: grhss local binds no longer located * fix: update l sigs (use xrec instead of located) * fix: lhssigtype wraps hssigtype * fix: replace noLoc with emptyLoc * fix: for 9.6, 9,8, 9.10 * fix: ghc 9.12 support * fix: don't build superfluous function on ghc >= 9 * build: bump supported ghc versions * fix: strict maybe in ghc 9.4 * build: bump tested ghc 9.4 version * refactor: move qualification into separate function --------- Co-authored-by: waddlaw <ingronze@gmail.com>
1 parent 0ccb73e commit 72b3698

File tree

3 files changed

+127
-30
lines changed

3 files changed

+127
-30
lines changed

.github/workflows/cabal.yml

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,29 @@ name: cabal
22

33
on:
44
push:
5-
branches: [ master ]
5+
branches: [ main ]
66
pull_request:
77
branches: [ '*' ]
8-
schedule:
9-
- cron: "00 15 * * *"
108

119
jobs:
1210
build:
13-
runs-on: ubuntu-18.04
11+
runs-on: ubuntu-20.04
1412
strategy:
13+
fail-fast: false
1514
matrix:
16-
ghc: ["8.6", "8.8", "8.10", "9.0"]
17-
cabal: ["3.2"]
18-
cache-version: ["2021-05-21"]
15+
ghc: ["8.6", "8.8", "8.10", "9.0", "9.2", "9.4"]
16+
cabal: ["3.6"]
17+
cache-version: ["2022-10-25"]
1918

2019
steps:
2120
- uses: actions/checkout@v2
22-
- uses: haskell/actions/setup@v1
21+
- uses: haskell/actions/setup@v2
2322
with:
2423
ghc-version: ${{ matrix.ghc }}
2524
cabal-version: ${{ matrix.cabal }}
2625

2726
- name: Cache ~/.cabal/store
28-
uses: actions/cache@v2
27+
uses: actions/cache@v3
2928
with:
3029
path: |
3130
~/.cabal/store

haskell-stack-trace-plugin.cabal

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,14 @@ license: MIT
1313
license-file: LICENSE
1414
author: Shinya Yamaguchi
1515
maintainer: a@wado.dev
16-
copyright: 2018-2021 Shinya Yamaguchi
16+
copyright: 2018-2022 Shinya Yamaguchi
1717
category: Compiler Plugin, Development, Debug
1818
build-type: Simple
1919
extra-source-files:
2020
CHANGELOG.md
2121
Readme.md
2222

23-
tested-with: GHC ==8.6.5 || ==8.8.4 || ==8.10.4 || ==9.0.1
23+
tested-with: GHC ==8.6.5 || ==8.8.4 || ==8.10.7 || ==9.0.2 || ==9.2.4 || ==9.4.8 || ==9.6.6 || ==9.8.4 || ==9.10.1 || ==9.12.1
2424

2525
source-repository head
2626
type: git
@@ -32,13 +32,13 @@ flag dev
3232
default: False
3333

3434
common common-opts
35-
build-depends: base >=4.12 && <4.16
35+
build-depends: base >=4.12 && <4.22
3636
default-language: Haskell2010
3737

3838
library
3939
import: common-opts
4040
hs-source-dirs: src
41-
build-depends: ghc ^>=8.6 || ^>=8.8 || ^>=8.10 || ^>=9.0
41+
build-depends: ghc ^>=8.6 || ^>=8.8 || ^>=8.10 || ^>=9.0 || ^>=9.2 || ^>=9.4 || ^>=9.6 || ^>=9.8 || ^>=9.10 || ^>=9.12
4242
exposed-modules: StackTrace.Plugin
4343

4444
if flag(dev)

src/StackTrace/Plugin.hs

Lines changed: 115 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,68 @@
11
{-# LANGUAGE RankNTypes #-}
22
{-# LANGUAGE OverloadedStrings #-}
33
{-# LANGUAGE CPP #-}
4+
{-# LANGUAGE FlexibleContexts #-}
45
module StackTrace.Plugin (plugin) where
56

67
import Control.Arrow (first)
78
import Data.Monoid (Any(Any, getAny))
8-
import GHC.Types.SrcLoc
9+
910
#if __GLASGOW_HASKELL__ >= 900
1011
import GHC.Plugins
1112
#else
12-
1313
import GhcPlugins
1414
#endif
15+
1516
#if __GLASGOW_HASKELL__ >= 810
1617
import GHC.Hs
1718
#endif
19+
1820
#if __GLASGOW_HASKELL__ < 810
1921
import HsSyn
2022
#endif
2123

24+
-- srcSpan now requires strict maybe
25+
#if __GLASGOW_HASKELL__ >= 904
26+
import GHC.Data.Strict as Strict (Maybe (Nothing))
27+
#endif
28+
2229
type Traversal s t a b
2330
= forall f. Applicative f =>
2431
(a -> f b) -> s -> f t
2532

2633
type Traversal' s a = Traversal s s a a
2734

35+
#if __GLASGOW_HASKELL__ < 900
36+
emptyLoc :: e -> Located e
37+
emptyLoc = noLoc
38+
#elif __GLASGOW_HASKELL__ < 910
39+
emptyLoc :: a -> LocatedAn an a
40+
emptyLoc = noLocA
41+
#else
42+
emptyLoc :: (HasAnnotation b) => e -> GenLocated b e
43+
emptyLoc = reLoc . noLoc
44+
#endif
45+
2846
plugin :: Plugin
2947
plugin = defaultPlugin {parsedResultAction = parsedPlugin, pluginRecompile = purePlugin}
3048

49+
#if __GLASGOW_HASKELL__ < 904
3150
parsedPlugin ::
3251
[CommandLineOption] -> ModSummary -> HsParsedModule -> Hsc HsParsedModule
3352
parsedPlugin _ _ pm = do
3453
let m = updateHsModule <$> hpm_module pm
3554
pm' = pm {hpm_module = m}
3655
return pm'
56+
#else
57+
parsedPlugin ::
58+
[CommandLineOption] -> ModSummary -> ParsedResult -> Hsc ParsedResult
59+
parsedPlugin _ _ pr = do
60+
let pm = parsedResultModule pr
61+
m = updateHsModule <$> hpm_module pm
62+
pm' = pm {hpm_module = m}
63+
return pr {parsedResultModule = pm'}
64+
#endif
65+
3766

3867
-- Use qualified import for GHC.Stack as "AutoImported.GHC.Stack"
3968
-- ...this should not interfere with other imports...
@@ -48,18 +77,42 @@ importDeclQualified :: ImportDeclQualifiedStyle
4877
importDeclQualified = QualifiedPre
4978
#endif
5079

51-
ghcStackImport :: Located (ImportDecl (GhcPass p))
80+
81+
#if __GLASGOW_HASKELL__ < 900
82+
ghcStackImport :: Located (ImportDecl GhcPs)
5283
ghcStackImport =
5384
L srcSpan $
5485
(simpleImportDecl $ mkModuleName "GHC.Stack")
55-
{ ideclQualified = importDeclQualified, ideclAs = Just $ noLoc ghcStackModuleName }
86+
{ ideclQualified = importDeclQualified, ideclAs = ideclAs' }
5687
where
88+
ideclAs' = Just $ noLoc ghcStackModuleName
89+
srcSpan = RealSrcSpan (realSrcLocSpan $ mkRealSrcLoc "haskell-stack-trace-plugin:very-unique-file-name-to-avoid-collision" 1 1)
90+
#else
91+
ghcStackImport :: LImportDecl GhcPs
92+
ghcStackImport =
93+
reLoc' $ L srcSpan $
94+
(simpleImportDecl $ mkModuleName "GHC.Stack")
95+
{ ideclQualified = importDeclQualified, ideclAs = ideclAs' }
96+
where
97+
ideclAs' = Just $ emptyLoc ghcStackModuleName
98+
99+
#if __GLASGOW_HASKELL__ >= 910
100+
reLoc' = reLoc
101+
#else
102+
reLoc' = reLocA
103+
#endif
104+
57105
-- This is for GHC-9 related problems. @noLoc@ causes GHC to throw warnings
58106
-- about unused imports. Even if the import is used
59107
-- See: https://github.com/waddlaw/haskell-stack-trace-plugin/issues/16
108+
#if __GLASGOW_HASKELL__ >= 904
109+
srcSpan = RealSrcSpan (realSrcLocSpan $ mkRealSrcLoc "haskell-stack-trace-plugin:very-unique-file-name-to-avoid-collision" 1 1) Strict.Nothing
110+
#else
60111
srcSpan = RealSrcSpan (realSrcLocSpan $ mkRealSrcLoc "haskell-stack-trace-plugin:very-unique-file-name-to-avoid-collision" 1 1) Nothing
112+
#endif
113+
#endif
61114

62-
#if __GLASGOW_HASKELL__ >= 900
115+
#if __GLASGOW_HASKELL__ >= 900 && __GLASGOW_HASKELL__ < 906
63116
updateHsModule :: HsModule -> HsModule
64117
#else
65118
updateHsModule :: HsModule GhcPs -> HsModule GhcPs
@@ -108,14 +161,25 @@ updateMatchGroup f mg@MG {} = (\x -> mg {mg_alts = x}) <$> updateLLMatch f (mg_a
108161
updateMatchGroup _ mg = pure mg
109162
#endif
110163

164+
#if __GLASGOW_HASKELL__ < 900
111165
updateLocated :: Functor f => (a -> b -> f c) -> a -> Located b -> f (Located c)
112166
updateLocated f g (L l e) = L l <$> f g e
167+
#endif
113168

169+
#if __GLASGOW_HASKELL__ < 900
114170
updateLLMatch :: Traversal' (Located [LMatch GhcPs (LHsExpr GhcPs)]) (LHsSigWcType GhcPs)
115171
updateLLMatch = updateLocated updateLMatches
172+
#else
173+
updateLLMatch :: Traversal' (XRec GhcPs [LMatch GhcPs (LHsExpr GhcPs)]) (LHsSigWcType GhcPs)
174+
updateLLMatch = traverse . updateLMatches
175+
#endif
116176

117177
updateLMatches :: Traversal' [LMatch GhcPs (LHsExpr GhcPs)] (LHsSigWcType GhcPs)
178+
#if __GLASGOW_HASKELL__ < 900
118179
updateLMatches f = traverse (updateLocated updateMatch f)
180+
#else
181+
updateLMatches = traverse . traverse . updateMatch
182+
#endif
119183

120184
updateMatch :: Traversal' (Match GhcPs (LHsExpr GhcPs)) (LHsSigWcType GhcPs)
121185
updateMatch f m@Match {} = (\x -> m {m_grhss = x}) <$> updateGrhss f (m_grhss m)
@@ -124,13 +188,17 @@ updateMatch _ m = pure m
124188
#endif
125189

126190
updateGrhss :: Traversal' (GRHSs GhcPs (LHsExpr GhcPs)) (LHsSigWcType GhcPs)
127-
updateGrhss f grhss@GRHSs {} = (\x -> grhss {grhssLocalBinds = x}) <$> updateLHsLocalBinds f (grhssLocalBinds grhss)
128191
#if __GLASGOW_HASKELL__ < 900
192+
updateGrhss f grhss@GRHSs {} = (\x -> grhss {grhssLocalBinds = x}) <$> updateLHsLocalBinds f (grhssLocalBinds grhss)
129193
updateGrhss _ grhss = pure grhss
194+
#else
195+
updateGrhss f grhss = (\x -> grhss {grhssLocalBinds = x}) <$> updateLocalBinds f (grhssLocalBinds grhss)
130196
#endif
131197

198+
#if __GLASGOW_HASKELL__ < 900
132199
updateLHsLocalBinds :: Traversal' (LHsLocalBinds GhcPs) (LHsSigWcType GhcPs)
133200
updateLHsLocalBinds = updateLocated updateLocalBinds
201+
#endif
134202

135203
updateLocalBinds :: Traversal' (HsLocalBinds GhcPs) (LHsSigWcType GhcPs)
136204
updateLocalBinds f (HsValBinds xHsValBinds hsValBindsLR) = HsValBinds xHsValBinds <$> updateHsValBindsLR f hsValBindsLR
@@ -141,7 +209,11 @@ updateHsValBindsLR f (ValBinds xValBinds lHsBindsLR lSigs) = ValBinds xValBinds
141209
updateHsValBindsLR _ valBinds = pure valBinds
142210

143211
updateLSigs :: Traversal' [LSig GhcPs] (LHsSigWcType GhcPs)
212+
#if __GLASGOW_HASKELL__ < 900
144213
updateLSigs f = traverse (updateLocated updateSig f)
214+
#else
215+
updateLSigs = traverse . traverse . updateSig
216+
#endif
145217

146218
updateSig :: Traversal' (Sig GhcPs) (LHsSigWcType GhcPs)
147219
updateSig f (TypeSig xSig ls t) = TypeSig xSig ls <$> f t
@@ -155,31 +227,40 @@ updateLHsSigWsType _ lhs = pure lhs
155227
#endif
156228

157229
updateLHsSigType :: Traversal' (LHsSigType GhcPs) (LHsType GhcPs)
230+
#if __GLASGOW_HASKELL__ >= 902
231+
updateLHsSigType = traverse . updateHsSigType
232+
#else
158233
updateLHsSigType f lhs@HsIB {} =
159234
(\x -> lhs {hsib_body = x}) <$> f (hsib_body lhs)
235+
#endif
160236
#if __GLASGOW_HASKELL__ < 900
161237
updateLHsSigType _ lhs = pure lhs
162238
#endif
163239

240+
241+
#if __GLASGOW_HASKELL__ >= 902
242+
updateHsSigType :: Traversal' (HsSigType GhcPs) (LHsType GhcPs)
243+
updateHsSigType f hs@HsSig {} = (\x -> hs {sig_body = x}) <$> f (sig_body hs)
244+
#endif
164245
updateLHsType :: Traversal' (LHsType GhcPs) (HsType GhcPs)
165246
updateLHsType = traverse
166247

248+
-- | Wraps an HsType with a HasStackCall qualifier
249+
wrapInQualTy :: HsType GhcPs -> (Any, HsType GhcPs)
250+
wrapInQualTy ty =
251+
flagASTModified $ HsQualTy xQualTy (emptyLoc $ appendHSC []) (emptyLoc ty)
252+
167253
-- Main process
168254
updateHsType :: HsType GhcPs -> (Any, HsType GhcPs)
169255
updateHsType ty@(HsQualTy xty ctxt body) =
170256
if hasHasCallStack (unLoc ctxt)
171257
then pure ty
172258
else flagASTModified $ HsQualTy xty (fmap appendHSC ctxt) body
173-
updateHsType ty@HsTyVar {} =
174-
flagASTModified $ HsQualTy xQualTy (noLoc $ appendHSC []) (noLoc ty)
175-
updateHsType ty@HsAppTy {} =
176-
flagASTModified $ HsQualTy xQualTy (noLoc $ appendHSC []) (noLoc ty)
177-
updateHsType ty@HsFunTy {} =
178-
flagASTModified $ HsQualTy xQualTy (noLoc $ appendHSC []) (noLoc ty)
179-
updateHsType ty@HsListTy {} =
180-
flagASTModified $ HsQualTy xQualTy (noLoc $ appendHSC []) (noLoc ty)
181-
updateHsType ty@HsTupleTy {} =
182-
flagASTModified $ HsQualTy xQualTy (noLoc $ appendHSC []) (noLoc ty)
259+
updateHsType ty@HsTyVar {} = wrapInQualTy ty
260+
updateHsType ty@HsAppTy {} = wrapInQualTy ty
261+
updateHsType ty@HsFunTy {} = wrapInQualTy ty
262+
updateHsType ty@HsListTy {} = wrapInQualTy ty
263+
updateHsType ty@HsTupleTy {} = wrapInQualTy ty
183264
updateHsType ty = pure ty
184265

185266
#if __GLASGOW_HASKELL__ < 810
@@ -203,9 +284,26 @@ hasHasCallStack = any (checkHsType . unLoc)
203284
checkHsType (HsTyVar _ _ lid) = unLoc lid == (mkRdrUnqual $ mkClsOcc "HasCallStack")
204285
checkHsType _ = False
205286

287+
xTyVar :: XTyVar GhcPs
288+
#if __GLASGOW_HASKELL__ >= 912
289+
xTyVar = NoEpTok
290+
#elif __GLASGOW_HASKELL__ >= 910
291+
xTyVar = []
292+
#elif __GLASGOW_HASKELL__ >= 900
293+
xTyVar = noAnn
294+
#else
295+
xTyVar = xQualTy
296+
#endif
297+
206298
-- make HasCallStack => constraint
207299
mkHSC :: LHsType GhcPs
208-
mkHSC = noLoc $ HsTyVar xQualTy NotPromoted lId
300+
mkHSC = emptyLoc $ HsTyVar xTyVar NotPromoted lId
301+
209302

303+
#if __GLASGOW_HASKELL__ < 900
210304
lId :: Located (IdP GhcPs)
211305
lId = noLoc $ mkRdrQual ghcStackModuleName $ mkClsOcc "HasCallStack"
306+
#else
307+
lId :: LIdP GhcPs
308+
lId = emptyLoc $ mkRdrQual ghcStackModuleName $ mkClsOcc "HasCallStack"
309+
#endif

0 commit comments

Comments
 (0)