[GHC] #15824: Prefix/infix distinction in TemplateHaskell types is lost

GHC ghc-devs at haskell.org
Sun Oct 28 18:49:01 UTC 2018


#15824: Prefix/infix distinction in TemplateHaskell types is lost
-------------------------------------+-------------------------------------
           Reporter:  int-index      |             Owner:  (none)
               Type:  bug            |            Status:  new
           Priority:  normal         |         Milestone:
          Component:  Template       |           Version:  8.6.1
  Haskell                            |
           Keywords:                 |  Operating System:  Unknown/Multiple
       Architecture:                 |   Type of failure:  None/Unknown
  Unknown/Multiple                   |
          Test Case:                 |        Blocked By:
           Blocking:                 |   Related Tickets:  #15815, #15760
Differential Rev(s):                 |         Wiki Page:
-------------------------------------+-------------------------------------
 Consider `data T a b = a :. b`.

 In the declaration, `:.` is mapped to `InfixC`:

 {{{
 ghci> putStrLn $(reify ''T >>= stringE . show)
 TyConI (DataD [] T [KindedTV a StarT,KindedTV b StarT] Nothing [InfixC
 (Bang NoSourceUnpackedness NoSourceStrictness,VarT a) :. (Bang
 NoSourceUnpackedness NoSourceStrictness,VarT b)] [])
 }}}

 In expressions, `a :. b` is mapped to `InfixE`:

 {{{
 ghci> runQ [e| 1 :+ 2 |] >>= print
 InfixE (Just (LitE (IntegerL 1))) (ConE :+) (Just (LitE (IntegerL 2)))
 }}}

 In patterns, `a :. b` is mapped to `InfixP`:

 {{{
 ghci> runQ [p| 1 :. 2 |] >>= print
 InfixP (LitP (IntegerL 1)) :. (LitP (IntegerL 2))
 }}}

 In types, `a :. b` is mapped to `InfixT`:

 {{{
 ghci> runQ [t| 1 :. 2 |] >>= print
 InfixT (LitT (NumTyLit 1)) (PromotedT :.) (LitT (NumTyLit 2))
 }}}

 That last one was a lie. In reality, in types `a :. b` is mapped to nested
 `AppT`:

 {{{
 ghci> runQ [t| 1 :. 2 |] >>= print
 AppT (AppT (PromotedT :.) (LitT (NumTyLit 1))) (LitT (NumTyLit 2))
 }}}

 This is despite the existence of `InfixT`.

 The same issue can be observed when reifying types:

 {{{
 ghci> type A = 1 :. 2
 ghci> putStrLn $(reify ''A >>= stringE . show)
 TyConI (TySynD A [] (AppT (AppT (PromotedT :.) (LitT (NumTyLit 1))) (LitT
 (NumTyLit 2))))
 }}}

 This is not specific to infix constructors and can be observed with any
 infix (type) operators.

 It's best to change this in the same release as we fix #15760, as there is
 code in the wild that is prepared to face neither `InfixT` nor `ParensT`,
 and it would break silently. RyanGlScott gives an example of such code:
 [https://github.com/glguy/th-
 abstraction/blob/5123c6d054d0949cb444590269f13e5d44699ab2/src/Language/Haskell/TH/Datatype.hs#L1156-L1160
 decomposeType from th-desugar].

 This issue is in part responsible for #15815, see comment:5:ticket:15815.

-- 
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/15824>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list