[GHC] #9173: Better type error messages
GHC
ghc-devs at haskell.org
Mon Apr 30 14:21:20 UTC 2018
#9173: Better type error messages
-------------------------------------+-------------------------------------
Reporter: simonpj | Owner: goldfire
Type: bug | Status: new
Priority: high | Milestone:
Component: Compiler | Version: 7.8.2
Resolution: | Keywords:
| TypeErrorMessages
Operating System: Unknown/Multiple | Architecture:
Type of failure: Incorrect | Unknown/Multiple
warning at compile-time | Test Case:
Blocked By: | Blocking:
Related Tickets: | Differential Rev(s):
Wiki Page: |
-------------------------------------+-------------------------------------
Comment (by goldfire):
I think the time is ripe for this ticket, and it shouldn't be hard. Here
are the pieces:
1. Update `TcErrors.mkExpectedActualMsg` to print out the `uo_thing` field
of the `TypeEqOrigin` passed in. For example, if we're reporting an actual
of `Maybe Int` and an expected of `Bool`, then `uo_thing` might hold `Just
5`. This step can likely be done by changing `msg1` of
`mkExpectedActualMsg`.
2. Rip out the special treatment of kinds in `mkExpectedActualMsg`. Other
than swapping out the word "kind" for "type", kinds and types should be
treated the same. This special treatment is currently there solely to
match pre-8.0 behavior. Doing this step should improve the error messages
worsened by #14066 and fix, e.g., #14887. Concretely, this step is
essentially to remove `msg5` from `mkExpectedActualMsg`.
Those two steps, by themselves, would nail this ticket. But Simon and I
think we can do better. Currently, the `uo_thing` of a `TypeEqOrigin`
tracks the term (or type, during kind-checking) that has the "actual"
type. (It's the `Just 5` mentioned in step 1.) However, we can also track
the aspect of the context that leads us to expect the "expected" type. For
example, this string could be something like "required as the condition of
an `if`" or "of the second argument of `($)`" or "of the type used in a
type signature". Here are example error messages:
Code: `if 'x' then foo else bar`
{{{
Type mismatch: `Char' /= `Bool'
Actual: `Char' is the type of `'x''
Expected: `Bool` is the type required as the condition of an `if'
}}}
Code: `not $ 'x'`
{{{
Type mismatch: `Char' /= `Bool'
Actual: `Char` is the type of `'x''
Expected: `Bool` is the type of the second argument of ($)
}}}
Code: `foo :: Maybe`
{{{
Kind mismatch: `* -> *' /= `*'
Actual: `* -> *' is the kind of `Maybe'
Expected: `*` is the kind of the type used in a type signature
}}}
Aren't these just lovely?
To do this:
3. Add an `SDoc` field to the `Check` constructor of an `ExpType` (in
`TcType`). Then, in every `mkCheckExpType`, supply an appropriate message.
Ideally, this message will not mention any types, because there will be no
chance to zonk them later.
4. Add a new field `uo_context` to `TypeEqOrigin` (of type `Maybe SDoc`)
that will get the doc from the `Check`. This seems like it will happen in
`TcUnify.tcSubTypeDS_NC_O`, but perhaps in other places, too. It's worth
checking every place we make a `TypeEqOrigin`.
5. Teach `TcErrors.mkExpectedActualMsg` to use this new info.
We could do steps 1-2 separately from 3-5, but given the very large number
of error messages one would have to sweep through to do so, it seems best
to common these changes up.
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/9173#comment:30>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list