Quantcast

Upgrading to Scala 2.12.1 causes ClassCastExceptions

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Upgrading to Scala 2.12.1 causes ClassCastExceptions

Michael Thaler
Hi,

I tried to compile / run our project with Scala 2.12.1 and now get ClassCastExceptions. The code ran fine with Scala 2.11.8.

The following code shows the problem:

package variant

object Variant {
sealed trait ValueType
case object ByteValue extends ValueType
case object ShortValue extends ValueType
case object IntValue extends ValueType
case object LongValue extends ValueType


trait Unwrapper[@specialized(Byte, Short, Int, Long) P] {
def unwrap(v: Variant): P = v.value.asInstanceOf[P]
}

def apply(value: Byte): Variant = Variant(value, ByteValue)

def apply(value: Short): Variant = Variant(value, ShortValue)

def apply(value: Int): Variant = Variant(value, IntValue)

def apply(value: Long): Variant = Variant(value, LongValue)
}

case class Variant(value: Long, valueType: Variant.ValueType)

package variant

import variant.Variant.Unwrapper

object Main extends App with Unwrapper[Byte] {
val v = Variant(42.toByte)
val result = unwrap(v)
println(result)
}

I get the same exception using Scala 2.12.0

Looking at the Scala 2.12 and Scala 2.12.1 change logs I could not find anything that explains this behavior.

What's causing this and how can I get the code working with Scala 2.12.1?

Best regards,
Michael

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Upgrading to Scala 2.12.1 causes ClassCastExceptions

Oliver Ruebenacker

     Hello,

  Could you post the exception message and stack trace and mark where in the code it is thrown? Thanks!

     Best, Oliver

On Tue, Jan 3, 2017 at 7:10 AM, Michael Thaler <[hidden email]> wrote:
Hi,

I tried to compile / run our project with Scala 2.12.1 and now get ClassCastExceptions. The code ran fine with Scala 2.11.8.

The following code shows the problem:

package variant

object Variant {
sealed trait ValueType
case object ByteValue extends ValueType
case object ShortValue extends ValueType
case object IntValue extends ValueType
case object LongValue extends ValueType


trait Unwrapper[@specialized(Byte, Short, Int, Long) P] {
def unwrap(v: Variant): P = v.value.asInstanceOf[P]
}

def apply(value: Byte): Variant = Variant(value, ByteValue)

def apply(value: Short): Variant = Variant(value, ShortValue)

def apply(value: Int): Variant = Variant(value, IntValue)

def apply(value: Long): Variant = Variant(value, LongValue)
}

case class Variant(value: Long, valueType: Variant.ValueType)

package variant

import variant.Variant.Unwrapper

object Main extends App with Unwrapper[Byte] {
val v = Variant(42.toByte)
val result = unwrap(v)
println(result)
}

I get the same exception using Scala 2.12.0

Looking at the Scala 2.12 and Scala 2.12.1 change logs I could not find anything that explains this behavior.

What's causing this and how can I get the code working with Scala 2.12.1?

Best regards,
Michael

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.



--
Oliver Ruebenacker
Senior Software Engineer, Diabetes Portal, Broad Institute

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Upgrading to Scala 2.12.1 causes ClassCastExceptions

Seth Tisue-3
shorter reproduction:

trait Unwrapper[@specialized(Byte) P] {
  def unwrap: P = 0L.asInstanceOf[P]
}
(new Unwrapper[Byte] {}).unwrap

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Upgrading to Scala 2.12.1 causes ClassCastExceptions

Michael Thaler
In reply to this post by Oliver Ruebenacker
Hi,

  Could you post the exception message and stack trace and mark where in the code it is thrown? Thanks!

The exception is:

 java.lang.ClassCastException: java.lang.Long cannot be cast to java.lang.Byte
        at scala.runtime.BoxesRunTime.unboxToByte(BoxesRunTime.java:93)
        at variant.Variant$Unwrapper.unwrap$mcB$sp(Variant.scala:12)
        at variant.Variant$Unwrapper.unwrap$mcB$sp$(Variant.scala:12)
        at variant.Main$.unwrap$mcB$sp(Main.scala:5)
        at variant.Main$.delayedEndpoint$variant$Main$1(Main.scala:7)
        at variant.Main$delayedInit$body.apply(Main.scala:5)
        at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
        at scala.App.$anonfun$main$1$adapted(App.scala:76)
        at scala.collection.immutable.List.foreach(List.scala:378)
        at scala.App.main(App.scala:76)
        at scala.App.main$(App.scala:74)
        at variant.Main$.main(Main.scala:5)
        at variant.Main.main(Main.scala)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:4

Best regards,
Michael

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Upgrading to Scala 2.12.1 causes ClassCastExceptions

Michael Thaler
In reply to this post by Seth Tisue-3
Hi Seth,

thanks for the shorter example. I made it a bit longer to give some context.

Best regards,
Michael

On Tuesday, January 3, 2017 at 4:55:45 PM UTC+1, Seth Tisue wrote:
shorter reproduction:

trait Unwrapper[@specialized(Byte) P] {
  def unwrap: P = 0L.asInstanceOf[P]
}
(new Unwrapper[Byte] {}).unwrap

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Upgrading to Scala 2.12.1 causes ClassCastExceptions

Michael Thaler
In reply to this post by Michael Thaler
Hi,

