ring the big bell of variance-related soundness holes

207 views
Skip to first unread message

Paul Phillips

unread,
Dec 29, 2012, 6:22:06 PM12/29/12
to Adriaan Moors, scala-i...@googlegroups.com
I spent hours analyzing my variance-related patch, unable to see how I'd caused 15 compile errors in the build.

And... and... why don't I think of this earlier. I'd unwittingly fixed variance checking, and revealed the 15 unsound constructs which were already there.

Here's an example, adapted from the first compilation error. CCE in 2.10 and trunk.

case class Wrapper[A](val underlying: java.util.List[A]) extends Seq[A] {
  def apply(idx: Int): A = underlying.get(idx)
  def length = 0
  def iterator = Iterator.empty
}

object Test {
  def f[A](x: Seq[A]) = x match { case Wrapper(wrapped) => wrapped }

  def main(args: Array[String]): Unit = {
    val w = Wrapper(new java.util.ArrayList[String])
    val xs = f(w: Seq[AnyRef])
    xs add Nil
    println(w(0).length)
  }
  // java.lang.ClassCastException: scala.collection.immutable.Nil$ cannot be cast to java.lang.String
  //   at Test$.main(bug.scala:15)
  //   at Test.main(bug.scala)
  //   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  //   at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
  //   at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
}

This hole was already known about -- it is https://issues.scala-lang.org/browse/SI-5189 -- but the attempt to remedy it was inadequate.

