Skip to content
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

ClassCastException on calling vararg ctor #7436

Closed
scabug opened this issue Apr 30, 2013 · 18 comments
Closed

ClassCastException on calling vararg ctor #7436

scabug opened this issue Apr 30, 2013 · 18 comments
Assignees
Milestone

Comments

@scabug
Copy link

scabug commented Apr 30, 2013

This code fails at runtime:

scala> class A(val p: Int*); case class B(p1: Int) extends A(p1); new B(1)
java.lang.ClassCastException: scala.collection.mutable.WrappedArray$ofInt cannot be cast to java.lang.Integer

The error only occurs in combination of a case class extending a class taking a vararg ctor that is marked as val.

Looking at the generated code the bug is obvious:

def p1(): Int = scala.Int.unbox(Main$$anon$1$B.super.p());

and

def <init>($outer: anonymous class anon$1, p1: Int): anonymous class anon$1$B = {
      Main$$anon$1$B.super.<init>($outer, scala.this.Predef.wrapIntArray(Array[Int]{p1}));
      scala.Product$class./*Product$class*/$init$(Main$$anon$1$B.this);
      ()
    }
  };

p1 is not correctly set in the ctor of B. Instead it treats p as the same value and tries to get the value from it.

@scabug
Copy link
Author

scabug commented Apr 30, 2013

Imported From: https://issues.scala-lang.org/browse/SI-7436?orig=1
Reporter: @sschaef
Affected Versions: 2.10.1, 2.10.2, 2.10.3, 2.10.4, 2.10.5
See #6793

@scabug
Copy link
Author

scabug commented Apr 30, 2013

@paulp said:
Ugh, I question the purpose of even allowing "val p: Int*".

@scabug
Copy link
Author

scabug commented Apr 30, 2013

Stave Escura (stave.escura-at-gmail.com) said:
I raised a question that lead to this bug http://stackoverflow.com/questions/16294822/constructors-in-scala-with-varargs

In Java I need varargs in order to make any thing even slightly approaching a DSL (mostly in tests). I don't know if the need is as great in Scala.

The example in the link shows what I think is a sensible use of varargs. I have an alternative implementation using Lists, but the code is much more verbose and not nearly as readable. I'd really appreciate some idiomatically correct code that did the same thing as the example not using val p:Int*

@scabug
Copy link
Author

scabug commented Apr 30, 2013

@sschaef said:
a possible workaround is {code}class X(p: Int*) { def params: Seq[Int] = p }{code}

@scabug
Copy link
Author

scabug commented May 21, 2013

@retronym said:
Akin to #6793

@scabug
Copy link
Author

scabug commented May 21, 2013

@retronym said:
scala/scala#2576

@scabug
Copy link
Author

scabug commented Aug 23, 2013

@Sciss said:
Are you sure it is fixed? Because

Welcome to Scala version 2.10.3-RC1 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_33).
scala> class A(val p: Int*); case class B(p1: Int) extends A(p1); new B(1)
java.lang.ClassCastException: scala.collection.mutable.WrappedArray$ofInt cannot be cast to java.lang.Integer
at scala.runtime.BoxesRunTime.unboxToInt(BoxesRunTime.java:106)
at B.p1(<console>:18)
...

@scabug
Copy link
Author

scabug commented Sep 19, 2013

@Sciss said (edited on Sep 19, 2013 10:36:07 PM UTC):
Hi there, I still see this bug in 2.10.3-RC2. I don't think it was fixed

Welcome to Scala version 2.10.3-RC2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_33).
Type in expressions to have them evaluated.
Type :help for more information.

scala> class A(val p: Int*); case class B(p1: Int) extends A(p1); new B(1)
java.lang.ClassCastException: scala.collection.mutable.WrappedArray$ofInt cannot be cast to java.lang.Integer
	at scala.runtime.BoxesRunTime.unboxToInt(BoxesRunTime.java:106)
	at B.p1(<console>:7)
	at ...

