{-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE DefaultSignatures #-} {-# LANGUAGE ExistentialQuantification #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE GADTs #-} {-# OPTIONS_HADDOCK not-home #-} ----------------------------------------------------------------------------- -- | -- Module : GHC.Internal.Exception.Context -- Copyright : (c) The University of Glasgow, 1998-2002 -- License : see libraries/base/LICENSE -- -- Maintainer : cvs-ghc@haskell.org -- Stability : internal -- Portability : non-portable (GHC extensions) -- -- Exception context type. -- ----------------------------------------------------------------------------- module GHC.Internal.Exception.Context ( -- * Exception context ExceptionContext(..) , emptyExceptionContext , addExceptionAnnotation , getExceptionAnnotations , getAllExceptionAnnotations , mergeExceptionContext , displayExceptionContext -- * Exception annotations , SomeExceptionAnnotation(..) , ExceptionAnnotation(..) ) where import GHC.Internal.Base ((++), return, String, Maybe(..), Semigroup(..), Monoid(..)) import GHC.Internal.Show (Show(..)) import GHC.Internal.Data.Typeable.Internal (Typeable, typeRep, eqTypeRep) import GHC.Internal.Data.Type.Equality ( (:~~:)(HRefl) ) -- | Exception context represents a list of 'ExceptionAnnotation's. These are -- attached to 'SomeException's via 'Control.Exception.addExceptionContext' and -- can be used to capture various ad-hoc metadata about the exception including -- backtraces and application-specific context. -- -- 'ExceptionContext's can be merged via concatenation using the 'Semigroup' -- instance or 'mergeExceptionContext'. -- -- Note that GHC will automatically solve implicit constraints of type 'ExceptionContext' -- with 'emptyExceptionContext'. data ExceptionContext = ExceptionContext [SomeExceptionAnnotation] instance Semigroup ExceptionContext where (<>) = mergeExceptionContext instance Monoid ExceptionContext where mempty = emptyExceptionContext -- | An 'ExceptionContext' containing no annotations. -- -- @since base-4.20.0.0 emptyExceptionContext :: ExceptionContext emptyExceptionContext = ExceptionContext [] -- | Construct a singleton 'ExceptionContext' from an 'ExceptionAnnotation'. -- -- @since base-4.20.0.0 addExceptionAnnotation :: ExceptionAnnotation a => a -> ExceptionContext -> ExceptionContext addExceptionAnnotation x (ExceptionContext xs) = ExceptionContext (SomeExceptionAnnotation x : xs) -- | Retrieve all 'ExceptionAnnotation's of the given type from an 'ExceptionContext'. -- -- @since base-4.20.0.0 getExceptionAnnotations :: forall a. ExceptionAnnotation a => ExceptionContext -> [a] getExceptionAnnotations (ExceptionContext xs) = [ x | SomeExceptionAnnotation (x :: b) <- xs , Just HRefl <- return (typeRep @a `eqTypeRep` typeRep @b) ] getAllExceptionAnnotations :: ExceptionContext -> [SomeExceptionAnnotation] getAllExceptionAnnotations (ExceptionContext xs) = xs -- | Merge two 'ExceptionContext's via concatenation -- -- @since base-4.20.0.0 mergeExceptionContext :: ExceptionContext -> ExceptionContext -> ExceptionContext mergeExceptionContext (ExceptionContext a) (ExceptionContext b) = ExceptionContext (a ++ b) -- | Render 'ExceptionContext' to a human-readable 'String'. -- -- @since base-4.20.0.0 displayExceptionContext :: ExceptionContext -> String displayExceptionContext (ExceptionContext anns0) = go anns0 where go (SomeExceptionAnnotation ann : anns) = displayExceptionAnnotation ann ++ "\n" ++ go anns go [] = "\n" data SomeExceptionAnnotation = forall a. ExceptionAnnotation a => SomeExceptionAnnotation a -- | 'ExceptionAnnotation's are types which can decorate exceptions as -- 'ExceptionContext'. -- -- @since base-4.20.0.0 class (Typeable a) => ExceptionAnnotation a where -- | Render the annotation for display to the user. displayExceptionAnnotation :: a -> String default displayExceptionAnnotation :: Show a => a -> String displayExceptionAnnotation = show