Opened 5 months ago

Closed 4 months ago

Last modified 4 months ago

#8567 closed bug (fixed)

Poor error message when GeneralizedNewtypeDeriving fails

Reported by: goldfire Owned by: nomeata
Priority: normal Milestone:
Component: Compiler Version: 7.7
Keywords: Cc:
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Difficulty: Unknown
Test Case: Blocked By:
Blocking: Related Tickets:

Description

Say I try to compile this silly module:

{-# LANGUAGE GeneralizedNewtypeDeriving, TypeFamilies #-}

module Bug where

class C a where
  meth :: a -> F a

type family F a
type instance F Int = Bool
type instance F Age = Char

instance C Int where
  meth = (> 0)

newtype Age = MkAge Int
  deriving C

Then, I get this output:

Bug.hs:16:12:
    No instance for (GHC.Types.Coercible Bool Char)
      because ‛Bool’ and ‛Char’ are different types.
      arising from a use of ‛GHC.Prim.coerce’
    In the expression:
        GHC.Prim.coerce (meth :: Int -> F Int) :: Age -> F Age
    In an equation for ‛meth’:
        meth = GHC.Prim.coerce (meth :: Int -> F Int) :: Age -> F Age
    In the instance declaration for ‛C Age’

What a confusing error message! Of the 9 lines of error, only 3 make sense: the line number (which is correct, at the line number of my deriving statement), saying that Bool and Char are different, and the conclusion that we're in an instance declaration.

This might be better:

Bug.hs:16:12:
    Cannot coerce from ‛Bool’ to ‛Char’
      because ‛Bool’ and ‛Char’ are different types
      arising from the need to coerce ‛Int -> F Int’ to ‛Age -> F Age’
    In the instance declaration for ‛C Age’
      generated automatically through GeneralizedNewtypeDeriving
      To see the code I am typechecking, use -ddump-deriv

I actually went ahead and tried to fix this myself, but it's unclear to me what the best implementation plan for such an error message is. The code in TcDeriv generates HsSyn RdrName and then renames it to HsSyn Name, but that code then gets sent through the normal type-checking pipeline. That pipeline builds up the error-reporting context without much heed to the fact that GHC itself generated the code. So, while I'm sure I could hack away long enough to get the error message to come out right, I'm equally sure that the resulting code would make people want to cry. Any advice? Or does someone with a better perspective want to take a stab?

Change History (5)

comment:1 Changed 5 months ago by simonpj

There are several parts to this:

  • It would be dead easy to generate a better error message for an unsolved constraint Coerce Int Bool. Rather than generating a generic type-class error message, it'd be easy to produce a message about the inability to coerce Int to Bool. Error messages are generated by TcErrors. We already generate special error messages for implicit parameters, which are already type-class constraints; ?x:Int is short for IP "x" Int.
  • The "arising from a use of corece" part is also generated in TcErrors. Again, it'd be easy to change the form of the message for a call to coerce.
  • A bit harder to omit the In the expression, In the definition of meth parts. They might even be helpful, if we explain in the manual how newtype deriving actually works (via corece).

I'd be happy to advise

Simon

Last edited 5 months ago by simonpj (previous) (diff)

comment:2 Changed 5 months ago by nomeata

  • Owner set to nomeata

In discussion with SPJ, we thought about how we can catch missing instances already in the code for deriving, at least for non-standalone-deriving. I’ll work on that, and on making the error message a bit nicer.

comment:3 Changed 5 months ago by nomeata

Was straight forward to implement, validate is running...

comment:4 Changed 5 months ago by Joachim Breitner <mail@…>

In 1791ea0abf446bc7221f713d715f4bf87dc6af47/ghc:

Print nicer error message for Coercible errors

It now reads

   Could not coerce from ‛S a’ to ‛S (NT a)’

and does not mention Coercible any more (as discussed in #8567).

comment:5 Changed 4 months ago by nomeata

  • Resolution set to fixed
  • Status changed from new to closed

This is implemented and in master, see the test suite update at 522563a27b630b63d18e0ec6fa09c7b5eb6ab6c1/testsuite for how the messages look like now.

Last edited 4 months ago by nomeata (previous) (diff)
Note: See TracTickets for help on using tickets.