Last active
January 30, 2021 18:32
-
-
Save sir-wabbit/369002d1338e410586a5c0a517699f29 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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