{throw Exception()} lambda type


#1

In this snippet typing process failed in last line, bottom has type (): R

fun main(args : Array<String>) {
  val bottom = {throw Exception()}

  println(bottom)
  println(bottom())
}

But in this one compiles successfully and even run with some results, bottom still typed to (): R

fun main(args : Array<String>) {   val bottom = {if(Math.random() > 0.5) throw Exception() else 42}

  println(bottom)
  println(bottom())
}


First question: type R - what is this?
Second question: which of two samples demonstrates bug in compiler? Or no bugs here?


#2

In your example bottom has type () -> Nothing, which is correct. If your IDE shows you something else, try updating to a newer nightly build.

The difference between the two examples is explained by the special nature of the Nothing type. Nothing is the empty type, it has no instances, thus it is a subtype of any other type.
You can assign bottom() to a variable of type Int, or String, or Foo, whatever Foo is.

So, when passing bottom() to println(), which is overloaded for Java primitive types for efficiency, you get an ambiguity: every overloaded version of println() fits. Why? Because it will never run, and the compiler tells you that: “(5, 3) : Unreachable code”.

In the second example the same property of Nothing works well for you: the if-expression has the type which is a common supertype of the branches, thus if one of the branches is of type Nothing, the result is simply of the type of the other branch (Int in this case). Again, it works because if the first branch was taken, there would be no execution of the code that could see the value of bottom.