Could Scala pick the most specific ambiguous overload?

I was hoping Scala.js would be able to ignore ambiguous overloads for native JS traits since they have JavaScript semantics and in JavaScript there are no overloads. This isn’t possible since Scala.js is using the normal Scala type system. (See https://github.com/scala-js/scala-js/issues/4709)

I was wondering whether it would be possible for Scala to pick the overload for the type which is more specific?

So in this case:

object Main extends App {

  trait Bar
  trait Baz

  def foo(bar: Bar): String = "bar"
  def foo(bar: Baz): Int = 123

  object BarBaz extends Bar with Baz

  foo(BarBaz)

}

It would pick the second foo since Baz comes earlier in linearization.

If you want the other one then you would add the type ascription of Bar.

I had hoped to work around this by using implicit priorities but even that doesn’t work. For example:

import scala.language.implicitConversions

object Main2 extends App {

  trait Bar
  trait Baz

  def foo(bar: Bar): String = "bar"
  def foo(bar: Baz): Int = 123

  object BarBazImplicit extends LowerPriorityImplicit {
    implicit def toBar(me: BarBazImplicit.type): Bar = new Bar {}
  }

  trait LowerPriorityImplicit {
    implicit def toBaz(me: BarBazImplicit.type): Baz = new Baz {}
  }

  foo(BarBazImplicit)

}

This is easy in the case that there is only a single parameter but if there are two then it might still be ambiguous:

object Main3 extends App {

  trait Bar
  trait Baz

  def foo(bar: Bar, baz: Baz): String = "bar"
  def foo(baz: Baz, bar: Bar): Int = 123

  object BarBaz extends Bar with Baz

  foo(BarBaz, BarBaz)

}

This could either still be an error and be what you want in the majority of cases or it could look at the parameters from left to right until it finds one that is more specific.

1 Like