kotlin

I need explain behaviour of Result<Unit>


val result: Result<Unit> = runCatching { Result.success("fuu") }

This code compiles fine but I would expect it to fail because the return type from runCatching is Result<String> and not Result<Unit>. Is compiler so smart that it knows that I don't care about actual return type because I specified it as Result<Unit>? Or it is some other feature of language? Is it described in some language design document? I couldn’t find any documentation on this.


Solution

  • The type of runCatching { Result.success("fuu") } is Result<Result<String>>. You can get a Result<String> just with runCatching { "foo" }. runCatching is a generic function:

    inline fun <R> runCatching(block: () -> R): Result<R>
    

    Since you didn't specify its parameter type R explicitly, it was inferred from the context. The context was that it needs to return a Result<Unit>, so your line is equivalent to:

    val result: Result<Unit> = runCatching<Unit> { Result.success("fuu") }
    

    This means that the block argument (the lambda expression) that you pass to runCatching needs to be of type () -> Unit; therefore, the result of Result.success is discarded, and the object Unit is returned instead.

    Note that the following would indeed give you the type of error you were expecting:

    val temp = runCatching { Result.success("fuu") }
    val result: Result<Unit> = temp
    

    In the above, the type of temp is inferred to be Result<Result<String>> and this cannot be cast to Result<Unit>.