[GHC] #15815: problem with splicing type into constraint
GHC
ghc-devs at haskell.org
Sat Oct 27 22:15:55 UTC 2018
#15815: problem with splicing type into constraint
-------------------------------------+-------------------------------------
Reporter: int-e | Owner: RyanGlScott
Type: bug | Status: new
Priority: highest | Milestone:
Component: Template Haskell | Version: 8.6.1
Resolution: | Keywords:
Operating System: Unknown/Multiple | Architecture:
Type of failure: GHC rejects | Unknown/Multiple
valid program | Test Case:
Blocked By: | Blocking:
Related Tickets: #15760 | Differential Rev(s):
Wiki Page: |
-------------------------------------+-------------------------------------
Changes (by RyanGlScott):
* cc: goldfire (added)
* related: => #15760
Comment:
I believe I understand what is happening here. The problem is that when
you roundtrip the following declaration through Template Haskell:
{{{#!hs
$([d| foo :: a ~ (Int -> Int) => a
foo = undefined |])
}}}
Then all parentheses are stripped away when converting this to the GHC
AST. This has important consequences when processing `foo`'s type
signature. Before the offending commit (that I linked to in comment:2),
the context of `foo`'s type signature would become:
{{{
HsEqTy a (HsOpTy Int (->) Int)
}}}
But after the offending commit, this becomes:
{{{
HsOpTy a (~) (HsOpTy Int (->) Int)
}}}
Upon first glance, these would appear to be identical. But as it turns
out, `HsEqTy` actually had special treatment in the renamer, which means
that it was renamed as though one had implicitly added `HsParTy`s around
both of its arguments. On the other hand, when GHC renaming sequences of
`HsOpTy`s (as in the second example), no such thing happens. In essence,
that AST corresponds to:
{{{#!hs
a ~ Int -> Int
}}}
GHC thinks that should be parenthesized as:
{{{#!hs
(a ~ Int) -> Int
}}}
Which leads to the error that we see in this ticket.
A quick-and-dirty way to fix this would be to change `cvtTypeKind` such
that when we convert an `EqualityT`, we parenthesize `~`'s arguments if
they aren't parenthesized. In other words, apply this patch:
{{{#!diff
diff --git a/compiler/hsSyn/Convert.hs b/compiler/hsSyn/Convert.hs
index 8b12a78..74a6011 100644
--- a/compiler/hsSyn/Convert.hs
+++ b/compiler/hsSyn/Convert.hs
@@ -1437,7 +1437,9 @@ cvtTypeKind ty_str ty
EqualityT
| [x',y'] <- tys' ->
- returnL (HsOpTy noExt x' (noLoc eqTyCon_RDR) y')
+ let px = parenthesizeHsType opPrec x'
+ py = parenthesizeHsType opPrec y'
+ in returnL (HsOpTy noExt px (noLoc eqTyCon_RDR) py)
| otherwise ->
mk_apps (HsTyVar noExt NotPromoted
(noLoc eqTyCon_RDR)) tys'
}}}
That makes the original program compile again, although it's just applying
a bandage over a deeper wound—namely, that TH conversion strips away
parentheses in the first place.
goldfire, weren't you looking into fixing the parentheses issue in #15760?
If so, perhaps your patch there would make for a more elegant fix for this
ticket. On the other hand, if that still needs some work, I could whip up
a stopgap solution now (based on the code above) so that this could be
backported to a patch release if necessary.
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/15815#comment:4>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list