Skip to content

1.6.0 regression: new mutable.WrappedArrayBuilder(classTag[Unit]).result() throws a CCE #4507

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 Jun 9, 2021 · 0 comments
Assignees
Labels
bug Confirmed bug. Needs to be fixed.
Milestone

Comments

@sjrd
Copy link
Member

sjrd commented Jun 9, 2021

Using Scala 2.12, the following expression throws an UndefinedBehaviorError over a ClassCastException:

new mutable.WrappedArrayBuilder(classTag[Unit]).result()
org.scalajs.linker.runtime.UndefinedBehaviorError: java.lang.ClassCastException: [V@1 is not an instance of Ljava.lang.Object;
    at $throwClassCastException (main.js:52:9)
    at $throwArrayCastException (main.js:58:3)
    at $asArrayOf_O (main.js:811:5)
    at $c_scm_WrappedArray$.make__O__scm_WrappedArray (WrappedArray.scala:105:10)
    at $p_scm_WrappedArrayBuilder__mkArray__I__scm_WrappedArray (ClassTag.scala:54:33)
    at $c_scm_WrappedArrayBuilder.result__scm_WrappedArray (WrappedArrayBuilder.scala:110:17)
    at $c_Lhelloworld_HelloWorld$.main__AT__V (HelloWorld.scala:17:62)
    at $s_Lhelloworld_HelloWorld__main__AT__V (HelloWorld.scala:14:8)

As the error message shows, we managed to create a [V, i.e., a void[]. This is not even supposed to be possible. It should be a scala.runtime.BoxedUnit[], which in Scala.js is actually a java.lang.Void[].

This regression appeared upstream in scala/scala#9091. That PR changed WrappedArrayBuilder to use ClassTag.emptyWrappedArray, which was defined as

  @transient private[scala] lazy val emptyArray: Array[T] = {
    val componentType =
      if (runtimeClass eq classOf[Void]) classOf[BoxedUnit] else runtimeClass
    java.lang.reflect.Array.newInstance(componentType, 0).asInstanceOf[Array[T]]
  }
  @transient private[scala] lazy val emptyWrappedArray: mutable.WrappedArray[T] =
    mutable.WrappedArray.make[T](emptyArray)

We copied that implementation in our overrides for ClassTag in
636be50
Unfortunately, it turned out that it was buggy. It was later fixed upstream in
scala/scala@5e6676d
but we didn't notice that, so we didn't port the fix.


This blew up when scala-collection-compat tried to upgrade to Scala.js 1.6.0 in scala/scala-collection-compat#462

@sjrd sjrd added the bug Confirmed bug. Needs to be fixed. label Jun 9, 2021
@sjrd sjrd added this to the v1.6.1 milestone Jun 9, 2021
@sjrd sjrd self-assigned this Jun 9, 2021
@sjrd sjrd closed this as completed in a91fe8b Jun 10, 2021
sjrd added a commit that referenced this issue Jun 10, 2021
…lt-unit

Fix #4507: Fix ClassTag.emptyArray for classTag[Unit].
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Confirmed bug. Needs to be fixed.
Projects
None yet
Development

No branches or pull requests

1 participant