Opened 3 years ago

Closed 3 years ago

Last modified 3 years ago

#4875 closed bug (fixed)

ghc misdiagnoses a compile time error concerning parameterized types

Reported by: Stef Joosten Owned by: simonpj
Priority: normal Milestone: 7.4.1
Component: Compiler Version: 6.12.3
Keywords: Cc:
Operating System: Windows Architecture: Unknown/Multiple
Type of failure: Other Difficulty:
Test Case: typecheck/should_fail/T4875 Blocked By:
Blocking: Related Tickets:

Description (last modified by igloo)

Please find the script HaskellBug?.hs at the bottom of this message.
Here is how to reproduce the behaviour in two steps.

Step 1: verify that Module HaskellBug? produces the following error message:

[1 of 1] Compiling HaskellBug       ( HaskellBug.hs, interpreted )

HaskellBug.hs:12:22:
    `rel' is not applied to enough type arguments
    Expected kind `??', but `rel' has kind `* -> *'
    In the type `rel -> concept'
    In the class declaration for `Association'

Step 2: remove the definition of class Morphic r c and verify that the script is now error free.

You have now reproduced the symptoms.

Assessment:
In this situation, ghc has diagnosed an error in the definition of
class Association. This error was resolved by removing another
definition, without altering the definition of class Association.
This proves that the definition of class Association was correct in the first place. Therefore, ghc has made a mistake. It has diagnosed
the error in the wrong location. I whould have expected an error
message like

HaskellBug.hs:23:22:
    `r' is applied to too many type arguments
    Expected <something sensible here>
    In the type `r -> c'
    In the class declaration for `Morphic'

Epilog:
I have taken the trouble to isolate the problem in a small script,
because this error has caused serious havoc in a large Haskell
project. Students, who were still learning about parameterized
types, have systematically been 'fixing' the wrong code, because
ghc has never pointed in the direction of the real error. In the
end, they were unable to resolve their mistake.
Besides haarvesting a frustrating experience with parameterized
types, wasting two entire days before giving up, they have turned a
large script upside down and introduced many more mistakes. That is
why I think it is important to get this fixed.

Here is the script:

{-# OPTIONS  -XMultiParamTypeClasses  -XFunctionalDependencies -XFlexibleInstances #-}
module HaskellBug where

  data Relation c -- The basic Relation
     = Rel { relnm :: String -- The name of the relation
           , relsrc :: c -- Source concept
           , reltrg :: c -- ^Target concept
           }
       deriving Eq

  class (Eq concept)=> Association rel concept | rel -> concept where
    source, target :: rel -> concept      -- e.g. Declaration Concept -> Concept
    sign  :: rel -> (concept,concept)
    sign x = (source x,target x) 
    homogeneous :: rel -> Bool
    homogeneous s = source s == target s

  instance (Eq c)=>Association (Relation c) c where
    source = relsrc
    target = reltrg
    
  class (Eq c, Association r c) => Morphic r c where
    multiplicities :: r c -> [c]
    multiplicities _ = []

Change History (6)

comment:1 Changed 3 years ago by igloo

  • Description modified (diff)

comment:2 Changed 3 years ago by igloo

  • Milestone set to 7.2.1
  • Owner set to simonpj

Thanks for the report.

GHC hasn't made a mistake as such. It's looked at the Morphic class, which tells it that Association's first parameter has kind * -> *, and then looked at the Association class, which tries to use it with kind *. It doesn't know that the first piece of information it found was the wrong one.

You can give GHC more information, which allows it to give better errors: If you add

{-# LANGUAGE KindSignatures #-}

at the top of the file, and change the class line to

class (Eq concept)=> Association (rel :: *) concept | rel -> concept where

then you get

q.hs:24:23:
    `r' is applied to too many type arguments
    In the type `r c -> [c]'
    In the class declaration for `Morphic'

instead.

Simon, I don't know how easy it would be to improve the error? Perhaps, assuming there is not context loop, it would be better for the typechecker to process class bodies in dependency order?

comment:3 Changed 3 years ago by simonpj

Yes, I was on a plane so I started working on this. Patch coming.

comment:4 Changed 3 years ago by simonpj

  • Resolution set to fixed
  • Status changed from new to closed
  • Test Case set to typecheck/should_fail/T4875

Fixed by
Try not to push this to the 7.0 branch because it'll (correctly) reject a few programs that 7.0 accepts.

Simon

comment:5 Changed 3 years ago by simonpj

Oops I missed out the commit message:

Mon Jan 10 11:03:51 GMT 2011  simonpj@microsoft.com
  * Do dependency analysis when kind-checking type declarations
  
  This patch fixes Trac #4875.  The main point is to do dependency
  analysis on type and class declarations, and kind-check them in
  dependency order, so as to improve error messages.
  
  This patch means that a few programs that would typecheck before won't
  typecheck any more; but before we were (naughtily) going beyond
  Haskell 98 without any language-extension flags, and Trac #4875
  convinces me that doing so is a Bad Idea.
  
  Here's an example that won't typecheck any more
         data T a b = MkT (a b)
         type F k = T k Maybe
  
  If you look at T on its own you'd default 'a' to kind *->*;
  and then kind-checking would fail on F.
  
  But GHC currently accepts this program beause it looks at
  the *occurrences* of T.

    M ./compiler/deSugar/DsMeta.hs -1 +1
    M ./compiler/hsSyn/HsDecls.lhs -2 +8
    M ./compiler/hsSyn/HsUtils.lhs -3 +4
    M ./compiler/rename/RnNames.lhs -1 +1
    M ./compiler/rename/RnSource.lhs -11 +52
    M ./compiler/typecheck/TcInstDcls.lhs -1 +1
    M ./compiler/typecheck/TcRnDriver.lhs -5 +5
    M ./compiler/typecheck/TcTyClsDecls.lhs -224 +139
    M ./compiler/typecheck/TcTyDecls.lhs +37
    M ./utils/ghctags/Main.hs -1 +1

comment:6 Changed 3 years ago by Stef Joosten

Simon, thank you for this.
Yours,
Stef Joosten

Note: See TracTickets for help on using tickets.