diff options
author | Sebastian Graf <sebastian.graf@kit.edu> | 2019-10-10 14:44:18 +0200 |
---|---|---|
committer | Marge Bot <ben+marge-bot@smart-cactus.org> | 2019-11-02 20:16:33 -0400 |
commit | 182b119943d34e82f67525c4b2390557f060c5f9 (patch) | |
tree | be48b9cbadd299bece85d4d3aca33a24e6e64e71 /compiler/GHC/Hs/Pat.hs | |
parent | 9980fb58f613ee3363c7e4cb86453e542c6c69aa (diff) | |
download | haskell-182b119943d34e82f67525c4b2390557f060c5f9.tar.gz |
Separate `LPat` from `Pat` on the type-level
Since the Trees That Grow effort started, we had `type LPat = Pat`.
This is so that `SrcLoc`s 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 `XPat`s everywhere!
There are several functions which dont't cope with `XPat`s by either
crashing (`hsPatType`) or simply returning incorrect results
(`collectEvVarsPat`).
This issue was raised in #17330. I also came up with a rather clean and
type-safe solution to the problem: We define
```haskell
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.
Diffstat (limited to 'compiler/GHC/Hs/Pat.hs')
-rw-r--r-- | compiler/GHC/Hs/Pat.hs | 32 |
1 files changed, 3 insertions, 29 deletions
diff --git a/compiler/GHC/Hs/Pat.hs b/compiler/GHC/Hs/Pat.hs index 25b0a1e184..0fa6dca7b8 100644 --- a/compiler/GHC/Hs/Pat.hs +++ b/compiler/GHC/Hs/Pat.hs @@ -72,7 +72,7 @@ import Data.Data hiding (TyCon,Fixity) type InPat p = LPat p -- No 'Out' constructors type OutPat p = LPat p -- No 'In' constructors -type LPat p = Pat p +type LPat p = XRec p Pat -- | Pattern -- @@ -326,34 +326,8 @@ type instance XSigPat GhcRn = NoExtField type instance XSigPat GhcTc = Type type instance XCoPat (GhcPass _) = NoExtField -type instance XXPat (GhcPass p) = Located (Pat (GhcPass p)) - - -{- -************************************************************************ -* * -* HasSrcSpan Instance -* * -************************************************************************ --} - -type instance SrcSpanLess (LPat (GhcPass p)) = Pat (GhcPass p) -instance HasSrcSpan (LPat (GhcPass p)) where - -- NB: The following chooses the behaviour of the outer location - -- wrapper replacing the inner ones. - composeSrcSpan (L sp p) = if sp == noSrcSpan - then p - else XPat (L sp (stripSrcSpanPat p)) - - -- NB: The following only returns the top-level location, if any. - decomposeSrcSpan (XPat (L sp p)) = L sp (stripSrcSpanPat p) - decomposeSrcSpan p = L noSrcSpan p - -stripSrcSpanPat :: LPat (GhcPass p) -> Pat (GhcPass p) -stripSrcSpanPat (XPat (L _ p)) = stripSrcSpanPat p -stripSrcSpanPat p = p - +type instance XXPat (GhcPass _) = NoExtCon -- --------------------------------------------------------------------- @@ -574,7 +548,7 @@ pprPat (ConPatOut { pat_con = con , ppr binds]) <+> pprConArgs details else pprUserCon (unLoc con) details -pprPat (XPat x) = ppr x +pprPat (XPat n) = noExtCon n pprUserCon :: (OutputableBndr con, OutputableBndrId p) |