`fun foo() { Unit }` does not give a warning or error


#1

Same with fun foo() { String }.

In Java, void foo() { String; } refuses to compile. Shouldn’t Kotlin do the same?


#2

Unit is both a type and a value in Kotlin (it’s actually a singleton). So writing fun foo() { Unit } is entirely sane from a language perspective, because in Kotlin functions always have a return type - there is no direct equivalent of void.

Of course, for compatibility, fun foo(): Unit is compiled to a void function in Java. But that’s a detail of bytecode translation.

fun foo() { String } is a function that evaluates a single expression and then throws the result away. Not very useful, but not illegal.


#3

fun foo() { String } gives no warning but fun foo() { 5 } warns about the unused expression. This appears to be inconsistent.

I noticed this issue while reading code that looked like this:

fun foo() {
    if (something) {
        throw SomeException()
    } else {
        Unit
    }
}

The author is new to Kotlin and didn’t realise that Unit here does nothing. I can understand being confused by this, and I’m surprised that no warning is generated.


#4

Also, I’m not sure i understand your point about fun foo() { Unit }. That’s not the same as fun foo() { return Unit }. fun foo(): String { "foo" }, for example, doesn’t compile.


#5

This appears to be about companion objects.

This doesn’t compile:

class Foo

fun foo() {
    Foo // Error: Please specify constructor invocation; classifier 'Foo' does not have a companion object
}

But this compiles (without warning):

class Foo {
    companion object
}

fun foo() {
    Foo
}

On the whole, unless I’m mistaken about what’s going on here, it seems to me that Kotlin should be warning about the unused expression in the second example above. Why isn’t it?


#6

Yes, it should. You’re welcome to file a YouTrack issue, and we’ll add diagnostics for this.


#7

Thanks, Dmitry. Issue filed here:

https://youtrack.jetbrains.com/issue/KT-11035