Java interop: Unit closures required to return kotlin.Unit


#1

Given this function:

object Tmp {
    @JvmStatic fun hello(f: () -> Unit) {
    }
}

The following Java code doesn’t compile

public class Hello {
    public void asd() {
        Tmp.hello(() -> {
        });
    }
}

as it requires the closure to return Unit.INSTANCE.
Suggestion: Add @JvmVoid annotation to denote Units that should actually behave as void


#2

I don’t understand why Unit is better than void or Void…

Someone can help me?


#3

Unit is a type (unlike void) and has a value (unlike Void). This enable uniform treatment of Unit when it comes to generic classes. I.e. we don’t need another two types: a function that returns something and a function that returns void. It’s all one type: a function that returns something tat may be Unit.

Introducing void would pose many problems in areas like type inference, compositionality of any sort of functions, etc


#4

@abreslav Could you explain in which case it’s better to use Nothing over Unit ?


#5

Thanks for response,
those are good points.
I’m interested to know how you will fix this issue.


#6

Nothing is for a function/method that never returns,
i.e. System.exit() should return Nothing.

Also “throw” statement returns nothing.

All statements after a Nothing one are unreachable.


#7

I’m not suggesting introducing void as a kotlin type, but rather annotating Unit for better Java interop. There is a straightforward translation from void to Unit which the compiler could do:

If void is covariant:

fun f(): @JvmVoid Unit {..}

would compile to two functions, one for kotlin, one for java:

public void f_kotlin(): Unit {
  ..
}
public void f_java() {
  f_kotlin();
}

And if it’s contravariant the java version would just wrap void functions and pass in Unit.INSTANCE automatically.


#8

This functionality is also required to maintain compatibility with code that inspects the return type of a method and will fail if it is not void. For example, in the Arquillian testing suite, the org.jboss.arquillian.junit.Arquillian.validatePublicVoidNoArgMethods() method checks to make sure that a test function annotated with @BeforeClass returns void. Without some way to generate the correct signature, Kotlin can’t be used with these libraries.


#9

Hello, is there any solution so far to pass () -> {} in Java to Kotlin function as an argument, which is declared as () -> Unit?