Skip to content

TH improperly converts promoted data cons in ConT

If you compile the following program:

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TemplateHaskell #-}
{-# OPTIONS_GHC -ddump-splices #-}
module Bug where

import Language.Haskell.TH

$([d| type AbsoluteUnit1 = '() |])
$(pure [TySynD (mkName "AbsoluteUnit2") [] (ConT '())])
$ /opt/ghc/8.6.1/bin/ghci Bug.hs
GHCi, version 8.6.0.20180810: http://www.haskell.org/ghc/  :? for help
Loaded GHCi configuration from /home/rgscott/.ghci
[1 of 1] Compiling Bug              ( Bug.hs, interpreted )
Bug.hs:8:3-33: Splicing declarations
    [d| type AbsoluteUnit1_a1HN =  '() |]
  ======>
    type AbsoluteUnit1_a4qs =  '()
Bug.hs:9:3-54: Splicing declarations
    pure [TySynD (mkName "AbsoluteUnit2") [] (ConT '())]
  ======>
    type AbsoluteUnit2 = ()

You'll notice an unusual discrepancy between the two -ddump-splices logs. In the first one:

    type AbsoluteUnit1_a4qs =  '()

The '() constructor is properly preceded with a single quote. In the second one, however:

    type AbsoluteUnit2 = ()

'() incorrectly appears without a single quote! The culprit is in the way Convert handles ConT:

          ConT nm -> do { nm' <- tconName nm
                        ; mk_apps (HsTyVar noExt NotPromoted (noLoc nm')) tys'}

This code naïvely assumes that ConT will never contain a promoted data constructor name by hardcoding NotPromoted. We really ought to be checking if nm' is a data con RdrName here and using Promoted if so, and NotPromoted otherwise.

Patch incoming.

Trac metadata
Trac field Value
Version 8.4.3
Type Bug
TypeOfFailure OtherFailure
Priority normal
Resolution Unresolved
Component Template Haskell
Test case
Differential revisions
BlockedBy
Related
Blocking
CC
Operating system
Architecture
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information