Making the scala compiler smarter about overloaded methods

67 views
Skip to first unread message

Hiram Chirino

unread,
Feb 1, 2011, 11:13:55 AM2/1/11
to scala-debate
When you have a couple of simple overloaded methods like:

object Log {
def log(m: String) = println("1:"+m)
def log(m: String, args: Any*) = println("2:"+m)
}
Log.log("test")
Log.log("test", 1)

The scala compiler is smart enough pick the right method, for example:

1:test
2:test

But in case like this:

object Log {
def log(m: => String) = println("1:"+m)
def log(m: String, args: Any*) = println("2:"+m)
}
Log.log("test")
Log.log("test", 1)

I complains with:

error: ambiguous reference to overloaded definition,
both method log in object Log of type (m: String,args: Any*)Unit
and method log in object Log of type (m: => String)Unit
match argument types (java.lang.String)
Log.log("test")

My question is why is it smart enough in the first case, but not the
second?

Hiram Chirino

unread,
Feb 6, 2011, 8:37:34 AM2/6/11
to scala-debate
Anyone out there?

HamsterofDeath

unread,
Feb 6, 2011, 9:11:28 AM2/6/11
to scala-...@googlegroups.com
i have another question: why doesn't the compiler complain about the
first case as well? both methods match. there is no "right method".

martin odersky

unread,
Feb 6, 2011, 9:20:16 AM2/6/11
to HamsterofDeath, scala-...@googlegroups.com
On Sun, Feb 6, 2011 at 3:11 PM, HamsterofDeath <h-s...@gmx.de> wrote:
> i have another question: why doesn't the compiler complain about the
> first case as well? both methods match. there is no "right method".
>

These are not questions about the compiler but about the language. The
language does have a spec that talks about these
things (section on overloading resolution). Both questions which have
been brought up here can be resolved by consulting the spec.
Any suggestion to do differently would have to propose a different
wording of the spec.

Cheers

-- Martin

Chirino, Hiram

unread,
Feb 8, 2011, 8:06:05 AM2/8/11
to scala-...@googlegroups.com
Accidentally went off list. Bringing back.

On Mon, Feb 7, 2011 at 5:49 PM, martin odersky <martin....@epfl.ch> wrote:
> On Mon, Feb 7, 2011 at 11:44 PM, Chirino, Hiram <chi...@fusesource.com> wrote:
>>
>> Seems to me that at since the there is no way for the caller to force
>> a => T type, overloading should consider all => T as being T when
>> comparing the type arguments of an overloaded method for purposes of
>> finding a more specific method.
>>
> There are good reasons why we do not want that. Notably, we want a
> method taking a T to be more specific than a method taking a => T.
> Believe me, it's pretty carefully calibrated.
>
> Cheers
>
>  -- Martin

Yeah seems delicate.  Ok here's my last shot at it then:  do in 2
passes, the first
pass does it like it's currently done, and if it's still ambiguous
then do a second pass with the => T to T conversion trick in hopes
that it gives you an un-ambiguous selection.

Should give us the best of both worlds.

--
Regards,
Hiram

FuseSource
Web: http://fusesource.com/

--
Regards,
Hiram

FuseSource
Web: http://fusesource.com/

Chirino, Hiram

unread,
Feb 8, 2011, 10:07:55 AM2/8/11
to scala-...@googlegroups.com
On Tue, Feb 8, 2011 at 8:18 AM, martin odersky <martin....@epfl.ch> wrote:

