import scala.collection.mutable.ListBuffer class A class B extends A class C extends B trait FF1[T, +R] trait FF2[-T, R] class Inv[T] class InvA extends Inv[A] class InvB extends Inv[B] class InvC extends Inv[C] class Multi[+Cov, Inv, -Con] class MultiCov[+T <: A] extends Multi[T, B, C] class MultiInv[T] extends Multi[A, T, C] class MultiCon[-T >: C] extends Multi[A, B, T] object Test { def f1 = Set[Inv[A]]() + new Inv[A] def f2 = Set[Inv[A]]() + new Inv[B] def f3 = Set[Inv[A]]() + new Inv[C] def f4 = Set[Inv[B]]() + new Inv[A] def f5 = Set[Inv[B]]() + new Inv[B] def f6 = Set[Inv[B]]() + new Inv[C] def f7 = Set[Inv[C]]() + new Inv[A] def f8 = Set[Inv[C]]() + new Inv[B] def f9 = Set[Inv[C]]() + new Inv[C] def g1 = Set[Multi[A, B, C]]() + new MultiCov[A] def g2 = Set[Multi[A, B, C]]() + new MultiCov[B] def g3 = Set[Multi[A, B, C]]() + new MultiCov[C] def g4 = Set[Multi[A, B, C]]() + new MultiInv[A] def g5 = Set[Multi[A, B, C]]() + new MultiInv[B] def g6 = Set[Multi[A, B, C]]() + new MultiInv[C] def g7 = Set[Multi[A, B, C]]() + new MultiCon[A] def g8 = Set[Multi[A, B, C]]() + new MultiCon[B] def g9 = Set[Multi[A, B, C]]() + new MultiCon[C] } object Functions { object Set1 { def f[T, R](x: FF1[T, R]) = () def h[T, R] : FF1[T, R] = sys.error("") def ff1 = f[B, B](h[A, A]) // fail def ff2 = f[B, B](h[B, A]) // fail def ff3 = f[B, B](h[C, A]) // fail def ff4 = f[B, B](h[A, B]) // suggest def ff5 = f[B, B](h[B, B]) // ok def ff6 = f[B, B](h[C, B]) // suggest def ff7 = f[B, B](h[A, C]) // suggest def ff8 = f[B, B](h[B, C]) // ok def ff9 = f[B, B](h[C, C]) // suggest } object Set2 { def f[T, R](x: FF2[T, R]) = () def h[T, R] : FF2[T, R] = sys.error("") def ff1 = f[B, B](h[A, A]) // suggest def ff2 = f[B, B](h[B, A]) // suggest def ff3 = f[B, B](h[C, A]) // fail def ff4 = f[B, B](h[A, B]) // ok def ff5 = f[B, B](h[B, B]) // ok def ff6 = f[B, B](h[C, B]) // fail def ff7 = f[B, B](h[A, C]) // suggest def ff8 = f[B, B](h[B, C]) // suggest def ff9 = f[B, B](h[C, C]) // fail } } // TODO // object TypeAlias { // type LL[T] = List[T] // val LL = List // // def f1 = Set[LL[B]]() + LL[A](new A) // def f2 = Set[LL[B]]() + LL[C](new C) // } object Javas { def f[T](x: java.util.List[T]) = () def g[T](x: java.util.Comparator[T]) = () def g1 = f[AnyRef](new java.util.ArrayList[String] { }) def g2 = g[String](Ordering.fromLessThan[AnyRef](_.toString < _.toString)) } object Misc { // original motivation class Data[A <: AnyVal] class MyData extends Data[Int] { } def f1 = Set[Data[AnyVal]]() + new MyData // from stackoverflow def foo(s: Set[CharSequence]): Unit = () def f4 = { val s: Set[String] = Set("Hello", "World"); foo(s) } class Trippy[+T1, T2, +T3] def g1 = Set[Trippy[AnyRef, AnyRef, AnyRef]]() + new Trippy[String, String, String] def g2 = Set[Map[String, String]]() + Map[AnyRef, String]() }