
#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