> On Tue, Feb 8, 2011 at 12:22 AM, Chirino, Hiram <chi...@fusesource.com> wrote:
>> On Mon, Feb 7, 2011 at 5:49 PM, martin odersky <martin....@epfl.ch> wrote:
>>> On Mon, Feb 7, 2011 at 11:44 PM, Chirino, Hiram <chi...@fusesource.com> wrote:
>>>>
>>>> Seems to me that at since the there is no way for the caller to force
>>>> a => T type, overloading should consider all => T as being T when
>>>> comparing the type arguments of an overloaded method for purposes of
>>>> finding a more specific method.
>>>>
>>> There are good reasons why we do not want that. Notably, we want a
>>> method taking a T to be more specific than a method taking a => T.
>>> Believe me, it's pretty carefully calibrated.
>>>
>>> Cheers
>>>
>>>  -- Martin
>>
>> Yeah seems delicate.  Ok here's my last shot at it then:  do in 2
>> passes, the first
>> pass does it like it's currently done, and if it's still ambiguous
>> then do a second pass with the => T to T conversion trick in hopes
>> that it gives you an un-ambiguous selection.
>>
>
> You'd need to write spec language for that and convince everyone that
> (a) nothing breaks and (b) the added complications are worth it. It's
> a huge and very hard task, which requires a SIP. Overloading
> resolution is one of the most subtle parts of both the Java and the
> Scala specs. You fiddle with it at your own risk ;-)
>
> Cheers
>
>  -- Martin
>

Fair enough. I'm not a language spec guru, so I'm not sure I'd be
able help much on that front. But I was able implement the change we
discussed and it seems to be working swimmingly. You can find the
patch at:

https://github.com/chirino/scala/commit/bc0ff4bae0121ba6fc7c4d12acd122bc460f26b4

With this patch in place, overloaded method resolution is 100%
backward compatible since the change only kicks in when the compiler
would have failed due to the method being ambiguous. With the patch
in place you now have the chance to call methods which were previously
thought ambiguous.

Paul Phillips

unread,
Feb 8, 2011, 12:45:21 PM2/8/11
to Chirino, Hiram, scala-...@googlegroups.com
On 2/8/11 7:07 AM, Chirino, Hiram wrote:
> Fair enough. I'm not a language spec guru, so I'm not sure I'd be
> able help much on that front. But I was able implement the change we
> discussed and it seems to be working swimmingly.

Yay for people who implement their ideas. (Or even try.)

There are multiple precedents for "try it this way, and then try it that
way only if it would otherwise fail" in the compiler. That said, they
are not embraced with enthusiasm.

What you want here seems pretty reasonable to me if only because there
is no way I can see to disambiguate the overload you're looking at in
favor of the by-name argument. So it will let you compile something
which you can never use, a situation I am always eager to avoid. I'm
not sure if it has been pointed out, but you can disambiguate it the
other way like this:

foo(arg, Nil: _*)

Hiram Chirino

unread,
Feb 27, 2011, 7:14:35 AM2/27/11
to Chirino, Hiram, scala-...@googlegroups.com
Hi,

Anyone had chance to peek at that patch? It's applying the additional
overloading resolution attempt in the tryTwice method which was also
using the same strategy to handle resolution with implicits
enabled/disabled.

BTW where is the wording in the spec which covers that try again
behavior that the compiler is currently using for the implicits? I'm
sure we could probably extend it a little so it also cover the case
that my patch is covering.

On Tue, Feb 8, 2011 at 10:07 AM, Chirino, Hiram <chi...@fusesource.com> wrote:

>>
>> You'd need to write spec language for that and convince everyone that
>> (a) nothing breaks and (b) the added complications are worth it. It's
>> a huge and very hard task, which requires a SIP. Overloading
>> resolution is one of the most subtle parts of both the Java and the
>> Scala specs. You fiddle with it at your own risk ;-)
>>
>> Cheers
>>
>>  -- Martin
>>
>
> Fair enough.  I'm not a language spec guru, so I'm not sure I'd be
> able help much on that front.  But I was able implement the change we
> discussed and it seems to be working swimmingly.  You can find the
> patch at:
>
> https://github.com/chirino/scala/commit/bc0ff4bae0121ba6fc7c4d12acd122bc460f26b4
>
> With this patch in place, overloaded method resolution is 100%
> backward compatible since the change only kicks in when the compiler
> would have failed due to the method being ambiguous.  With the patch
> in place you now have the chance to call methods which were previously
> thought ambiguous.
>
> --
> Regards,
> Hiram
>
> FuseSource
> Web: http://fusesource.com/
>

---

Reply all
Reply to author
Forward
0 new messages