-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Varargs and currying in Selectable
's applyDynamic
#18009
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
Comments
@prolativ Since you were already looking at the issue would you be up to try to diagnose and fix this? |
@odersky how would we like to solve the problem then? Make the actual behaviour compliant with the specification of |
I don't know, and won't have the cycles to get deep into it. We need a simple fix. Just explore whatever can be made to work. |
I did some analysis and it seems like an attempt to bring the behaviours of
In both cases the shape of the signatures of def applyDynamic(name: String)(args: Int*)(arg: Int): Int = args.sum + arg (in case of def applyDynamic(name: String)(args: Int*): Int => Int = (arg: Int) => args.sum + arg so it will work for a refinement method like def foo(x: Int)(y: Int): Int => Int which is
def applyDynamic(name: String)(args: Int*)(x: Boolean)(y: String, z: Char): Int the normalized type would be def applyDynamic(name: String)(args: Int*): Boolean => (String, Char) => Int
class Sel2 extends Selectable {
def applyDynamic(name: String)(args: Int*)(arg: Int): Int = args.sum + arg
}
val sel2 = (new Sel2).asInstanceOf[Sel2 {
def foo(x: Int)(y: Int): Int
}] that would cause a compilation warning/error because The problem of dangling parameter lists in class Sel1 extends Selectable {
def applyDynamic(name: String)(args: Int*): Int = args.sum
}
val sel1 = (new Sel1).asInstanceOf[Sel1 {
def baz(xs: Int*)(ys: Int*): Int
}] we could try to make sel1.baz(1)(2) compile by desugaring it to sel1.applyDynamic("baz")(1, 2) but what about something like val ints1 = Seq(1)
sel1.baz(ints1*)(2) ? sel1.applyDynamic("baz")(ints1*, 2) is not something legal in general. On the other hand val ints2 = Seq(2)
sel1.baz(1)(ints2*) desugared as sel1.applyDynamic("baz")(1, ints2*) would make sense, although this seems quite inconsistent. @odersky any opinions on how we should handle these 2 problems? |
Compiler version
3.3.2-RC1-bin-20230615-916d4e7-NIGHTLY and before
Minimized code
Output
When one tries to compile and run the snippet from above after uncommenting only one commented line at a time, here's what happens in each case:
sel1.foo
:Compilation succeeds, prints
3
.Relevant
-Xprint:typer
output:sel1.bar
:Compilation error
Relevant
-Xprint:typer
output:sel2.foo
:Runtime exception
Relevant
-Xprint:typer
output:sel2.bar
:Compilation error
Relevant
-Xprint:typer
output:Expectation
The specification says:
Given a value
v
of typeC { Rs }
, whereC
is a class reference andRs
are structural refinement declarations, and givenv.a
of typeU
[...]U
is a method type(T11, ..., T1n)...(TN1, ..., TNn): R
and it is not a dependent method type, we mapv.a(a11, ..., a1n)...(aN1, ..., aNn)
to:Thus, according to the spec, the 4 cases should get desugared as follows:
sel1.foo(1)(2)
->sel1.applyDynamic("foo")(1, 2).asInstanceOf[Int]
sel1.bar(1)(2)
->sel1.applyDynamic("bar")(1, 2).asInstanceOf[Int]
sel2.foo(1)(2)
->sel2.applyDynamic("foo")(1, 2).asInstanceOf[Int]
sel2.bar(1)(2)
->sel2.applyDynamic("bar")(1, 2).asInstanceOf[Int]
The first two cases should compile successfully and return
3
then, while the latter two should either perform eta-expansion and fail at runtime with an exception on casting a function toInt
(we should try to avoid this situation) or complain about a missing parameter.On the other hand, as a user I would expect code using
Selectable
to behave analogously to code usingDynamic
instead.Thus, given the snippet below
and uncommenting a single line at a time, I get:
dyn1.foo
:dyn1.bar
:dyn2.foo
:Compiles, prints
3
dyn2.bar
:Compiles, prints
3
For
Dynamic
s the behaviour in scala 2 is basically the same, though the compilation errors fordyn1.foo
anddyn1.bar
are slightly different:Summing this up, the behaviour for
Dynamic
s in this case is the opposite to the specified behaviour forSelectable
, which in turn is different to the current actual (definitely buggy in some way) behaviour forSelectable
.The text was updated successfully, but these errors were encountered: