[GHC] #14320: Brackets change meaning of value-constructor type

GHC ghc-devs at haskell.org
Wed Oct 4 19:04:27 UTC 2017


#14320: Brackets change meaning of value-constructor type
-------------------------------------+-------------------------------------
        Reporter:  nr                |                Owner:  (none)
            Type:  bug               |               Status:  new
        Priority:  normal            |            Milestone:
       Component:  Compiler (Type    |              Version:  8.2.1
  checker)                           |             Keywords:  GADT,
      Resolution:                    |  existential type
Operating System:  Linux             |         Architecture:  x86_64
 Type of failure:  GHC rejects       |  (amd64)
  valid program                      |            Test Case:
      Blocked By:                    |             Blocking:
 Related Tickets:                    |  Differential Rev(s):
       Wiki Page:                    |
-------------------------------------+-------------------------------------

Comment (by RyanGlScott):

 Just to make sure: your file has the following GADT:

 {{{#!hs
 newtype TypedExpToo :: * -> * where
   TEBad  :: (forall a . (Exp -> (TypedExp a)))
 }}}

 Did you mean for `TEBad`'s return type to actually be `TypedExpToo a`?
 (I'll assume the answer is "yes".)

 This is another oddity caused by the fact that we validity check GADT
 constructor type signatures on source syntax instead of Core. In this
 case, the `HsParTy` constructor is throwing a wrench into things.

 Supporting this use case doesn't seem like it would be particularly
 difficult: we'd just need to have `splitLHsForAllTy` and `splitLHsQualTy`
 looks through parentheses:

 {{{#!diff
 diff --git a/compiler/hsSyn/HsTypes.hs b/compiler/hsSyn/HsTypes.hs
 index b9cd946..1864aa2 100644
 --- a/compiler/hsSyn/HsTypes.hs
 +++ b/compiler/hsSyn/HsTypes.hs
 @@ -1053,10 +1053,12 @@ splitLHsSigmaTy ty

  splitLHsForAllTy :: LHsType pass -> ([LHsTyVarBndr pass], LHsType pass)
  splitLHsForAllTy (L _ (HsForAllTy { hst_bndrs = tvs, hst_body = body }))
 = (tvs, body)
 +splitLHsForAllTy (L _ (HsParTy t)) = splitLHsForAllTy t
  splitLHsForAllTy body
 = ([], body)

  splitLHsQualTy :: LHsType pass -> (LHsContext pass, LHsType pass)
  splitLHsQualTy (L _ (HsQualTy { hst_ctxt = ctxt, hst_body = body })) =
 (ctxt,     body)
 +splitLHsQualTy (L _ (HsParTy t)) = splitLHsQualTy t
  splitLHsQualTy body                                                  =
 (noLoc [], body)

  splitLHsInstDeclTy :: LHsSigType GhcRn
 }}}

 This makes `Badgadt.hs` typecheck (after correcting the return type of
 `TEBad`). Do others think this is reasonable?

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


More information about the ghc-tickets mailing list