[scalacfork] /scratch/trunk6/src/library/scala/collection/convert/WrapAsJava.scala:102: error: type mismatch;
[scalacfork]  found   : java.util.List[?A5] where type ?A5 <: A (this is a GADT skolem)
[scalacfork]  required: java.util.List[A]
[scalacfork] Note: ?A5 <: A, but Java-defined trait List is invariant in type E.
[scalacfork] You may wish to investigate a wildcard type such as `_ <: A`. (SLS 3.2.10)
[scalacfork]     case JListWrapper(wrapped) => wrapped
[scalacfork]                                   ^
[scalacfork] /scratch/trunk6/src/library/scala/collection/convert/WrapAsJava.scala:120: error: type mismatch;
[scalacfork]  found   : java.util.List[?A6] where type ?A6 <: A (this is a GADT skolem)
[scalacfork]  required: java.util.List[A]
[scalacfork] Note: ?A6 <: A, but Java-defined trait List is invariant in type E.
[scalacfork] You may wish to investigate a wildcard type such as `_ <: A`. (SLS 3.2.10)
[scalacfork]     case JListWrapper(wrapped) => wrapped
[scalacfork]                                   ^
[scalacfork] /scratch/trunk6/src/library/scala/collection/convert/WrapAsJava.scala:156: error: type mismatch;
[scalacfork]  found   : java.util.Set[?A8] where type ?A8 <: A (this is a GADT skolem)
[scalacfork]  required: java.util.Set[A]
[scalacfork] Note: ?A8 <: A, but Java-defined trait Set is invariant in type E.
[scalacfork] You may wish to investigate a wildcard type such as `_ <: A`. (SLS 3.2.10)
[scalacfork]     case JSetWrapper(wrapped) => wrapped
[scalacfork]                                  ^
[scalacfork] /scratch/trunk6/src/library/scala/collection/convert/WrapAsJava.scala:174: error: type mismatch;
[scalacfork]  found   : java.util.Set[?A9] where type ?A9 <: A (this is a GADT skolem)
[scalacfork]  required: java.util.Set[A]
[scalacfork] Note: ?A9 <: A, but Java-defined trait Set is invariant in type E.
[scalacfork] You may wish to investigate a wildcard type such as `_ <: A`. (SLS 3.2.10)
[scalacfork]     case JSetWrapper(wrapped) => wrapped
[scalacfork]                                  ^
[scalacfork] /scratch/trunk6/src/library/scala/collection/convert/WrapAsJava.scala:193: error: type mismatch;
[scalacfork]  found   : java.util.Map[?A10,?B1] where type ?B1 <: B (this is a GADT skolem), type ?A10 <: A (this is a GADT skolem)
[scalacfork]  required: java.util.Map[A,B]
[scalacfork] Note: ?A10 <: A, but Java-defined trait Map is invariant in type K.
[scalacfork] You may wish to investigate a wildcard type such as `_ <: A`. (SLS 3.2.10)
[scalacfork] Note: ?B1 <: B, but Java-defined trait Map is invariant in type V.
[scalacfork] You may wish to investigate a wildcard type such as `_ <: B`. (SLS 3.2.10)
[scalacfork]     case JMapWrapper(wrapped) => wrapped
[scalacfork]                                  ^
[scalacfork] /scratch/trunk6/src/library/scala/collection/convert/WrapAsJava.scala:213: error: type mismatch;
[scalacfork]  found   : java.util.Dictionary[?A11,?B2] where type ?B2 <: B (this is a GADT skolem), type ?A11 <: A (this is a GADT skolem)
[scalacfork]  required: java.util.Dictionary[A,B]
[scalacfork] Note: ?A11 <: A, but Java-defined class Dictionary is invariant in type K.
[scalacfork] You may wish to investigate a wildcard type such as `_ <: A`. (SLS 3.2.10)
[scalacfork] Note: ?B2 <: B, but Java-defined class Dictionary is invariant in type V.
[scalacfork] You may wish to investigate a wildcard type such as `_ <: B`. (SLS 3.2.10)
[scalacfork]     case JDictionaryWrapper(wrapped) => wrapped
[scalacfork]                                         ^
[scalacfork] /scratch/trunk6/src/library/scala/collection/convert/WrapAsJava.scala:254: error: type mismatch;
[scalacfork]  found   : java.util.concurrent.ConcurrentMap[?A13,?B4] where type ?B4 <: B (this is a GADT skolem), type ?A13 <: A (this is a GADT skolem)
[scalacfork]  required: java.util.concurrent.ConcurrentMap[A,B]
[scalacfork] Note: ?A13 <: A, but Java-defined trait ConcurrentMap is invariant in type K.
[scalacfork] You may wish to investigate a wildcard type such as `_ <: A`. (SLS 3.2.10)
[scalacfork] Note: ?B4 <: B, but Java-defined trait ConcurrentMap is invariant in type V.
[scalacfork] You may wish to investigate a wildcard type such as `_ <: B`. (SLS 3.2.10)
[scalacfork]     case JConcurrentMapDeprecatedWrapper(wrapped) => wrapped
[scalacfork]                                                      ^
[scalacfork] /scratch/trunk6/src/library/scala/collection/convert/WrapAsJava.scala:274: error: type mismatch;
[scalacfork]  found   : java.util.concurrent.ConcurrentMap[?A14,?B5] where type ?B5 <: B (this is a GADT skolem), type ?A14 <: A (this is a GADT skolem)
[scalacfork]  required: java.util.concurrent.ConcurrentMap[A,B]
[scalacfork] Note: ?A14 <: A, but Java-defined trait ConcurrentMap is invariant in type K.
[scalacfork] You may wish to investigate a wildcard type such as `_ <: A`. (SLS 3.2.10)
[scalacfork] Note: ?B5 <: B, but Java-defined trait ConcurrentMap is invariant in type V.
[scalacfork] You may wish to investigate a wildcard type such as `_ <: B`. (SLS 3.2.10)
[scalacfork]     case JConcurrentMapWrapper(wrapped) => wrapped
[scalacfork]                                            ^
[scalacfork] /scratch/trunk6/src/library/scala/collection/convert/WrapAsScala.scala:126: error: type mismatch;
[scalacfork]  found   : scala.collection.mutable.Buffer[?A5] where type ?A5 <: A (this is a GADT skolem)
[scalacfork]  required: scala.collection.mutable.Buffer[A]
[scalacfork] Note: ?A5 <: A, but trait Buffer is invariant in type A.
[scalacfork] You may wish to investigate a wildcard type such as `_ <: A`. (SLS 3.2.10)
[scalacfork]     case MutableBufferWrapper(wrapped) => wrapped
[scalacfork]                                           ^
[scalacfork] /scratch/trunk6/src/library/scala/collection/convert/WrapAsScala.scala:144: error: type mismatch;
[scalacfork]  found   : scala.collection.mutable.Set[?A6] where type ?A6 <: A (this is a GADT skolem)
[scalacfork]  required: scala.collection.mutable.Set[A]
[scalacfork] Note: ?A6 <: A, but trait Set is invariant in type A.
[scalacfork] You may wish to investigate a wildcard type such as `_ <: A`. (SLS 3.2.10)
[scalacfork]     case MutableSetWrapper(wrapped) => wrapped
[scalacfork]                                        ^
[scalacfork] /scratch/trunk6/src/library/scala/collection/convert/WrapAsScala.scala:164: error: type mismatch;
[scalacfork]  found   : scala.collection.mutable.Map[?A7,?B1] where type ?B1 <: B (this is a GADT skolem), type ?A7 <: A (this is a GADT skolem)
[scalacfork]  required: scala.collection.mutable.Map[A,B]
[scalacfork] Note: ?A7 <: A, but trait Map is invariant in type A.
[scalacfork] You may wish to investigate a wildcard type such as `_ <: A`. (SLS 3.2.10)
[scalacfork] Note: ?B1 <: B, but trait Map is invariant in type B.
[scalacfork] You may wish to investigate a wildcard type such as `_ <: B`. (SLS 3.2.10)
[scalacfork]     case MutableMapWrapper(wrapped) => wrapped
[scalacfork]                                        ^
[scalacfork] /scratch/trunk6/src/library/scala/collection/convert/WrapAsScala.scala:217: error: type mismatch;
[scalacfork]  found   : scala.collection.mutable.Map[?A8,?B2] where type ?B2 <: B (this is a GADT skolem), type ?A8 <: A (this is a GADT skolem)
[scalacfork]  required: scala.collection.mutable.Map[A,B]
[scalacfork] Note: ?A8 <: A, but trait Map is invariant in type A.
[scalacfork] You may wish to investigate a wildcard type such as `_ <: A`. (SLS 3.2.10)
[scalacfork] Note: ?B2 <: B, but trait Map is invariant in type B.
[scalacfork] You may wish to investigate a wildcard type such as `_ <: B`. (SLS 3.2.10)
[scalacfork]     case DictionaryWrapper(wrapped) => wrapped
[scalacfork]                                        ^
[scalacfork] /scratch/trunk6/src/library/scala/collection/immutable/RedBlackTree.scala:353: error: type mismatch;
[scalacfork]  found   : List[scala.collection.immutable.RedBlackTree.Tree[?A13,B]] where type ?A13 <: A (this is a GADT skolem)
[scalacfork]  required: List[scala.collection.immutable.RedBlackTree.Tree[A,B]]
[scalacfork]         if (depth == 1) zipper else findDepth(tail, depth - 1)
[scalacfork]                                               ^
[scalacfork] /scratch/trunk6/src/library/scala/collection/immutable/RedBlackTree.scala:354: error: type mismatch;
[scalacfork]  found   : List[scala.collection.immutable.RedBlackTree.Tree[?A14,B]] where type ?A14 <: A (this is a GADT skolem)
[scalacfork]  required: List[scala.collection.immutable.RedBlackTree.Tree[A,B]]
[scalacfork]       case _ :: tail => findDepth(tail, depth)
[scalacfork]                                   ^
[scalacfork] /scratch/trunk6/src/library/scala/io/Codec.scala:73: error: type mismatch;
[scalacfork]  found   : x.type (with underlying type T)
[scalacfork]  required: ?T1 where type ?T1 <: T (this is a GADT skolem)
[scalacfork]       case (f, cond) => if (cond) f(x) else x
[scalacfork]                                     ^
[scalacfork] one warning found
Reply all
Reply to author
Forward
0 new messages