I tried to investigate this further.

I compiled the following classes with Scala 2.11.8 and Scala 2.12.1:

trait Unwrapper[@specialized(Byte) P] {
def unwrap: P = {
val result = 0L.asInstanceOf[P]
result
}
}

object UnwrapperTest extends App with Unwrapper[Byte] {

println(unwrap)
}

With Scala 2.11.8 I get the following byte code:

$ javap -c Unwrapper

Compiled from "Unwrapper.scala"
public interface variant.Unwrapper{
public abstract java.lang.Object unwrap();

public abstract byte unwrap$mcB$sp();

}

$ javap -c Unwrapper\$class

Compiled from "Unwrapper.scala"
public abstract class variant.Unwrapper$class extends java.lang.Object{
public static java.lang.Object unwrap(variant.Unwrapper);
Code:
0: lconst_0
1: invokestatic #13; //Method scala/runtime/BoxesRunTime.boxToLong:(J)Ljava/lang/Long;
4: astore_1
5: aload_1
6: areturn

public static byte unwrap$mcB$sp(variant.Unwrapper);
Code:
0: aload_0
1: invokeinterface #24, 1; //InterfaceMethod variant/Unwrapper.unwrap:()Ljava/lang/Object;
6: invokestatic #28; //Method scala/runtime/BoxesRunTime.unboxToByte:(Ljava/lang/Object;)B
9: ireturn

public static void $init$(variant.Unwrapper);
Code:
0: return

}

$ javap -c Unwrapper\$mcB\$sp

Compiled from "Unwrapper.scala"
public interface variant.Unwrapper$mcB$sp extends variant.Unwrapper{
public abstract byte unwrap();

public abstract byte unwrap$mcB$sp();

}

$ javap -c Unwrapper\$mcB\$sp\$class

Compiled from "Unwrapper.scala"
public abstract class variant.Unwrapper$mcB$sp$class extends java.lang.Object{
public static byte unwrap(variant.Unwrapper$mcB$sp);
Code:
0: aload_0
1: invokeinterface #13, 1; //InterfaceMethod variant/Unwrapper$mcB$sp.unwrap$mcB$sp:()B
6: ireturn

public static byte unwrap$mcB$sp(variant.Unwrapper$mcB$sp);
Code:
0: lconst_0
1: l2i
2: i2b
3: istore_1
4: iload_1
5: ireturn

public static void $init$(variant.Unwrapper$mcB$sp);
Code:
0: return

}

With Scala 2.12.1 I get:

javap -c Unwrapper

public interface variant.Unwrapper{
public static java.lang.Object unwrap$(variant.Unwrapper);
Code:
0: aload_0
1: invokespecial #16; //InterfaceMethod unwrap:()Ljava/lang/Object;
4: areturn

public java.lang.Object unwrap();
Code:
0: lconst_0
1: invokestatic #23; //Method scala/runtime/BoxesRunTime.boxToLong:(J)Ljava/lang/Long;
4: astore_1
5: aload_1
6: areturn

public static byte unwrap$mcB$sp$(variant.Unwrapper);
Code:
0: aload_0
1: invokespecial #32; //InterfaceMethod unwrap$mcB$sp:()B
4: ireturn

public byte unwrap$mcB$sp();
Code:
0: aload_0
1: invokeinterface #16, 1; //InterfaceMethod unwrap:()Ljava/lang/Object;
6: invokestatic #36; //Method scala/runtime/BoxesRunTime.unboxToByte:(Ljava/lang/Object;)B
9: ireturn

public static void $init$(variant.Unwrapper);
Code:
0: return

javap -c Unwrapper\$mcB\$sp

public interface variant.Unwrapper$mcB$sp extends variant.Unwrapper{
}

I am not an expert on Java bytecode, but with Scala 2.11.8 I see the following byte code that converts a long to a byte:

public static byte unwrap$mcB$sp(variant.Unwrapper$mcB$sp);
Code:
0: lconst_0
1: l2i
2: i2b
3: istore_1
4: iload_1
5: ireturn

With Scala 2.12.1 I see no such code. Instead the following code is invoked:

public java.lang.Object unwrap();
Code:
0: lconst_0
1: invokestatic #23; //Method scala/runtime/BoxesRunTime.boxToLong:(J)Ljava/lang/Long;
4: astore_1
5: aload_1
6: areturn

This returns a boxed long. And then

public byte unwrap$mcB$sp();
Code:
0: aload_0
1: invokeinterface #16, 1; //InterfaceMethod unwrap:()Ljava/lang/Object;
6: invokestatic #36; //Method scala/runtime/BoxesRunTime.unboxToByte:(Ljava/lang/Object;)B
9: ireturn

And this unboxes the boxed long to a byte which does not work because BoxesRunTime.unboxToByte expects a java.lang.Byte, not a java.lang.Long.

This seems a compiler bug related to specializing, if I remove @specialized from

trait Unwrapper[@specialized(Byte) P] {
def unwrap: P = {
val result = 0L.asInstanceOf[P]
result
}
}


everything works fine. If my conclusions are correct, should I report this to scala-language or open a bug report for the Scala compiler?

Best regards,
Michael

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Upgrading to Scala 2.12.1 causes ClassCastExceptions

Michael Thaler
Actually the whole boxing / unboxing should not be there because the code is specialized.

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Loading...