packages feed

ghc-stack-annotations-0.2.0.0: src/GHC/Stack/Annotation/Compat/Class.hs

{-# LANGUAGE CPP #-}
module GHC.Stack.Annotation.Compat.Class (
  StackAnnotation(..),
  SomeStackAnnotation(..),
  CompatAnnotation(..),
  ) where

#include "macros.h"

import Data.Typeable ( Typeable )

#if defined(SUPPORT_STACK_ANN_SRCLOC)
import GHC.Stack.Annotation.Experimental (StackAnnotation(..), SomeStackAnnotation(..))
import qualified GHC.Stack.Annotation.Experimental as Annotation
#elif defined(SUPPORT_STACK_ANN)
import GHC.Stack.Annotation.Experimental (SomeStackAnnotation(..))
import qualified GHC.Stack.Annotation.Experimental as Annotation
import GHC.Stack (SrcLoc, prettySrcLoc)
#else
import GHC.Stack (SrcLoc, prettySrcLoc)
#endif

-- The following source code is a partial copy of ghc-internal:
--  GHC.Internal.Stack.Annotation
-- It copies the `StackAnnotation` type class and its documentation.
--
-- As such, we reproduce the copyright notice here.

-- Copyright (c) 2023, ghc-devs@haskell.org
--
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
--     * Redistributions of source code must retain the above copyright
--       notice, this list of conditions and the following disclaimer.
--
--     * Redistributions in binary form must reproduce the above
--       copyright notice, this list of conditions and the following
--       disclaimer in the documentation and/or other materials provided
--       with the distribution.
--
--     * Neither the name of ghc-devs@haskell.org nor the names of other
--       contributors may be used to endorse or promote products derived
--       from this software without specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-- OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


#if !defined(SUPPORT_STACK_ANN_LATEST)
-- | 'StackAnnotation's are types which can be pushed onto the call stack
-- as the payload of 'AnnFrame' stack frames.
--
class StackAnnotation a where
  -- | Display a human readable string for the 'StackAnnotation'.
  --
  -- This is supposed to be the long version of 'displayStackAnnotationShort'
  -- and may contain a source location.
  --
  -- If not provided, 'displayStackAnnotation' is derived from 'stackAnnotationSourceLocation'
  -- and 'displayStackAnnotationShort'.
  displayStackAnnotation :: a -> String

  -- | Get the 'SrcLoc' of the given 'StackAnnotation'.
  --
  -- This is optional, 'SrcLoc' are not strictly required for 'StackAnnotation', but
  -- it is still heavily encouraged to provide a 'SrcLoc' for better IPE backtraces.
  stackAnnotationSourceLocation :: a -> Maybe SrcLoc

  -- | The description of the StackAnnotation without any metadata such as source locations.
  --
  -- Prefer implementing 'displayStackAnnotationShort' over 'displayStackAnnotation'.
  displayStackAnnotationShort :: a -> String

  {-# MINIMAL displayStackAnnotation | displayStackAnnotationShort #-}

  displayStackAnnotation ann =
    displayStackAnnotationShort ann
      ++ case stackAnnotationSourceLocation ann of
          Nothing -> ""
          Just srcLoc -> ", called at " ++ prettySrcLoc srcLoc

  stackAnnotationSourceLocation _ann = Nothing

  displayStackAnnotationShort = displayStackAnnotation
#endif


-- Only define this is, if `ghc-experimental` doesn't define it already. Otherwise, just re-export it.

#if !defined(SUPPORT_STACK_ANN)
-- |
-- The @SomeStackAnnotation@ type is the root of the stack annotation type hierarchy.
-- When the call stack is annotated with a value of type @a@, behind the scenes it is
-- encapsulated in a @SomeStackAnnotation@.
--
data SomeStackAnnotation where
  SomeStackAnnotation :: forall a. (Typeable a, StackAnnotation a) => a -> SomeStackAnnotation
#endif

#if defined(SUPPORT_STACK_ANN_LATEST)
{- No instance needed -}
#elif defined(SUPPORT_STACK_ANN_SRCLOC)
instance StackAnnotation SomeStackAnnotation where
  displayStackAnnotation (SomeStackAnnotation ann) =
    Annotation.displayStackAnnotation ann
  stackAnnotationSourceLocation (SomeStackAnnotation ann) =
    Annotation.stackAnnotationSourceLocation ann
  displayStackAnnotationShort (SomeStackAnnotation ann) =
    Annotation.displayStackAnnotationShort ann
#elif defined(SUPPORT_STACK_ANN)
instance StackAnnotation SomeStackAnnotation where
  displayStackAnnotation (SomeStackAnnotation ann) =
    Annotation.displayStackAnnotation ann
#else
instance StackAnnotation SomeStackAnnotation where
  displayStackAnnotation (SomeStackAnnotation ann) =
    displayStackAnnotation ann
  stackAnnotationSourceLocation (SomeStackAnnotation ann) =
    stackAnnotationSourceLocation ann
  displayStackAnnotationShort (SomeStackAnnotation ann) =
    displayStackAnnotationShort ann
#endif

-- ----------------------------------------------------------------------------
-- Backwards compatibility wrapper
-- ----------------------------------------------------------------------------

-- | A newtype that bridges the locally defined 'StackAnnotation' to GHC's 'ghc-experimental:StackAnnotation'.
--
newtype CompatAnnotation a = CompatAnnotation a

#if defined(SUPPORT_STACK_ANN)
instance (Typeable a, StackAnnotation a) => Annotation.StackAnnotation (CompatAnnotation a) where
  displayStackAnnotation (CompatAnnotation a) =
    displayStackAnnotation a
#if defined(SUPPORT_STACK_ANN_SRCLOC)
  stackAnnotationSourceLocation (CompatAnnotation a) =
    stackAnnotationSourceLocation a
  displayStackAnnotationShort (CompatAnnotation a) =
    displayStackAnnotationShort a
#endif
#endif