Improving overloaded error messages

22 views
Skip to first unread message

Mark Harrah

unread,
Jun 3, 2012, 7:31:36 PM6/3/12
to scala-i...@googlegroups.com
It is well known[1] that the quality of error messages and type inference when calling an overloaded method is lower than when calling non-overloaded methods. I've implemented a proof of concept that introduces a new annotation to indicate that better error messages[2] are desired at the expense of generality. The documentation for the annotation[3] should explain the idea and the test case[4] should show the difference it makes in practice.

I won't claim this is suitable for inclusion to trunk in implementation or concept, but hopefully it is a start for discussion and demonstrates the need. Previously, it has been suggested that macros would help, but that approach seems to require untyped macro arguments, which aren't coming in the near future anytime soon as far as I know (and I would prefer sticking to typed macros).

-Mark

[1] at least to scala-internals readers, I assume
[2] I think it used to provide better inference too, but it doesn't appear to do so after rebasing to the latest master.
[3] https://github.com/harrah/scala/commit/f229bd83d33b1b68d76dc3b0fe3eba65bff3d284#diff-3
[4] https://github.com/harrah/scala/commit/f229bd83d33b1b68d76dc3b0fe3eba65bff3d284#diff-4

Adriaan Moors

unread,
Jun 4, 2012, 5:10:32 AM6/4/12
to scala-i...@googlegroups.com
I think we could always provide a more helpful message when one of the overloaded variants could type check if types were inferred differently.
Since we're already erroring out, the performance hit may be acceptable.

Your example:

```
A.scala:11: error: overloaded method value overloaded with alternatives:
  (special: Special[Boolean])Unit <and>
  (normal: Normal[Boolean])Unit
 cannot be applied to (Normal[Int])
  overloaded[Boolean](new Normal(3))
            ^
```

Could be improved to (modulo more error-messagey wording):

```
A.scala:11: error: overloaded method value overloaded with alternatives:
  (special: Special[Boolean])Unit <and>
  (normal: Normal[Boolean])Unit
 cannot be applied to (Normal[Int])
  overloaded[Boolean](new Normal(3))
            ^

Note: Normal[Int] was inferred for overloaded's argument.
However, the closest overloaded variant requires a Normal[Boolean].
If that's what you meant, the above error becomes:

  found   : Int(3)
  required: Boolean
   overloaded[Boolean](new Normal(3))
                                                   ^
```

Mark Harrah

unread,
Jun 4, 2012, 9:33:33 AM6/4/12
to scala-i...@googlegroups.com
On Mon, 4 Jun 2012 11:10:32 +0200
Adriaan Moors <adriaa...@epfl.ch> wrote:

> I think we could *always* provide a more helpful message when one of the
> overloaded variants could type check if types were inferred differently.
> Since we're already erroring out, the performance hit may be acceptable.

Thanks for looking at this...

> Your example:
>
> ```
> A.scala:11: error: overloaded method value overloaded with alternatives:
> (special: Special[Boolean])Unit <and>
> (normal: Normal[Boolean])Unit
> cannot be applied to (Normal[Int])
> overloaded[Boolean](new Normal(3))
> ^
> ```
>
> Could be improved to (modulo more error-messagey wording):
>
> ```
> A.scala:11: error: overloaded method value overloaded with alternatives:
> (special: Special[Boolean])Unit <and>
> (normal: Normal[Boolean])Unit
> cannot be applied to (Normal[Int])
> overloaded[Boolean](new Normal(3))
> ^
>
> Note: Normal[Int] was inferred for overloaded's argument.
> However, the closest overloaded variant requires a Normal[Boolean].
> If that's what you meant, the above error becomes:
>
> found : Int(3)
> required: Boolean
> overloaded[Boolean](new Normal(3))
> ^
> ```

A double message is probably more confusing, but perhaps the first section can be dropped. This would be more what I'm aiming for:

Normal[Int] was inferred for overloaded's argument.
However, the closest overloaded variant requires a Normal[Boolean].

found : Int(3)
required: Boolean
overloaded[Boolean](new Normal(3))
^

It implies there is an overload without taking up too much vertical space and preserves the clearer found/required lines. Of course, you've generalized the concept and now have the SIP-worthy "closest overloaded variant".

I thought the patch improved inference as well, so that this compiles:

overloaded[Int => Boolean](new Normal(_ == 0))

but either it never did or something changed in trunk (I wrote the original patch months ago). It is the double penalty of error message and inference that I was trying to overcome, but improving the error message without the need for a special annotation would be great.

-Mark

Adriaan Moors

unread,
Jun 4, 2012, 9:48:42 AM6/4/12
to scala-i...@googlegroups.com


On Mon, Jun 4, 2012 at 3:33 PM, Mark Harrah <dmha...@gmail.com> wrote:
improving the error message without the need for a special annotation would be great.
Yes, I think that's a realistic and worthy goal. I agree we should not waste vertical space.
I'm not yet convinced that we should have a special annotation that affects type inference
(and thus method overloading (and thus run-time behavior)).

Mark Harrah

unread,
Jun 4, 2012, 10:53:20 AM6/4/12
to scala-i...@googlegroups.com
The special annotation was a means to producing a prototype in a reasonable amount of time that passed the test suite. It helps to show that, for the special case I'm concerned about, it is possible to produce the same message as the non-overloaded case without affecting other code. This of course ignores it being an ugly solution I don't want to be associated with and wouldn't accept into a codebase that I had any say over. So, I have no problem disowning an annotation if the overloaded error message could be clearer for this case.

-Mark
Reply all
Reply to author
Forward
0 new messages