Evan Laforge | 27 Jul 21:35 2013
Picon

cascading type errors in ghc

I frequently see one logical mistake turn into many type errors in
ghc.  Of course in general "one logical mistake" to a human and a type
checker can be completely different things, so that's not surprising.
The thing is, I feel like I started seeing more with the upgrade to
ghc 7.6 (or was it 7.4?) a while back, which I guess coincides with a
big typechecker overhaul.  So I tracked down a specific example,
though I haven't checked if this gives different results in older
ghcs:

complicated :: Bool -> Int -> (Double -> Double)
    -> Int -> Char -> Int -> Char -> ()
complicated _ _ _ _ _ _ _ = ()

t0 = complicated 0 id x1 y1 x1 y1
    where
    x1 :: Int
    x1 = 0
    y1 :: Char
    y1 = 'a'

In this case, the call to complicated is missing the initial Bool.  In
ghci the above gives 5 separate type errors, for the 2nd, 3rd, 4th,
5th, and 6th arguments.  The curious thing is, if I replace x1 and y1
with their values:

t0 = complicated 0 id 0 'a' 0 'a'

I'm now down to only 3 type errors, for 2nd, 4th, and 6th args.

So I'm just curious: what's the difference between the where-bound
(Continue reading)

Simon Peyton-Jones | 28 Jul 18:01 2013
Picon

RE: cascading type errors in ghc

Giving good type error messages is tricky!

You get different behaviour for literals because 0 has type (forall a. Num a => a), whereas you declared x1 to
have type Int.  GHC could have additionally said "Can't find an instance for Num Bool, but it suppresses
such errors if there are more serious ones at hand.  Hence the difference you observed.

Previous GHCs would often bale out altogether if they tried to unify Int with Bool, and recover at some outer
point.  That's good for not getting lots of errors, but it might suppress genuinely separate errors. 
Nowadays we gather all the unsolved constraints without an exception-style bale-out, which probably
accounts for you seeing more errors.

The good news is that error generation is all in one module TcErrors.lhs, so it's easy to adjust these
things.  For example, given a nearby bunch of errors, you could suppress all but one.  I don't know whether
that would on balance make things better or not.  But it's certainly easy to experiment (if you build
yourself a GHC).

Simon

|  -----Original Message-----
|  From: Glasgow-haskell-users [mailto:glasgow-haskell-users-bounces <at> haskell.org]
|  On Behalf Of Evan Laforge
|  Sent: 27 July 2013 20:36
|  To: GHC users
|  Subject: cascading type errors in ghc
|  
|  I frequently see one logical mistake turn into many type errors in
|  ghc.  Of course in general "one logical mistake" to a human and a type
|  checker can be completely different things, so that's not surprising.
|  The thing is, I feel like I started seeing more with the upgrade to
|  ghc 7.6 (or was it 7.4?) a while back, which I guess coincides with a
(Continue reading)

Evan Laforge | 6 Aug 21:03 2013
Picon

Re: cascading type errors in ghc

On Sun, Jul 28, 2013 at 9:01 AM, Simon Peyton-Jones
<simonpj <at> microsoft.com> wrote:
> Giving good type error messages is tricky!

Indeed, and I'm fully aware this is a Hard Problem.

> You get different behaviour for literals because 0 has type (forall a. Num a => a), whereas you declared x1
to have type Int.  GHC could have additionally said "Can't find an instance for Num Bool, but it suppresses
such errors if there are more serious ones at hand.  Hence the difference you observed.
>
> Previous GHCs would often bale out altogether if they tried to unify Int with Bool, and recover at some
outer point.  That's good for not getting lots of errors, but it might suppress genuinely separate errors. 
Nowadays we gather all the unsolved constraints without an exception-style bale-out, which probably
accounts for you seeing more errors.

Yeah, that makes a lot of sense, thanks for the explanation.

I don't know how others like to work, but I like when a compiler bails
early, because I fix errors one at a time, and I search for the
easiest looking ones before worrying about the complicated looking
ones.

> The good news is that error generation is all in one module TcErrors.lhs, so it's easy to adjust these
things.  For example, given a nearby bunch of errors, you could suppress all but one.  I don't know whether
that would on balance make things better or not.  But it's certainly easy to experiment (if you build
yourself a GHC).

Maybe we could do better with some heuristics, e.g. categorize errors
into "simple" and "advanced", and have simple errors suppress advanced
ones.  This already happens to an extent: syntax error will suppress
(Continue reading)

Malcolm Wallace | 9 Aug 10:48 2013

Re: cascading type errors in ghc


On 6 Aug 2013, at 20:03, Evan Laforge wrote:

> I don't know how others like to work, but I like when a compiler bails
> early, because I fix errors one at a time, and I search for the
> easiest looking ones before worrying about the complicated looking
> ones.

With C compilers, it is often the case that only the first error is real, and the subsequent errors are
consequences of not being able to recover from the first one.

However, one of the really nice things about GHC is that the list of type errors is complete and coherent.  I
often start at the bottom of the list and work my way up fixing them in a single pass (upwards, in order to give
myself the best chance that the line numbers are still correct after I have fixed the later errors).  There
are not many compilers you can do that with, and I like it when I can.

Regards,
    Malcolm

Gmane