@scabug
Copy link
Author

scabug commented Sep 19, 2013

@sschaef said:
Seems to be a regression / missing backport for 2.10.3. In 2.11 everything works as expected.

@scabug
Copy link
Author

scabug commented Sep 19, 2013

@Sciss said:
@simon - your workaround doesn't help when you have class A(val p: Any*); case class B(p1: Int) extends A(p1), if you need to access p1 as an Int.

@scabug
Copy link
Author

scabug commented Sep 20, 2013

@retronym said:
This had the wrong fix version:

 qbin/scala
Welcome to Scala version 2.11.0-20130919-080201-884e1ce762 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_37).
Type in expressions to have them evaluated.
Type :help for more information.

scala> class A(val p: Int*); case class B(p1: Int) extends A(p1); new B(1)
defined class A
defined class B
res0: B = B(1)

@scabug
Copy link
Author

scabug commented Mar 10, 2014

Adam Retter (adamretter) said:
It seems to be that this is a regression, as this works in Scala 2.10.0, however it does not work in any newer bugfix 2.10 version (i.e. 2.10.1, 2.10.2, 2.10.3 and 2.10.4-RC2). I believe that as this works in 2.10.0, it should work in all 2.10.x versions.

My test case is not as elegant as the one initially posted, but for completeness, here it is:

object Blah extends App {

  trait ArgProvider {
  }

  case class ColumnReference(value: String) extends ArgProvider


  abstract class Rule(name: String, val argProviders: ArgProvider*)

  case class InRule(inValue: ArgProvider) extends Rule("in", inValue) {

    def valid(): Boolean = {
      println(inValue.getClass) //This causes a ClassCastException on 2.10.1+ but not 2.10.0

      true
    }
  }

  val rule = InRule(ColumnReference("Column1"))
  rule.valid()
}

I have been suggested the workaround of defining the InRule class as:

case class InRule(inValue: ArgProvider) extends Rule("in", Seq(inValue): _*) {
  ...
}

Whilst the workaround helps me, I still have to modify my code to move onward from 2.10.0 to 2.10.1+ which is not ideal.

@scabug
Copy link
Author

scabug commented Mar 10, 2014

Adam Retter (adamretter) said:
I really believe this is a regression in 2.10.1+, as it works fine in 2.10.0. If I understand your semantic versioning scheme then bugfix releases should not introduce breaking changes, so I am classing this as a regression.

It is nice to know it is fixed in the upcoming 2.11, but not everyone has the luxury of being able to easily move to 2.11, especially when there is not yet a stable version.

@scabug
Copy link
Author

scabug commented Mar 10, 2014

@adriaanm said:
Fixed on 2.11.0-M4 (since it's a fix-version in the past), fix pending for 2.10.5-RC1.

@scabug
Copy link
Author

scabug commented Mar 10, 2014

@adriaanm said:
Sorry about the regression, Adam. Scheduled for a fix in 2.10.5-RC1.

@scabug
Copy link
Author

scabug commented Mar 10, 2014

Adam Retter (adamretter) said:
No worries Adriaan, we only just hit it in the last couple months. I just wanted to bump the Jira issue, in the hope it would get resolved. Thanks for looking into it.

@scabug
Copy link
Author

scabug commented Oct 1, 2014

@Sciss said:
Will this be fixed in 2.10.5? Last comment from Adriaan says pending, but date for 2.10.5-RC1 is in less than two weeks? Kind of sad to have a regression surviving through 4 or now 5 dot releases... Thanks!

@scabug
Copy link
Author

scabug commented Feb 26, 2015

@adriaanm said:
Unfortunately this didn't make it into 2.10.5. It is fixed in 2.11, though.

@scabug scabug closed this as completed Feb 26, 2015
@scabug scabug added this to the 2.11.0-M4 milestone Apr 7, 2017
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

2 participants