Skip to content

Extension method with default argument fails to construct #14278

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
soronpo opened this issue Jan 16, 2022 · 3 comments · Fixed by #17510
Closed

Extension method with default argument fails to construct #14278

soronpo opened this issue Jan 16, 2022 · 3 comments · Fixed by #17510

Comments

@soronpo
Copy link
Contributor

soronpo commented Jan 16, 2022

Compiler version

v3.1.1-RC2

Minimized code

https://scastie.scala-lang.org/MiSpvFT0SKygDNEJdezOzQ

class Foo

extension (foo : Foo)
  def patch(arg : List[Int], arg2 : Int = 0) : Unit = {}
  def patch(arg : Int) : Unit = patch(List(arg))

Output

value patch is not a member of Playground.Foo.
An extension method was tried, but could not be fully constructed:

    Playground.patch()

Expectation

No error.

@odersky
Copy link
Contributor

odersky commented Mar 13, 2022

The problem comes from a combination of overloading, currying, and default arguments. It has nothing to do with extension methods. For instance:

class Foo

object Test {
  def patch2(foo: Foo)(arg : List[Int], arg2 : Int = 0) : Unit = {}
  def patch2(foo: Foo)(arg : Int) : Unit = patch2(foo)(List(arg))
}

fails with

-- [E134] Type Error: i14278a.scala:5:43 ---------------------------------------
5 |  def patch2(foo: Foo)(arg : Int) : Unit = patch2(foo)(List(arg))
  |                                           ^^^^^^
  |None of the overloaded alternatives of method patch2 in object Test with types
  | (foo: Foo)(arg: Int): Unit
  | (foo: Foo)(arg: List[Int], arg2: Int): Unit
  |match arguments ((foo : Foo))
1 error found

Scala 2.13 also fails here:

14278a.scala:5: error: ambiguous reference to overloaded definition,
both method patch2 in object Test of type (foo: Foo)(arg: Int): Unit
and  method patch2 in object Test of type (foo: Foo)(arg: List[Int], arg2: Int): Unit
match argument types (Foo)
  def patch2(foo: Foo)(arg : Int) : Unit = patch2(foo)(List(arg))
                                           ^
1 error

Maybe the advice (requirement?) should be that overloaded curried methods (which includes extension methods) cannot have default arguments.

@soronpo
Copy link
Contributor Author

soronpo commented Mar 13, 2022

Or the advice could be to use implicit classes, since we don't have the problem there. It's incorrect to compare Scala 2.13 according to how extension methods are desugared. Scala 2.13 has implicit classes and that is what extension methods are meant to replace. From user perspective I do not care about the desugaring. I care about expressiveness.

@som-snytt
Copy link
Contributor

som-snytt commented Mar 13, 2022

I don't think default args should break this case. If one alternative is applicable, then it is selected; if more than one is applicable, then alternatives requiring default args are discarded. Edit: changed in #14775

ckipp01 added a commit to ckipp01/dotty that referenced this issue May 15, 2023
nicolasstucki added a commit that referenced this issue May 16, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants