Reputation: 3330
I am using Kotlin 1.2.60.
val someString: String = try {
String.format("Okay %s", "there") // or any function that returns String
} catch(exception: Exception) {
try {
// fun incrementErrorCount() { ... }
incrementErrorCount() // [1] Error: Type mismatch: Inferred type is Unit but String was expected
} finally {
throw exception
}
// throw exception // [2] Fixes the type mismatch when uncommented, but raises Warning: Unreachable code
}
I get a Type mismatch error at 1
because it expects incrementErrorCount()
to return a String — but the return type shouldn't matter, because it is always going to re-throw exception
anyway.
I added 2
, which fixes the Type mismatch error, but raises an Unreachable code warning because the function never proceeds beyond the throw
in finally
.
What am I doing wrong? How can I get this to compile without errors or warnings?
Upvotes: 2
Views: 2576
Reputation: 8371
See the Kotlin Reference for try-catch-finally
and you'll see:
The returned value of a
try
-expression is either the last expression in thetry
block or the last expression in thecatch
block (or blocks). Contents of thefinally
block do not affect the result of the expression.
So this means that while your intention is correct, and there is no way to return from your second try
block, the Kotlin compiler will still take Unit
as it's return value and not modify it due to the specification of the finally
block.
To make the compiler aware of the fact that the catch
block will always return Nothing
, you need to move the throw
out of the finally
block.
Upvotes: 2
Reputation: 13007
I'm assuming your desired logic is that if String.format fails, you let the exception be thrown, but also increment your error count. In that case, I think you need (untested)...
val someString: String = try {
String.format("Okay %s", "there") // or any function that returns String
} catch(exception: Exception) {
try {
// fun incrementErrorCount() { ... }
incrementErrorCount()
}
catch (dontCare: Exception) {
}
throw exception
}
Upvotes: 0
Reputation: 89568
try-catch
is an expression in Kotlin. If the try
block runs successfully without throwing anything, its last value is returned. If it throws an exception, the catch
block's last value is returned.
In your case, if String.format
doesn't throw an exception, its result is returned from the first try-catch
, and you're good. This is the easy route.
If String.format
throws an exception, the last expression of the catch
block is returned, which is the second, nested try-finally
itself. This can end two ways:
try
block runs successfully, its last expression (in this case, incrementErrorCount
) is what it evaluates to, and then the result of that call would be assigned to someString
. This is the type error you're getting, it looks like incrementErrorCount
doesn't return a String
to assign.try
fails, you throw an exception, cancelling the assignment of someString
altogether.Adding line [2] fixes your error because the nested try-catch
isn't used as the value to assign to someString
, it's just ran and the throw
expression cancels the entire assignment of someString
.
Upvotes: 0