Opened 4 years ago

Closed 4 years ago

#8884 closed bug (fixed)

Reifying closed type families is broken

Reported by: goldfire Owned by: goldfire
Priority: normal Milestone: 7.8.1
Component: Template Haskell Version: 7.8.1-rc2
Keywords: Cc:
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Test Case: th/T8884
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:


If I say

{-# LANGUAGE TemplateHaskell, TypeFamilies, PolyKinds #-}

module Scratch where

import Language.Haskell.TH

type family Foo a where
  Foo x = x

$( do FamilyI foo [] <- reify ''Foo
      runIO $ putStrLn $ show foo
      return [] )

and compile, I see (with uniques suppressed)

ClosedTypeFamilyD Scratch.Foo
  [KindedTV a (VarT k)]
  (Just (AppT (AppT ArrowT (VarT k)) (VarT k)))
  [TySynEqn [VarT k,VarT x] (VarT x)]

There are two problems here:

  1. The return kind (the third parameter to ClosedTypeFamilyD) should be just that -- the return kind. In the output, we see the full kind of the type family. k -> k.
  1. The equation includes the kind variable k, which should be implicit.

Change History (13)

comment:1 Changed 4 years ago by Richard Eisenberg <eir@…>

In 8c5ea91d68cdc79b413e05f7dacfd052f5de8c64/ghc:

Fix #8884.

There were two unrelated errors fixed here:
 1) Make sure that only the *result kind* is reified when reifying
    a type family. Previously, the whole kind was reified, which
    defies the TH spec.

 2) Omit kind patterns in equations.

comment:2 Changed 4 years ago by goldfire

Status: newmerge

The fix affects open type families as well as closed. Both families had exactly the same mis-behavior, upon inspection of the code.

Given that, it's unclear to me whether this should be merged. The old behavior was clearly wrong -- for example, reifying a type family and then trying to splice it would end in failure. But, the old behavior was also quite reliable, and it's conceivable that users have noticed the poor behavior and have coded against it. (In fact, a co-author of one of my libraries has done just that, which is how I discovered the GHC bug!)

So, we must choose between

  • Retaining the incorrect behavior (which has been around for some time), while not surprising users in the final 7.8 release, or
  • Having correct behavior.

I slightly favor the latter, believing that this error was so egregious that no one (other than me, evidently) is using this feature of GHC. If anyone else were using the feature, we would have seen the bug report!

So, I'm setting this ticket to merge but am happy to have others disagree about that decision.

comment:3 Changed 4 years ago by goldfire

Test Case: th/T8884

comment:4 Changed 4 years ago by carter

how would they even use the incorrect behavior constructively?

comment:5 Changed 4 years ago by simonpj

I think we should merge. IBM and Microsoft may sometimes have to maintain old, incorrect behaviour for legacy reasons, but GHC doesn't!

Thank you for fixing this.


comment:6 in reply to:  4 Changed 4 years ago by goldfire

Replying to carter:

how would they even use the incorrect behavior constructively?

Note that the incorrect behavior applied to open type families as well as closed, so this isn't a new bug in 7.8. How could they use it constructively? Reifying a type family gives the list of arguments and the result kind. By counting the number of arguments, a program could remove the same number of arrows from the returned kind to get the actual result kind. It's not too hard, actually. As for the extra kind parameters, I suppose a program could do dependency analysis to discover which variables are kind variables and remove them.

In any case, my library (a branch of singletons) was able to use the incorrect behavior without too much trouble (once we figured out what was going on), so there's an evidence proof for you. :)

comment:7 Changed 4 years ago by thoughtpolice

Resolution: fixed
Status: mergeclosed

Merged in 7.8.

comment:8 Changed 4 years ago by nomeata

Test case fails on ghc-7.8:

Actual stderr output differs from expected:
--- ./th/T8884.stderr	2014-03-17 16:06:49.515482947 +0000
+++ ./th/T8884.comp.stderr	2014-03-17 16:44:36.121051051 +0000
@@ -1,3 +0,0 @@
-type family T8884.Foo (a_0 :: k_1) :: k_1 where T8884.Foo x_2 = x_2
-type family T8884.Baz (a_0 :: k_1) :: *
-type instance T8884.Baz x_0 = x_0
*** unexpected failure for T8884(normal) Maybe some test files missing?

comment:9 Changed 4 years ago by thoughtpolice

Blagh, totally my fault. On it...

comment:10 Changed 4 years ago by nomeata

thoughtpolice: Did you get to fix it? It seems the only failing test case missing after Gergo fixed up the failures he caused.

comment:11 Changed 4 years ago by Joachim Breitner <mail@…>

In df409de9550dc8a07e010964a54112266d809341/ghc:

Flush after TH in #8884 test case

(I recall that this was needed in some cases in the past, and might fix
the validate error on travis.)

comment:12 Changed 4 years ago by nomeata

Status: closedmerge

The test case fix should also be merged.

comment:13 Changed 4 years ago by thoughtpolice

Status: mergeclosed


Note: See TracTickets for help on using tickets.