Skip to content

Instantly share code, notes, and snippets.

@lemastero
Forked from hobwekiva/Unsoundness.scala
Created November 28, 2019 09:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lemastero/3c2ab2448923d7e0357c75ec451f2d66 to your computer and use it in GitHub Desktop.
Save lemastero/3c2ab2448923d7e0357c75ec451f2d66 to your computer and use it in GitHub Desktop.
import scala.language.existentials
class A { class E }
class B extends A { class E }
trait CD { type E }
trait C extends CD { type E = Int }
trait D extends CD { type E = String }
object Test {
type EE[+X <: { type E }] = X#E
def fail1(): Unit = {
val a = new A
val b = new B
var x1: EE[A] = new a.E
var x2: EE[B] = new b.E
x1 = x2
}
def fail2(): Unit = {
val b = new B
var x1: p.E forSome { val p: A } = new b.E // should not compile
var x2: p.E forSome { val p: B } = new b.E
x1 = x2 // should not compile
}
def fail3(): Unit = {
var x1: EE[C] = 5
var x2: EE[C with D] = ""
x1 = x2
}
def fail4(): Unit = {
trait P { type R }
trait A extends P { type R = Int }
trait B extends P { type R = String }
trait F[X <: P] { def foo: X#R }
val a: F[B with A] = new F[A with B] { def foo: String = "a" }
println(a.foo : Int)
}
def fail5(): Unit = {
trait A { type L <: Nothing }
trait B { type L >: Any }
def toL(b: B)(x: Any): b.L = x
val p: B with A = null
println(toL(p)("hello"): Nothing)
}
def fail6(): Unit = {
trait LowerBound[T] {
type M >: T;
}
trait UpperBound[U] {
type M <: U;
}
trait Upcast[T] {
type X <: LowerBound[T]
def compute: X
final lazy val ub: X = compute
def upcast(t: T): ub.M = t
}
class Coerce[T,U] extends Upcast[T] {
type X = LowerBound[T] with UpperBound[U]
override def compute = ???
def coerce(t: T): U = upcast(t)
}
val zero : String = (new Coerce[Int,String]).coerce(0)
}
def fail7(): Unit = {
trait A
trait B extends A
trait C {
val x : AnyRef
trait D { type T >: B <: A }
val y: (D with x.type)#T = new B { }
}
class D extends C {
trait E
lazy val x : AnyRef { type T = E } = ???
def frob(arg : E) : E = arg
frob(y)
}
new D
}
def wrap(label: String)(op: => Unit): Unit =
try { op } catch { case x: ClassCastException => println("%37s -> %s".format(label, x.getClass.getName)) }
def testAll(): Unit = {
wrap("Variance and inner classes")(fail1())
wrap("Conformance of existentials")(fail2())
wrap("Linearization and projections #1")(fail3())
wrap("Linearization and projections #2")(fail4())
wrap("Linearization and inhabitance of ⊥ #1")(fail5())
wrap("Linearization and inhabitance of ⊥ #2")(fail6())
wrap("Linearization and projections #3")(fail7())
}
}
/*
Variance and inner classes -> java.lang.ClassCastException
Conformance of existentials -> java.lang.ClassCastException
Linearization and projections #1 -> java.lang.ClassCastException
Linearization and projections #2 -> java.lang.ClassCastException
Linearization and inhabitance of ⊥ #1 -> java.lang.ClassCastException
Linearization and inhabitance of ⊥ #2 -> java.lang.ClassCastException
Linearization and projections #3 -> java.lang.ClassCastException
*/
Test.testAll()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment