Skip to content

Conversation

@tanishiking
Copy link
Member

Fixes #24072

Add a tiebreaker in the compare method to prefer non-varargs methods over varargs methods when both alternatives are equally specific.

isAsGood function normally prefer varargs methods. However, it can fail to distinguish methods when wildcard types are involved with invariant type parameters. For example:

def blub[T](a: Class[? <: T]): Unit // m1 def blub[T](a: Class[T], ints: Int*): Unit // m2 blub(classOf[Object])

Here, compare(m1, m2) returns 0 (ambiguous) because both winsType1 and winsType2 are false:

  • m2 is not as good as m1 (this is correct: a varargs method can only be as good as another varargs method).
  • m1 is NOT as good as the m2 because Class[? <: T] is not a subtype of Class[T] (Class is invariant)

The new tiebreaker resolves this ambiguities by preferring non-varargs methods as a final comparison step when owner hierarchy and type-based comparisons don't distinguish the alternatives.

// For example, when comparing:
// def m[T](a: Class[? <: T]): Unit
// def m[T](a: Class[T], ints: Int*): Unit
// Both winsType1 and winsType2 are false because Class[? <: T] is not
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given

  • m1 = def m[T](a: Class[? <: T]): Unit
  • m2 = def m[T](a: Class[T], ints: Int*): Unit

isAsGood(m1, m2) returns false because here

isApplicableMethodRef(alt2, tp1.paramInfos, WildcardType, ArgMatch.Compatible)

isApplicableMethodRef(m2, List(Class[? <: T]) is false, because Class[? <: T] <: Class[T] doesn't hold.

Fixes scala#24072 Add a tiebreaker in the `compare` method to prefer non-varargs methods over varargs methods when both alternatives are equally specific. `isAsGood` function normally prefer varargs methods. However, it can fail to distinguish methods when wildcard types are involved with invariant type parameters. For example: ```scala def blub[T](a: Class[? <: T]): Unit // m1 def blub[T](a: Class[T], ints: Int*): Unit // m2 blub(classOf[Object]) ``` Here, `compare(m1, m2)` returns 0 (ambiguous) because both `winsType1` and `winsType2` are false: - `m2` is not as good as `m1` (this is correct: a varargs method can only be as good as another varargs method). - `m1` is NOT as good as the `m2` because Class[? <: T] is not a subtype of Class[T] (Class is invariant) The new tiebreaker resolves this ambiguities by preferring non-varargs methods as a final comparison step when owner hierarchy and type-based comparisons don't distinguish the alternatives.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

1 participant