Pattern synonyms in call stacks
Summary
When combining pattern synonyms, view patterns and GHC call stacks, the use site of the pattern synonym doesn't appear in the call stack, but any functions called through view patterns will still show up as called from within the pattern synonym. This makes it impossible to extract the source location of where the (explicitly-bidirectional) pattern synonym was used from the call stack.
The use case for having this information available would be to annotate an abstract syntax tree for an embedded language with source mapping information. We're using an explicitly bidirectional pattern synonym to construct tuples, and also to extract values from existing tuples by using view patterns to generate projection AST nodes for every element in the tuple.
Steps to reproduce
Below is a stripped down version of the pattern described above:
Main.hs
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE ViewPatterns #-}
module Main where
import GHC.Stack
-- | Some useless pattern synonym that groups a value with the call stack using
-- view patterns. In the real code base where I'm using this this pattern
-- synonym generates part of an abstract syntax tree instead.
pattern Annotated :: HasCallStack => (CallStack, a) -> a
pattern Annotated x <- (addCallStack -> x)
where
Annotated (_, x) = x
-- | Used in 'Annotated' to pair a value with the current call stack, since
-- you cannot add the 'HasCallStack' constraint to a lambda (in the real use
-- case we would be calling a function that does something with the call stack
-- here).
addCallStack :: HasCallStack => a -> (CallStack, a)
addCallStack x = (callStack, x)
someAnnotatedValue :: (CallStack, Int)
someAnnotatedValue = let Annotated annotated = 10 in annotated
main :: IO ()
main = do
let (stack, _) = someAnnotatedValue
putStrLn "No lines from within 'someAnnotatedValue' (i.e. line 24) will show up here:"
putStrLn $ prettyCallStack stack
Running this with either GHC 8.10.3 or the GHC 9.0.0.20201227 release candidate prints the following:
No lines from within 'someAnnotatedValue' (i.e. line 24) will show up here:
CallStack (from HasCallStack):
addCallStack, called at Main.hs:12:25 in main:Main
Expected behavior
I'd expect either the use of the pattern synonym to show up in the call stack,
or I'd expect the pattern synonym to be inlined and the call to addCallStack
to show up as if it were originating from someAnnotatedValue
(i.e. from
Main.hs:24:25
).
If this behaviour is intentional or an unavoidable consequence of how pattern
synonyms are implemented, is there any other way to find out where Annotated
was used from?
Environment
- GHC version used: GHC 8.10.3 and 9.0.0.20201227 from ghcup
Optional:
- Operating System: Manjaro Linux
- System Architecture: x86_64