TTG: Handling Source Locations

Vladislav Zavialov vladislav at serokell.io
Tue Feb 12 12:32:11 UTC 2019


> One way to think of it is this: we can now put SrcSpans where they make sense, rather than everywhere.

I claim an SrcSpan makes sense everywhere, so this is not a useful
distinction. Think about it as code provenance, an AST node always
comes from somewhere: a user-written .hs file, a GHCi command, or
compiler-generated code (via TH or deriving). We should never omit
this information from a node.

And when we are writing code that consumes an AST, it always makes
sense to ask what the provenance of a node is, for example to use it
in an error message.

> this lets us add more than one; that's redundant but not harmful

It goes against the philosophy of making illegal states
irrepresentable. Now all code must be careful not to end up in an
illegal state of nested SrcSpan, without any help from the
typechecker.

The code that pattern matches on an AST, at the same time, must be
prepared to handle this case anyway (or else we risk to crash), which
it currently does with stripSrcSpanPat in the implementation of dL.

And having to remember to apply dL when matching on the AST is more
trivia to learn and remember. Not even a warning if one forgets to do
that, no appropriate place to explain this to new contributors
(reading another Note just to start doing anything at all with the
AST? unnecessary friction), and only a test failure at best in case of
a mistake.

My concrete proposal: let's just put SrcSpan in the extension fields
of each node. In other words, take these lines

type instance XVarPat  (GhcPass _) = NoExt
type instance XLazyPat (GhcPass _) = NoExt
type instance XAsPat   (GhcPass _) = NoExt
type instance XParPat  (GhcPass _) = NoExt
type instance XBangPat (GhcPass _) = NoExt
...

and replace them with

type instance XVarPat  (GhcPass _) = SrcSpan
type instance XLazyPat (GhcPass _) = SrcSpan
type instance XAsPat   (GhcPass _) = SrcSpan
type instance XParPat  (GhcPass _) = SrcSpan
type instance XBangPat (GhcPass _) = SrcSpan
...

And don't bother with the HasSrcSpan class, don't define
composeSrcSpan and decomposeSrcSpan. Very straightforward and
beneficial for both producers and consumers of an AST.

All the best,
Vladislav


More information about the ghc-devs mailing list