Hannes Siebenhandl pushed to branch wip/fendor/stack-annotation-with-backtraces at Glasgow Haskell Compiler / GHC
Commits:
-
ff5cf2e5
by fendor at 2025-08-27T09:34:03+02:00
7 changed files:
- libraries/ghc-experimental/src/GHC/Stack/Annotation/Experimental.hs
- libraries/ghc-internal/ghc-internal.cabal.in
- libraries/ghc-internal/src/GHC/Internal/Exception/Backtrace.hs
- + libraries/ghc-internal/src/GHC/Internal/Stack/Annotation.hs
- libraries/ghc-internal/src/GHC/Internal/Stack/Decode.hs
- testsuite/tests/interface-stability/ghc-experimental-exports.stdout
- testsuite/tests/interface-stability/ghc-experimental-exports.stdout-mingw32
Changes:
| ... | ... | @@ -58,6 +58,7 @@ import Data.Typeable |
| 58 | 58 | import GHC.Exts
|
| 59 | 59 | import GHC.IO
|
| 60 | 60 | import GHC.Internal.Stack
|
| 61 | +import GHC.Internal.Stack.Annotation
|
|
| 61 | 62 | |
| 62 | 63 | -- Note [User-defined stack annotations for better stack traces]
|
| 63 | 64 | -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| ... | ... | @@ -127,31 +128,10 @@ import GHC.Internal.Stack |
| 127 | 128 | -- This means, right now, if you want to reliably capture stack frame annotations,
|
| 128 | 129 | -- in both pure and impure code, prefer 'throw' and 'throwIO' variants over 'error'.
|
| 129 | 130 | |
| 130 | --- ----------------------------------------------------------------------------
|
|
| 131 | --- StackAnnotation
|
|
| 132 | --- ----------------------------------------------------------------------------
|
|
| 133 | - |
|
| 134 | --- | 'StackAnnotation's are types which can be pushed onto the call stack
|
|
| 135 | --- as the payload of 'AnnFrame' stack frames.
|
|
| 136 | ---
|
|
| 137 | -class StackAnnotation a where
|
|
| 138 | - displayStackAnnotation :: a -> String
|
|
| 139 | - |
|
| 140 | 131 | -- ----------------------------------------------------------------------------
|
| 141 | 132 | -- Annotations
|
| 142 | 133 | -- ----------------------------------------------------------------------------
|
| 143 | 134 | |
| 144 | --- |
|
|
| 145 | --- The @SomeStackAnnotation@ type is the root of the stack annotation type hierarchy.
|
|
| 146 | --- When the call stack is annotated with a value of type @a@, behind the scenes it is
|
|
| 147 | --- encapsulated in a @SomeStackAnnotation@.
|
|
| 148 | ---
|
|
| 149 | -data SomeStackAnnotation where
|
|
| 150 | - SomeStackAnnotation :: forall a. (Typeable a, StackAnnotation a) => a -> SomeStackAnnotation
|
|
| 151 | - |
|
| 152 | -instance StackAnnotation SomeStackAnnotation where
|
|
| 153 | - displayStackAnnotation (SomeStackAnnotation a) = displayStackAnnotation a
|
|
| 154 | - |
|
| 155 | 135 | data StringAnnotation where
|
| 156 | 136 | StringAnnotation :: String -> StringAnnotation
|
| 157 | 137 | |
| ... | ... | @@ -175,7 +155,7 @@ instance Show CallStackAnnotation where |
| 175 | 155 | instance StackAnnotation CallStackAnnotation where
|
| 176 | 156 | displayStackAnnotation (CallStackAnnotation cs) = case getCallStack cs of
|
| 177 | 157 | [] -> "<unknown source location>"
|
| 178 | - ((_,srcLoc):_) -> prettySrcLoc srcLoc
|
|
| 158 | + ((fnName,srcLoc):_) -> fnName ++ ", called at " ++ prettySrcLoc srcLoc
|
|
| 179 | 159 | |
| 180 | 160 | -- ----------------------------------------------------------------------------
|
| 181 | 161 | -- Annotate the CallStack with custom data
|
| ... | ... | @@ -295,6 +295,7 @@ Library |
| 295 | 295 | GHC.Internal.Stable
|
| 296 | 296 | GHC.Internal.StableName
|
| 297 | 297 | GHC.Internal.Stack
|
| 298 | + GHC.Internal.Stack.Annotation
|
|
| 298 | 299 | GHC.Internal.Stack.CCS
|
| 299 | 300 | GHC.Internal.Stack.CloneStack
|
| 300 | 301 | GHC.Internal.Stack.Constants
|
| ... | ... | @@ -11,7 +11,7 @@ import GHC.Internal.IORef |
| 11 | 11 | import GHC.Internal.IO.Unsafe (unsafePerformIO)
|
| 12 | 12 | import GHC.Internal.Exception.Context
|
| 13 | 13 | import GHC.Internal.Ptr
|
| 14 | -import GHC.Internal.Data.Maybe (fromMaybe)
|
|
| 14 | +import GHC.Internal.Data.Maybe (fromMaybe, mapMaybe)
|
|
| 15 | 15 | import GHC.Internal.Stack.Types as GHC.Stack (CallStack, HasCallStack)
|
| 16 | 16 | import qualified GHC.Internal.Stack as HCS
|
| 17 | 17 | import qualified GHC.Internal.ExecutionStack.Internal as ExecStack
|
| ... | ... | @@ -144,7 +144,7 @@ displayBacktraces bts = concat |
| 144 | 144 | displayExec = unlines . map (indent 2 . flip ExecStack.showLocation "") . fromMaybe [] . ExecStack.stackFrames
|
| 145 | 145 | -- The unsafePerformIO here is safe as 'StackSnapshot' makes sure neither the stack frames nor
|
| 146 | 146 | -- references closures can be garbage collected.
|
| 147 | - displayIpe = unlines . map (indent 2 . CloneStack.prettyStackEntry) . unsafePerformIO . CloneStack.decode
|
|
| 147 | + displayIpe = unlines . mapMaybe (fmap (indent 2) . CloneStack.prettyStackFrameWithIpe) . unsafePerformIO . CloneStack.decodeStackWithIpe
|
|
| 148 | 148 | displayHsc = unlines . map (indent 2 . prettyCallSite) . HCS.getCallStack
|
| 149 | 149 | where prettyCallSite (f, loc) = f ++ ", called at " ++ HCS.prettySrcLoc loc
|
| 150 | 150 |
| 1 | +{-# LANGUAGE GADTs #-}
|
|
| 2 | +{-# LANGUAGE ScopedTypeVariables #-}
|
|
| 3 | +module GHC.Internal.Stack.Annotation where
|
|
| 4 | + |
|
| 5 | +import GHC.Internal.Base
|
|
| 6 | +import GHC.Internal.Data.Typeable
|
|
| 7 | + |
|
| 8 | +-- ----------------------------------------------------------------------------
|
|
| 9 | +-- StackAnnotation
|
|
| 10 | +-- ----------------------------------------------------------------------------
|
|
| 11 | + |
|
| 12 | +-- | 'StackAnnotation's are types which can be pushed onto the call stack
|
|
| 13 | +-- as the payload of 'AnnFrame' stack frames.
|
|
| 14 | +--
|
|
| 15 | +class StackAnnotation a where
|
|
| 16 | + displayStackAnnotation :: a -> String
|
|
| 17 | + |
|
| 18 | +-- ----------------------------------------------------------------------------
|
|
| 19 | +-- Annotations
|
|
| 20 | +-- ----------------------------------------------------------------------------
|
|
| 21 | + |
|
| 22 | +-- |
|
|
| 23 | +-- The @SomeStackAnnotation@ type is the root of the stack annotation type hierarchy.
|
|
| 24 | +-- When the call stack is annotated with a value of type @a@, behind the scenes it is
|
|
| 25 | +-- encapsulated in a @SomeStackAnnotation@.
|
|
| 26 | +--
|
|
| 27 | +data SomeStackAnnotation where
|
|
| 28 | + SomeStackAnnotation :: forall a. (Typeable a, StackAnnotation a) => a -> SomeStackAnnotation
|
|
| 29 | + |
|
| 30 | +instance StackAnnotation SomeStackAnnotation where
|
|
| 31 | + displayStackAnnotation (SomeStackAnnotation a) = displayStackAnnotation a |
| ... | ... | @@ -4,6 +4,7 @@ |
| 4 | 4 | {-# LANGUAGE FlexibleInstances #-}
|
| 5 | 5 | {-# LANGUAGE GHCForeignImportPrim #-}
|
| 6 | 6 | {-# LANGUAGE MagicHash #-}
|
| 7 | +{-# LANGUAGE NamedFieldPuns #-}
|
|
| 7 | 8 | {-# LANGUAGE RankNTypes #-}
|
| 8 | 9 | {-# LANGUAGE RecordWildCards #-}
|
| 9 | 10 | {-# LANGUAGE ScopedTypeVariables #-}
|
| ... | ... | @@ -23,6 +24,7 @@ module GHC.Internal.Stack.Decode ( |
| 23 | 24 | StackEntry(..),
|
| 24 | 25 | -- * Pretty printing
|
| 25 | 26 | prettyStackEntry,
|
| 27 | + prettyStackFrameWithIpe,
|
|
| 26 | 28 | )
|
| 27 | 29 | where
|
| 28 | 30 | |
| ... | ... | @@ -39,6 +41,7 @@ import GHC.Internal.Data.Tuple |
| 39 | 41 | import GHC.Internal.Foreign.Ptr
|
| 40 | 42 | import GHC.Internal.Foreign.Storable
|
| 41 | 43 | import GHC.Internal.Exts
|
| 44 | +import GHC.Internal.Unsafe.Coerce
|
|
| 42 | 45 | |
| 43 | 46 | import GHC.Internal.ClosureTypes
|
| 44 | 47 | import GHC.Internal.Heap.Closures
|
| ... | ... | @@ -52,6 +55,7 @@ import GHC.Internal.Heap.Closures |
| 52 | 55 | )
|
| 53 | 56 | import GHC.Internal.Heap.Constants (wORD_SIZE_IN_BITS)
|
| 54 | 57 | import GHC.Internal.Heap.InfoTable
|
| 58 | +import GHC.Internal.Stack.Annotation
|
|
| 55 | 59 | import GHC.Internal.Stack.Constants
|
| 56 | 60 | import GHC.Internal.Stack.CloneStack
|
| 57 | 61 | import GHC.Internal.InfoProv.Types (InfoProv (..), ipLoc, lookupIPE)
|
| ... | ... | @@ -560,6 +564,16 @@ decodeStackWithFrameUnpack unpackFrame (StackSnapshot stack#) = do |
| 560 | 564 | -- Pretty printing functions for stack entires, stack frames and provenance info
|
| 561 | 565 | -- ----------------------------------------------------------------------------
|
| 562 | 566 | |
| 567 | +prettyStackFrameWithIpe :: (StackFrame, Maybe InfoProv) -> Maybe String
|
|
| 568 | +prettyStackFrameWithIpe (frame, mipe) =
|
|
| 569 | + case frame of
|
|
| 570 | + AnnFrame {annotation = Box someStackAnno } ->
|
|
| 571 | + case unsafeCoerce someStackAnno of
|
|
| 572 | + SomeStackAnnotation ann ->
|
|
| 573 | + Just $ displayStackAnnotation ann
|
|
| 574 | + _ ->
|
|
| 575 | + (prettyStackEntry . toStackEntry) <$> mipe
|
|
| 576 | + |
|
| 563 | 577 | prettyStackEntry :: StackEntry -> String
|
| 564 | 578 | prettyStackEntry (StackEntry {moduleName=mod_nm, functionName=fun_nm, srcLoc=loc}) =
|
| 565 | 579 | mod_nm ++ "." ++ fun_nm ++ " (" ++ loc ++ ")" |
| ... | ... | @@ -10949,10 +10949,6 @@ module System.Mem.Experimental where |
| 10949 | 10949 | |
| 10950 | 10950 | |
| 10951 | 10951 | -- Instances:
|
| 10952 | -instance GHC.Stack.Annotation.Experimental.StackAnnotation GHC.Stack.Annotation.Experimental.CallStackAnnotation -- Defined in ‘GHC.Stack.Annotation.Experimental’
|
|
| 10953 | -instance GHC.Stack.Annotation.Experimental.StackAnnotation GHC.Stack.Annotation.Experimental.ShowAnnotation -- Defined in ‘GHC.Stack.Annotation.Experimental’
|
|
| 10954 | -instance GHC.Stack.Annotation.Experimental.StackAnnotation GHC.Stack.Annotation.Experimental.SomeStackAnnotation -- Defined in ‘GHC.Stack.Annotation.Experimental’
|
|
| 10955 | -instance GHC.Stack.Annotation.Experimental.StackAnnotation GHC.Stack.Annotation.Experimental.StringAnnotation -- Defined in ‘GHC.Stack.Annotation.Experimental’
|
|
| 10956 | 10952 | instance GHC.Internal.Base.Alternative GHC.Internal.Types.IO -- Defined in ‘GHC.Internal.Base’
|
| 10957 | 10953 | instance GHC.Internal.Base.Alternative [] -- Defined in ‘GHC.Internal.Base’
|
| 10958 | 10954 | instance GHC.Internal.Base.Alternative GHC.Internal.Maybe.Maybe -- Defined in ‘GHC.Internal.Base’
|
| ... | ... | @@ -11151,3 +11147,7 @@ instance GHC.Internal.Show.Show GHC.Internal.IO.SubSystem.IoSubSystem -- Defined |
| 11151 | 11147 | instance GHC.Internal.Show.Show GHC.Stack.Annotation.Experimental.CallStackAnnotation -- Defined in ‘GHC.Stack.Annotation.Experimental’
|
| 11152 | 11148 | instance GHC.Internal.Show.Show GHC.Internal.Stats.GCDetails -- Defined in ‘GHC.Internal.Stats’
|
| 11153 | 11149 | instance GHC.Internal.Show.Show GHC.Internal.Stats.RTSStats -- Defined in ‘GHC.Internal.Stats’
|
| 11150 | +instance GHC.Internal.Stack.Annotation.StackAnnotation GHC.Stack.Annotation.Experimental.CallStackAnnotation -- Defined in ‘GHC.Stack.Annotation.Experimental’
|
|
| 11151 | +instance GHC.Internal.Stack.Annotation.StackAnnotation GHC.Stack.Annotation.Experimental.ShowAnnotation -- Defined in ‘GHC.Stack.Annotation.Experimental’
|
|
| 11152 | +instance GHC.Internal.Stack.Annotation.StackAnnotation GHC.Stack.Annotation.Experimental.StringAnnotation -- Defined in ‘GHC.Stack.Annotation.Experimental’
|
|
| 11153 | +instance GHC.Internal.Stack.Annotation.StackAnnotation GHC.Internal.Stack.Annotation.SomeStackAnnotation -- Defined in ‘GHC.Internal.Stack.Annotation’
|
| ... | ... | @@ -10952,10 +10952,6 @@ module System.Mem.Experimental where |
| 10952 | 10952 | |
| 10953 | 10953 | |
| 10954 | 10954 | -- Instances:
|
| 10955 | -instance GHC.Stack.Annotation.Experimental.StackAnnotation GHC.Stack.Annotation.Experimental.CallStackAnnotation -- Defined in ‘GHC.Stack.Annotation.Experimental’
|
|
| 10956 | -instance GHC.Stack.Annotation.Experimental.StackAnnotation GHC.Stack.Annotation.Experimental.ShowAnnotation -- Defined in ‘GHC.Stack.Annotation.Experimental’
|
|
| 10957 | -instance GHC.Stack.Annotation.Experimental.StackAnnotation GHC.Stack.Annotation.Experimental.SomeStackAnnotation -- Defined in ‘GHC.Stack.Annotation.Experimental’
|
|
| 10958 | -instance GHC.Stack.Annotation.Experimental.StackAnnotation GHC.Stack.Annotation.Experimental.StringAnnotation -- Defined in ‘GHC.Stack.Annotation.Experimental’
|
|
| 10959 | 10955 | instance GHC.Internal.Base.Alternative GHC.Internal.Types.IO -- Defined in ‘GHC.Internal.Base’
|
| 10960 | 10956 | instance GHC.Internal.Base.Alternative [] -- Defined in ‘GHC.Internal.Base’
|
| 10961 | 10957 | instance GHC.Internal.Base.Alternative GHC.Internal.Maybe.Maybe -- Defined in ‘GHC.Internal.Base’
|
| ... | ... | @@ -11154,3 +11150,7 @@ instance GHC.Internal.Show.Show GHC.Internal.IO.SubSystem.IoSubSystem -- Defined |
| 11154 | 11150 | instance GHC.Internal.Show.Show GHC.Stack.Annotation.Experimental.CallStackAnnotation -- Defined in ‘GHC.Stack.Annotation.Experimental’
|
| 11155 | 11151 | instance GHC.Internal.Show.Show GHC.Internal.Stats.GCDetails -- Defined in ‘GHC.Internal.Stats’
|
| 11156 | 11152 | instance GHC.Internal.Show.Show GHC.Internal.Stats.RTSStats -- Defined in ‘GHC.Internal.Stats’
|
| 11153 | +instance GHC.Internal.Stack.Annotation.StackAnnotation GHC.Stack.Annotation.Experimental.CallStackAnnotation -- Defined in ‘GHC.Stack.Annotation.Experimental’
|
|
| 11154 | +instance GHC.Internal.Stack.Annotation.StackAnnotation GHC.Stack.Annotation.Experimental.ShowAnnotation -- Defined in ‘GHC.Stack.Annotation.Experimental’
|
|
| 11155 | +instance GHC.Internal.Stack.Annotation.StackAnnotation GHC.Stack.Annotation.Experimental.StringAnnotation -- Defined in ‘GHC.Stack.Annotation.Experimental’
|
|
| 11156 | +instance GHC.Internal.Stack.Annotation.StackAnnotation GHC.Internal.Stack.Annotation.SomeStackAnnotation -- Defined in ‘GHC.Internal.Stack.Annotation’
|