Skip to content

The apply syntax does not work with scala.Dynamic's applyDynamic/applyDynamicNamed #9462

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
sjrd opened this issue Jul 29, 2020 · 0 comments
Closed

Comments

@sjrd
Copy link
Member

sjrd commented Jul 29, 2020

Minimized code

import scala.language.dynamics

object MyDynamic {
  object literal extends scala.Dynamic {
    def applyDynamic(name: String)(args: Any*): Any =
      "applyDynamic: " + name + " -> " + args
    def applyDynamicNamed(name: String)(args: (String, Any)*): Any =
      "applyDynamicNamed: " + name + " -> " + args
  }
}

object Test {
  def main(args: Array[String]): Unit = {
    println(MyDynamic.literal())
    println(MyDynamic.literal("foobar"))
    println(MyDynamic.literal(foo = "Foo", bar = 42))
  }
}

Output

-- [E008] Not Found Error: tests\run\hello.scala:14:22 -------------------------
14 |    println(MyDynamic.literal())
   |            ^^^^^^^^^^^^^^^^^
   |value applyDynamic is not a member of object MyDynamic, but could be made available as an extension method.
   |
   |The following import might fix the problem:
   |
   |  import reflect.Selectable.reflectiveSelectable
   |
-- [E008] Not Found Error: tests\run\hello.scala:15:22 -------------------------
15 |    println(MyDynamic.literal("foobar"))
   |            ^^^^^^^^^^^^^^^^^
   |value applyDynamic is not a member of object MyDynamic, but could be made available as an extension method.
   |
   |The following import might fix the problem:
   |
   |  import reflect.Selectable.reflectiveSelectable
   |
-- [E008] Not Found Error: tests\run\hello.scala:16:22 -------------------------
16 |    println(MyDynamic.literal(foo = "Foo", bar = 42))
   |            ^^^^^^^^^^^^^^^^^
   |            value applyDynamicNamed is not a member of object MyDynamic
3 errors found

Expectation

It runs and outputs the following:

applyDynamic: apply -> ArraySeq()
applyDynamic: apply -> ArraySeq(foobar)
applyDynamicNamed: apply -> ArraySeq((foo,Foo), (bar,42))

Notes

This works in Scala 2.

Explicitly calling .apply makes it work in Dotty as well:

    println(MyDynamic.literal.apply())
    println(MyDynamic.literal.apply("foobar"))
    println(MyDynamic.literal.apply(foo = "Foo", bar = 42))

This is necessary for Scala.js, because this is how js.Dynamic.literal is defined. All code using js.Dynamic.literal hits this issue at the moment.

sjrd added a commit to dotty-staging/dotty that referenced this issue Aug 18, 2020
…c treatment.

Previously, identifying when there was an inserted apply, which had
to be carried through the Dynamic treatment, was done on a
syntactical basis. This would mishandle cases written as

  someContainer.someDynamic()

as it would think that this was an explicit dynamic call for
`"someDynamic"` on `someContainer` (although `someContainer` is not
even a `scala.Dynamic` itself, but `someContainer.someDynamic` is).

We now reliably detect inserted applys by looking at the result of
the pre-type-checking of the function part, and testing whether
there is a synthetic `Select(_, nme.apply)` node.
@sjrd sjrd closed this as completed in 22010f6 Aug 19, 2020
sjrd added a commit that referenced this issue Aug 19, 2020
…apply-insertion

Fix #9462: Identify inserted apply's more reliably in the Dynamic treatment.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant