Skip to content
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

Overloading regression in Scala 3 #14699

Closed
soronpo opened this issue Mar 16, 2022 · 7 comments · Fixed by #14719
Closed

Overloading regression in Scala 3 #14699

soronpo opened this issue Mar 16, 2022 · 7 comments · Fixed by #14719
Labels
area:overloading itype:bug regression This worked in a previous version but doesn't anymore
Milestone

Comments

@soronpo
Copy link
Contributor

soronpo commented Mar 16, 2022

The following works in 2.13, but fails in Scala 3.

Compiler version

v3.1.2-RC1

Minimized code

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

def always(block: => Unit): Unit = {}
def always(args: Int*)(block: => Unit): Unit ={}

always{} //error
always(1,2,3) {}

Output

None of the overloaded alternatives of method always in object Playground with types
 (args: Int*)(block: => Unit): Unit
 (block: => Unit): Unit
match arguments (<nonsensical><notype></nonsensical>)

Expectation

No error, same as in Scala 2.13

@soronpo soronpo added itype:bug area:overloading regression This worked in a previous version but doesn't anymore labels Mar 16, 2022
@som-snytt
Copy link
Contributor

som-snytt commented Mar 16, 2022

I guess it works in 2.13 not because of specificity but because "if the result expr of the block is omitted, unit is assumed".

scala 2.13.8> object X {
            | def always(block: => Unit): Unit = println(s"OK $block")
            | def always(args: Int*)(block: => Unit): Unit = println(s"Well, ${args.sum} and $block")
            | }
object X

scala 2.13.8> X.always _
                ^
              error: ambiguous reference to overloaded definition,
              both method always in object X of type (args: Int*)(block: => Unit): Unit
              and  method always in object X of type (block: => Unit): Unit
              match expected type ?

scala 2.13.8> X.always {}
OK ()

I thought 2.13 preferred non-varargs, but by tupling and discarding

scala 2.13.8> def f(body: => Unit) = ()
def f(body: => Unit): Unit

scala 2.13.8> f(1,2,3)

Tangentially, #14700

@odersky
Copy link
Contributor

odersky commented Mar 19, 2022

I think this is indeed ambiguous according to spec.

@odersky odersky closed this as completed Mar 19, 2022
@som-snytt
Copy link
Contributor

The expectation is that if it works with explicit unit value, it should work when the unit value is implicit. Only one alternative is applicable.

scala> object X {
     | def always(block: => Unit): Unit = println(s"OK $block")
     | def always(args: Int*)(block: => Unit): Unit = println(s"Well, ${args.sum} and $block")
     | }
// defined object X

scala> X.always {()}
OK ()

scala> X.always {}
-- [E134] Type Error: --------------------------------------------------------------------------------------------------
1 |X.always {}
  |^^^^^^^^
  |None of the overloaded alternatives of method always in object X with types
  | (args: Int*)(block: => Unit): Unit
  | (block: => Unit): Unit
  |match arguments (<notype>)
1 error found

@soronpo
Copy link
Contributor Author

soronpo commented Mar 19, 2022

I think this is indeed ambiguous according to spec.

Maybe the behavior is undefined according to the spec, but it's not defined that it's illegal as well. So where the spec is ambiguous/undefined we turn to the existing implementation. The Scala 2 compiler implementation accepts this as legal code. Therefore, I think we need to stick to that as the de facto specified behavior and treat the Scala 3 implementation as a regression.

@som-snytt
Copy link
Contributor

som-snytt commented Mar 19, 2022

@soronpo That comment meant that unapplied X.always is "ambiguous reference", as in the error message in my transcript, not that the spec is ambiguous on this point. But I think the error message you're getting is just a bug. My first comment wasn't clear.

I think my previous comment is the correct interpretation of X.always {}, namely, that it is the same as X.always {()} and should also work without controversy.

@odersky
Copy link
Contributor

odersky commented Mar 20, 2022

I misread the example. In fact there is no ambiguity. {} as an argument is equivalent to (()) and that determines the alternative unambiguously.

@soronpo
Copy link
Contributor Author

soronpo commented Mar 20, 2022

Thank you @odersky

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:overloading itype:bug regression This worked in a previous version but doesn't anymore
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants