12

In his talk Compilers are Databases, Martin Odersky presents an interesting variance corner case:

class Tree[-T] {
  def tpe: T @uncheckedVariance
  def withType(t: Type): Tree[Type]
}

T is defined to be contravariant, because it is useful to think of a typed tree (Tree[Type]) as a subtype of an untyped tree (Tree[Nothing]), but not the other way around.

Normally, the Scala compiler would complain about T appearing as the return type of the tpe method. That's why Martin shuts up the compiler with an @uncheckedVariance annotion.

Here is the example translated to Kotlin:

abstract class Tree<in T> {
    abstract fun tpe(): T
    abstract fun withType(t: Type): Tree<Type>
}

As expected, the Kotlin compiler complains about T appearing in an 'out' position. Does Kotlin have something similar to @uncheckedVariance? Or is there a better way to solve this particular problem?

fredoverflow
  • 256,549
  • 94
  • 388
  • 662
  • You really want to just use `Tree[Unit]` for untyped trees. It prevents more bugs (compile-time vs runtime error) and doesn't require you to work around the type checker (hey that's funny isn't it). Odersky was just Oderskying here. –  Apr 11 '16 at 21:21

1 Answers1

10

Kotlin has an @UnsafeVariance annotation which is an equivalent to @uncheckedVariance in scala:

abstract class Tree<in T> {
  abstract fun tpe(): @UnsafeVariance T
  abstract fun withType(t: Type): Tree<Type>
}
Vladimir Mironov
  • 30,514
  • 3
  • 65
  • 62
  • Interesting, `@unsafeVariance` appears to be [a relatively recent feature](https://blog.jetbrains.com/kotlin/2015/10/kotlin-1-0-beta-candidate-is-out/). Thanks! – fredoverflow Apr 11 '16 at 21:25