Separate `LPat` from `Pat` on the type-level by re-introducing `Located` only within GHC
Since the Trees That Grow effort started, we had type LPat = Pat.
This is so that SrcLocs would only be annotated in GHC's AST, which is
the reason why all GHC passes use the extension constructor XPat to
attach source locations. See #15495 for the design discussion behind
that.
But now suddenly there are XPats everywhere!
There are several functions which dont't cope with XPats by either
crashing (hsPatType) or simply returning incorrect results
(collectEvVarsPat).
This issue was raised in #17330 (closed). I also came up with a rather clean and type-safe solution to the problem: We define
type family XRec p (f :: * -> *) = r | r -> p f
type instance XRec (GhcPass p) f = Located (f (GhcPass p))
type instance XRec TH f = f p
type LPat p = XRec p Pat
This is a rather modular embedding of the old "ping-pong" style, while
we only pay for the Located wrapper within GHC. No ping-ponging in
a potential Template Haskell AST, for example. Yet, we miss no case
where we should've handled a SrcLoc: hsPatType and
collectEvVarsPat are not callable at an LPat.
Also, this gets rid of one indirection in Located variants:
Previously, we'd have to go through XPat and Located to get from
LPat to the wrapped Pat. Now it's just Located again.
Thus we fix #17330 (closed).
The corresponding solution on the wiki page is solution D.