Opened 3 years ago

Closed 2 years ago

Last modified 23 months ago

#9968 closed bug (fixed)

DeriveAnyClass fails on multi-parameter type classes

Reported by: goldfire Owned by: dreixel
Priority: high Milestone: 8.0.1
Component: Compiler Version: 7.10.1-rc1
Keywords: Generics Cc: osa1, kosmikus
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Test Case: deriving/should_compile/T9968, should_fail/T9968a
Blocked By: Blocking:
Related Tickets: #9821 Differential Rev(s):
Wiki Page:

Description

When I say

{-# LANGUAGE DeriveAnyClass, MultiParamTypeClasses #-}

module Bug where

class C a b
data X
  deriving (C Int)

and load that into GHCi, I see this:

*Main> :load "/Users/rae/temp/DeriveAny.hs"
[1 of 1] Compiling Bug              ( /Users/rae/temp/DeriveAny.hs, interpreted )
Var/Type length mismatch: 
  [b_a2YW]
  []
Var/Type length mismatch: 
  [b_a2YW]
  []
Ok, modules loaded: Bug.
*Bug> :info C
class C a b 	-- Defined at /Users/rae/temp/DeriveAny.hs:5:1
instance C X -- Defined at /Users/rae/temp/DeriveAny.hs:7:13

It seems my Int parameter to C is being dropped. I don't believe I have a debug build in this example, so that debugging output is shipping.

Change History (17)

comment:1 Changed 3 years ago by simonpj

Owner: set to dreixel
Priority: normalhighest

Pedro this looks like your territory. Might you look? It's an outright bug.

Thanks

Simon

comment:2 Changed 3 years ago by dreixel

Yes, this is probably related to #9821. I can look into it next week.

comment:3 Changed 3 years ago by thoughtpolice

Priority: highesthigh

comment:4 Changed 3 years ago by dreixel

Simon, could you give me some help with this? I was hoping it would be easy to just reuse the infrastructure for newtype deriving here. Should I follow the structure of the EarlyDerivSpec generated by the first branch of mkNewTypeEqn?

comment:5 Changed 3 years ago by simonpj

Branch wip/T9968.

comment:6 Changed 3 years ago by simonpj

FYI Pedro is actively working on this.

comment:7 Changed 3 years ago by thoughtpolice

Milestone: 7.10.17.12.1

Moving to the 7.12.1 milestone, as these tickets won't be fixed in time for the 7.10.1 release (unless you, the reader, help write a patch :)

comment:8 Changed 2 years ago by osa1

I managed to get a panic out of this: (this is with GHC 7.10.2)

➜  trac9968  cat Bug.hs
{-# LANGUAGE DeriveAnyClass, MultiParamTypeClasses, FunctionalDependencies #-}

module Bug where

class C a b where
  showFirst  :: (a, b) -> String
  showSecond :: (a, b) -> String

data X
  deriving (C Bool)

main :: IO ()
main = putStrLn "ok"
➜  trac9968  runhaskell Bug.hs
Var/Type length mismatch:
  [b_alK]
  []
Var/Type length mismatch:
  [b_alK]
  []
Var/Type length mismatch:
  [b_alK]
  []
Var/Type length mismatch:
  [b_alK]
  []
ghc: panic! (the 'impossible' happened)
  (GHC version 7.10.2 for x86_64-unknown-linux):
        funResultTy forall b_alK. C X b_alK => (X, b_alK) -> String

Please report this as a GHC bug:  http://www.haskell.org/ghc/reportabug

A question about how deriving syntax supposed to work:

Let's say we have

class C a b

data X

as in the example above.

We can do deriving (C Bool), which implements an instance for C Bool X but if I want to derive C X Bool, is there a way to do that? Currently if I try to do deriving (C X Bool) or deriving (C Bool X) I'm getting this error:

➜  trac9968  runhaskell Bug.hs

Bug.hs:10:13:
    Expected kind ‘k0 -> GHC.Prim.Constraint’,
      but ‘C Bool X’ has kind ‘GHC.Prim.Constraint’
    In the data declaration for ‘X’

Which is clear enough but I'm wondering if there are any workarounds to make deriving (C X Bool) work.

comment:9 Changed 2 years ago by osa1

Cc: osa1 added

comment:10 Changed 2 years ago by rwbarton

I think it's best to keep the simple rule: data X = ... deriving (..., c, ...) means to derive c X (here c is an application of a class constructor to zero or more types). After all if you want something else like C X Bool then you can express that with a standalone deriving declaration deriving instance C X Bool. Or in this case just write an empty instance, it's shorter :)

comment:11 Changed 2 years ago by thoughtpolice

Milestone: 7.12.18.0.1

Milestone renamed

comment:12 Changed 2 years ago by simonpj

Cc: kosmikus added

Adding Andres, the king of generics.

comment:13 Changed 2 years ago by simonpj

See also #10938 for another example of this bug

comment:14 Changed 2 years ago by Simon Peyton Jones <simonpj@…>

In af77089/ghc:

Fix DeriveAnyClass (Trac #9968)

The main issue concerned things like

   data T a = MkT a deriving( C Int )

which is supposed to generate

   instance C Int (T a) where {}

But the 'Int' argument (called cls_tys in the code) wasn't
even being passed to inferConstraints and mk_data_eqn, so it
really had no chance.   DeriveAnyClass came along after this
code was written!

Anyway I did quite a bit of tidying up in inferConstraints.

Also I discovered that this case was not covered at all

   data T a b = MkT a b deriving( Bifunctor )

What constraints should we generate for the instance context?
We can deal with classes whose last arg has kind *, like Eq, Ord;
or (* -> *), like Functor, Traversable.  But we really don't have
a story for classes whose last arg has kind (* -> * -> *).

So I augmented checkSideConditions to check for that and give
a sensible error message.

ToDo: update the user manual.

comment:15 Changed 2 years ago by Simon Peyton Jones <simonpj@…>

In 8317893/ghc:

Improve documentation for DeriveAnyClass

c.f. Trac #9968

comment:16 Changed 2 years ago by simonpj

Resolution: fixed
Status: newclosed
Test Case: deriving/should_compile/T9968, should_fail/T9968a

comment:17 Changed 23 months ago by simonpj

Keywords: Generics added
Note: See TracTickets for help on using tickets.