Skip to content

Conversation

@tanishiking
Copy link
Member

@tanishiking tanishiking commented Dec 4, 2025

Fixes #24072

When comparing overloaded methods where one is non-varargs with wildcard types (e.g., Class[? <: T]) and another is varargs, the non-varargs method should be preferred.
Previously, the compiler failed to distinguish these methods , and results in an ambiguity error.

def blub[T](a: Class[? <: T]): Unit // m1
def blub[T](a: Class[T], ints: Int*): Unit // m2
blub(classOf[Object]) // m1 should be picked, but fails to resolve

The problem is compare(m1, m2) returned 0 because:

  • (1). m2 (varargs) is correctly considered "not as good" as m1.
  • (2). m1 (non-varargs) was also considered "not as good" as m2. (but m1 should be as good as m2! because Class[Concrete] can be applied to both m1 and m2).

The (2) occurred because Class[? <: T] is not a subtype of Class[T] (due to invariance). Consequently, isApplicableMethodRef(m2, Class[? <: T]) returned false because isCompatible(Class[? <: T], Class[T]) returned false during the applicability check against the method.

This commit adds special handling in TestApplication.argOK to check if wildcard upper bounds are compatible with their formal types during overload resolution, in addition to isCompatible.

Fixes scala#24072

When comparing overloaded methods where one is non-varargs with wildcard types (e.g., `Class[? <: T]`) and another is varargs, the non-varargs method should be preferred.
Previously, the compiler failed to distinguish these methods , and results in an ambiguity error.

```scala
def blub[T](a: Class[? <: T]): Unit // m1
def blub[T](a: Class[T], ints: Int*): Unit // m2
blub(classOf[Object]) // m1 should be picked, but fails to resolve
````

The problem is `compare(m1, m2)` returned 0 because:

- (1). `m2` (varargs) is correctly considered "not as good" as `m1`.
- (2). `m1` (non-varargs) was also considered "not as good" as `m2`. (but `m1` should be as good as `m2`! because `Class[Concrete]` can be applied to both m1 and m2).

The (2) occurred because `Class[? <: T]` is not a subtype of `Class[T]` (due to invariance). Consequently, `isApplicableMethodRef(m2, Class[? <: T])` returned `false` because `isCompatible(Class[? <: T], Class[T])` returned `false` during the applicability check against the method.

This commit adds special handling in `TestApplication.argOK` to check if wildcard upper bounds are compatible with their formal types during overload resolution, in addition to `isCompatible`.
@tanishiking tanishiking force-pushed the i24072 branch 2 times, most recently from 801fc51 to b8e3f98 Compare December 5, 2025 09:02
@tanishiking tanishiking marked this pull request as ready for review December 5, 2025 12:12
@tanishiking tanishiking changed the title Prefer non-varargs methods in overload resolution when tiebreaker Fix varargs overload resolution with wildcard types Dec 5, 2025
@tanishiking tanishiking requested a review from odersky December 8, 2025 10:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Ambiguous overload when involving wildcard types and variadic parameters

2 participants