Skip to content

BoxedUnit cannot be cast to class scala.Function0 #14700

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

Open
som-snytt opened this issue Mar 16, 2022 · 6 comments
Open

BoxedUnit cannot be cast to class scala.Function0 #14700

som-snytt opened this issue Mar 16, 2022 · 6 comments

Comments

@som-snytt
Copy link
Contributor

Compiler version

Minimized code

Welcome to Scala 3.1.3-RC1-bin-SNAPSHOT-git-d38e10e (17.0.2, Java OpenJDK 64-Bit Server VM).
Type in expressions for evaluation. Or try :help.

scala> def g(args: Int*)(block: => Unit): Unit = println(s"Well, ${args.sum} and $block")
def g(args: Int*)(block: => Unit): Unit

scala> def f = g()
def f: (=> Unit) => Unit

scala> f(println("x"))
x
java.lang.ClassCastException: class scala.runtime.BoxedUnit cannot be cast to class scala.Function0 (scala.runtime.BoxedUnit and scala.Function0 are in unnamed module of loader java.net.URLClassLoader @535b8c24)
  at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
  at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
  ... 33 elided

Expectation

Welcome to Scala 2.13.8 (OpenJDK 64-Bit Server VM, Java 17.0.2).
Type in expressions for evaluation. Or try :help.

scala> def g(args: Int*)(block: => Unit): Unit = println(s"Well, ${args.sum} and $block")
def g(args: Int*)(block: => Unit): Unit

scala> def f = g()
                ^
       error: missing argument list for method g
       Unapplied methods are only converted to functions when a function type is expected.
       You can make this conversion explicit by writing `g _` or `g(_)(_)` instead of `g`.

scala> def f = g() _
def f: (=> Unit) => Unit

scala> f(println("x"))
x
Well, 0 and ()
@som-snytt som-snytt added itype:bug stat:needs triage Every issue needs to have an "area" and "itype" label labels Mar 16, 2022
@odersky odersky added stat:cannot reproduce and removed stat:needs triage Every issue needs to have an "area" and "itype" label labels Mar 19, 2022
@odersky
Copy link
Contributor

odersky commented Mar 19, 2022

I can't reproduce this in 3.1.2-RC2.

@odersky odersky closed this as completed Mar 19, 2022
@griggt
Copy link
Contributor

griggt commented Mar 19, 2022

I can't reproduce this in 3.1.2-RC2.

It only happens on main, seems to be a result of #14295

@som-snytt
Copy link
Contributor Author

Thanks, I was just about to identify a commit.

@odersky
Copy link
Contributor

odersky commented Mar 19, 2022

It only happens in the repl of main as far as I can see. The following program works as expected:

object l1:
  def g(args: Int*)(block: => Unit): Unit = println(s"Well, ${args.sum} and $block")
object l2:
  import l1.*
  def f = g()
@main def Test =
  import l1.*
  import l2.*
  f(println("x"))

@som-snytt
Copy link
Contributor Author

I confirmed it also compiles under separate compilation, so I'll try to see what's wrong with REPL.

@som-snytt
Copy link
Contributor Author

I picked this up. I'll try to PR before it catches odersky's attention. It's only the REPL.

Currently, with g and f precompiled:

scala> f(println("x"))
x
x
Well, 0 and (), ()

scala> f(println("x"))
x
java.lang.ClassCastException: class scala.runtime.BoxedUnit cannot be cast to class scala.Function0 (scala.runtime.BoxedUnit and scala.Function0 are in unnamed module of loader java.net.URLClassLoader @4bee18dc)
  at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
  at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
  ... 34 elided

Until now, I compared various permutations, but forgot to ask if it works twice, a classic question for resident compiler.

First time,

// elimByName
    val res0: Unit =
      f.apply(
        {
          def $anonfun(): Unit = println("x")
          closure($anonfun:() ?=> Unit)
        }
      )
// erasure
    def res0(): scala.runtime.BoxedUnit =
      f().apply(
        {
          def $anonfun(): Unit = println("x")
          {
            def $anonfun$adapted(): Object =
              {
                $anonfun()
                scala.runtime.BoxedUnit#UNIT
              }
            closure($anonfun$adapted:Function0)
          }
        }
      ).asInstanceOf[scala.runtime.BoxedUnit]

where erasure is too boxy. Second time, elimByName sits on the bench.

// erasure
    def res0(): scala.runtime.BoxedUnit =
      f().apply(
        {
          println("x")
          scala.runtime.BoxedUnit#UNIT
        }
      ).asInstanceOf[scala.runtime.BoxedUnit]

scalac says

// erasure
    def main(args: String[]): Unit =
      {
        f().apply(
          {
            def $anonfun(): Unit = println("x")
            {
              def $anonfun$adapted(): Object =
                {
                  $anonfun()
                  scala.runtime.BoxedUnit#UNIT
                }
              closure($anonfun$adapted:Function0)
            }
          }
        )
        ()
      }

Also scalac under some regime:

@main def test(): Int = f[Unit](println("x"))

@som-snytt som-snytt removed their assignment Oct 10, 2022
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

4 participants