Skip to content

AbstractMethodError or IllegalAccessError exception calling member of a specialized class in another module #12222

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
OndrejSpanel opened this issue Nov 9, 2020 · 3 comments · Fixed by scala/scala#9703
Assignees
Milestone

Comments

@OndrejSpanel
Copy link
Member

reproduction steps

using Scala 2.13.3, 2.12.2, 2.11.12 or 2.10.7 (other versions not tested)

Clone https://github.com/OndrejSpanel/SpecRepro or use the files as below:

Buffer.scala:

trait ABuffer[@specialized(Float)T] {
  def count: Int
}

class Buffer[@specialized(Float) T](array_par: Array[T]) extends ABuffer[T] {
  var array: Array[T] = array_par

  var count: Int = 0
}

class Float32Buffer(array_par: Array[Float]) extends Buffer[Float](array_par)

Main.scala:

object Main extends App {

  val vertices = Array[Float]()

  val attribute = new Float32Buffer(vertices)
  println(attribute.count)

}

build.sbt:

name := "SpecRepro"

val commonSettings = Seq(scalaVersion := "2.13.3")

lazy val root = (project in file(".")).settings(commonSettings)

lazy val examples = (project in file("examples")).dependsOn(root).settings(commonSettings)

problem

When running Main, an exception java.lang.AbstractMethodError is thrown.

Notes

This is extracted from a real-life problem, where the module root is in fact a library used in a different sbt project.

  • the issue cannot be seen if both sources are located in the same SBT module
  • the issue goes away if you change var count to def count
  • the issue goes away if you change var array to var array: Array[T] = _
  • the issue goes away if you remove any of the two @specialized annotations
  • if you change var count to val count, an exception java.lang.IllegalAccessError si thrown instead

I was unable to reproduce the issue with Dotty 0.27.0-RC1

@SethTisue
Copy link
Member

I was unable to reproduce the issue with Dotty 0.27.0-RC1

Dotty simply ignores @specialized

@OndrejSpanel
Copy link
Member Author

It seems the issue was already described in http://aleksandar-prokopec.com/2013/11/03/specialization-quirks.html:

Specialization in 2.10 has a problem of specializing constructors in some cases

With explanation and a workaround:

I won’t get into why the above fails the way it fails - suffices to say that the specialization creates specialized fields in the specialized variants of the class and does not properly rewire the bridges for the field accessor methods in the constructor body correctly. Here is the pattern to solve the above issues - create a method init in which you initialize the troublesome fields:

@SethTisue SethTisue added this to the Backlog milestone Nov 10, 2020
@joroKr21
Copy link
Member

joroKr21 commented Jul 13, 2021

Looks like the names are mangled for some reason:

scala> typeOf[Buffer[_]].decls.toList.map(_.name).foreach(println)
array_par
<init>
array
array_$eq
array
$line3$$read$$iw$Buffer$$count
$line3$$read$$iw$Buffer$$count_$eq
$line3$$read$$iw$Buffer$$count

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants