[2.12.0] Incorrect warning: Class A$B differs only in case from A$B

99 views
Skip to first unread message

Georgi Jojgov

unread,
Nov 23, 2016, 4:15:56 AM11/23/16
to scala-internals
I'd like to report a regression from 2.11.8 to 2.12.0

class A[@specialized(Long, Double) T](val value: T) {
  trait B


 
def useValue(x:T): Unit = ???
  useValue
(value)
}

Output from Scala 2.12.0:

[warn] .../Warning.scala:2: Class A$B differs only in case from A$B. Such classes will overwrite one another on case-insensitive filesystems.
[warn]   trait B
[warn]         ^
[warn] one warning found


SI-9097 sounds related, but it was fixed in 2.11.6 and indeed, the code compiles fine with 2.11.8. 

Georgi

Georgi Jojgov

unread,
Nov 23, 2016, 9:28:29 AM11/23/16
to scala-internals
There seems to be more at hand, because I am getting ClassCastExceptions at runtime with 2.12.0 which are not there is 2.11.8. Here is a reduces test case (please disregard the obvious question if this is a pattern one should be using):

import org.scalatest.{Matchers, Suite, WordSpecLike}

trait BaseSp[@specialized(Long, Double) S]{
  def initialValue: S
  var value: S = initialValue
}
trait BaseNotSp[S]{
  def initialValue: S
  var value: S = initialValue
}

final class Bar_Sp_Sp    [@specialized(Long, Double) S](val initialValue: S) extends BaseSp[S]
final class Bar_NotSp_Sp [@specialized(Long, Double) S](val initialValue: S) extends BaseSp[S]
final class Bar_Sp_NotSp [@specialized(Long, Double) S](val initialValue: S) extends BaseNotSp[S]
final class Bar_NotSp_NotSp                         [S](val initialValue: S) extends BaseNotSp[S]

class CrashSpec  extends Suite with WordSpecLike with Matchers {
  "How to reproduce" in {
    intercept[ClassCastException](new Bar_Sp_Sp[Double](Double.MaxValue)).getMessage should equal(null)
    intercept[ClassCastException](new Bar_Sp_Sp[Long](Long.MaxValue)).getMessage should equal("java.lang.Long cannot be cast to java.lang.Double")
    intercept[ClassCastException](new Bar_NotSp_Sp[Double](Double.MaxValue)).getMessage should equal(null)
    intercept[ClassCastException](new Bar_NotSp_Sp[Long](Long.MaxValue)).getMessage should equal("java.lang.Long cannot be cast to java.lang.Double")

    new Bar_Sp_NotSp[Double](Double.MaxValue)
    new Bar_Sp_NotSp[Long](Long.MaxValue)
    new Bar_NotSp_NotSp[Double](Double.MaxValue)
    new Bar_NotSp_NotSp[Long](Long.MaxValue)
  }
}

Please note that the exception message is null in some of the cases and the runtime exception is only present if the base class is @specialized

Georgi
.

som-snytt

unread,
Nov 23, 2016, 4:59:32 PM11/23/16
to scala-internals

2.11 says after specialization:

        abstract trait T[@specialized(scala.Long, scala.Double) S] extends Object {
          def /*T*/$init$(): Unit = {
            ()
          };
          def v0(): S;
          protected[this] var v: S = T.this.v0();
          <accessor> def v(): S = T.this.v;
          <accessor> def v_=(x$1: S): Unit = T.this.v = x$1;
          <specialized> def v0$mcD$sp(): Double = T.this.v0().asInstanceOf[Double]();
          <specialized> def v0$mcJ$sp(): Long = T.this.v0().asInstanceOf[Long]();
          <accessor> <specialized> def v$mcD$sp(): Double = T.this.v().asInstanceOf[Double]();
          <accessor> <specialized> def v$mcJ$sp(): Long = T.this.v().asInstanceOf[Long]();
          <accessor> <specialized> def v$mcD$sp_=(x$1: Double): Unit = T.this.v_=(x$1.asInstanceOf[S]());
          <accessor> <specialized> def v$mcJ$sp_=(x$1: Long): Unit = T.this.v_=(x$1.asInstanceOf[S]());
          def specInstance$(): Boolean = false
        };
        abstract <specialized> trait T$mcD$sp extends Object with T[Double] {
          <specialized> def v0(): Double;
          <specialized> protected[this] var v$mcD$sp: Double = T$mcD$sp.this.v0();
          <accessor> <specialized> def v$mcD$sp(): Double = T$mcD$sp.this.v$mcD$sp;
          override <accessor> <specialized> def v(): Double = T$mcD$sp.this.v$mcD$sp();
          <accessor> <specialized> def v$mcD$sp_=(x$1: Double): Unit = T$mcD$sp.this.v$mcD$sp = x$1;
          override <accessor> <specialized> def v_=(x$1: Double): Unit = T$mcD$sp.this.v$mcD$sp_=(x$1);
          def specInstance$(): Boolean = true
        };
        abstract <specialized> trait T$mcJ$sp extends Object with T[Long] {
          <specialized> def v0(): Long;
          <specialized> protected[this] var v$mcJ$sp: Long = T$mcJ$sp.this.v0();
          <accessor> <specialized> def v$mcJ$sp(): Long = T$mcJ$sp.this.v$mcJ$sp;
          override <accessor> <specialized> def v(): Long = T$mcJ$sp.this.v$mcJ$sp();
          <accessor> <specialized> def v$mcJ$sp_=(x$1: Long): Unit = T$mcJ$sp.this.v$mcJ$sp = x$1;
          override <accessor> <specialized> def v_=(x$1: Long): Unit = T$mcJ$sp.this.v$mcJ$sp_=(x$1);
          def specInstance$(): Boolean = true
        }

but 2.12 says:

        abstract trait T[@specialized(scala.Long, scala.Double) S] extends Object {
          def /*T*/$init$(): Unit = {
            ()
          };
          def v0(): S;
          <accessor> <sub_synth> def v(): S = T.this.v0();
          <accessor> <sub_synth> def v_=(x$1: S): Unit;
          <specialized> def v0$mcD$sp(): Double = T.this.v0().asInstanceOf[Double]();
          <specialized> def v0$mcJ$sp(): Long = T.this.v0().asInstanceOf[Long]();
          <accessor> <specialized> <sub_synth> def v$mcD$sp(): Double = T.this.v().asInstanceOf[Double]();
          <accessor> <specialized> <sub_synth> def v$mcJ$sp(): Long = T.this.v().asInstanceOf[Long]();
          <accessor> <specialized> <sub_synth> def v$mcD$sp_=(x$1: Double): Unit = T.this.v_=(x$1.asInstanceOf[S]());
          <accessor> <specialized> <sub_synth> def v$mcJ$sp_=(x$1: Long): Unit = T.this.v_=(x$1.asInstanceOf[S]());
          def specInstance$(): Boolean = false
        };
        abstract <specialized> trait T$mcD$sp extends Object with T[Double];
        abstract <specialized> trait T$mcJ$sp extends Object with T[Long]

where sub_synth is contributed by fields:

        abstract trait T[@specialized(scala.Long, scala.Double) S] extends Object {
          def /*T*/$init$(): Unit = {
            ()
          };
          def v0(): S;
          <accessor> <sub_synth> def v(): S = T.this.v0();
          <accessor> <sub_synth> def v_=(x$1: S): Unit
        }

som-snytt

unread,
Nov 23, 2016, 5:03:50 PM11/23/16
to scala-internals

That was for

scala> trait T[@specialized(Long, Double) S] { def v0: S ; var v = v0 }


Also https://issues.scala-lang.org/browse/SI-10072

Lukas Rytz

unread,
Dec 6, 2016, 8:57:47 AM12/6/16
to scala-i...@googlegroups.com
Hi Georgi,

Thanks for the reports. I created tickets for the two bugs you reported:

Cheers: Lukas

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

Reply all
Reply to author
Forward
0 new messages