Hi Guys, I have a code like this: ```import java.s...
# announcements
j
Hi Guys, I have a code like this:
Copy code
import java.security.MessageDigest
fun foo(rp: String) {
    return bar(rp)
}
private fun bar(rp: String): ByteArray {
    return MessageDigest.getInstance("SHA-256").digest(rp.toByteArray())
}
The generarted code for kotlin uses:
Intrinsics.checkParameterIsNotNull
for
foo
and generates
if (rpId ==null)
in
bar
. In the later case it throws a
TypeCastException
in case of null and in former an
IllegalArgumentException
. So why does generated code need to handle null checks differently??
r
The provided code doesn't even compile
j
Copy code
import java.security.MessageDigest
fun foo(rp: String) {
    return bar(rp)
}
private fun bar(rp: String): ByteArray {
    return MessageDigest.getInstance("SHA-256").digest(rp.toByteArray())
}
if this because of using inline
String.toByteArray()
? Even then we could have still used the same null check in
Intrinsics.checkParameterIsNotNull(rp, "rp")
??
d
The difference is between public and private function.
foo
is public, and therefor can be called from untrusted code (including Java), who might be passing null. In those cases we want
IllegalArgumentException
. However
bar
is private, and
null
should never end up there. If it for some reason does, you have done an unchecked cast somewhere in your code.
j
@diesieben07 Thanks. however, when I change the argument in both
foo
and
bar
the null check in bar disappears!!? a primitive byte[] can be null too!
Copy code
import java.security.MessageDigest
fun foo(rp: ByteArray):ByteArray {
    return bar(rp)
}
private fun bar(rp: ByteArray): ByteArray {
    return MessageDigest.getInstance("SHA-256").digest(rp)
}
decompiled java code for this is:
Copy code
private static final byte[] bar(byte[] rp) {
      byte[] var10000 = MessageDigest.getInstance("SHA-256").digest(rp);
      Intrinsics.checkExpressionValueIsNotNull(var10000, "MessageDigest.getInstance(\"SHA-256\").digest(rp)");
      return var10000;
   }
d
digest
is a Java method, so it's argument is a platform type (
ByteArray!
in this case). This type is allowed to accept nulls, so the compiler does not emit the check.
Actually... I am talking BS.
You are right, the
TypeCastException
is remnants of the
this as java.lang.String
in
String.toByteArray
.
j
cool. Thanks for clarifying! 👍
just for sake of addition info for archival… [this thread here captures it well](https://github.com/jacoco/jacoco/issues/754)
d
1) There's some work in progress related to unification of nullability-related exceptions. However, this can potentially change a program behavior, and can happen in major release only (and we are somewhat late with that change for 1.3). 2) Yes, currently due to the way redundant null check elimination works in the Kotlin compiler, non-private functions get somewhat better treatment (because they have nullability assertions on parameters, and optimizer takes them into account). This can be improved in a minor release.
j
Thanks @dmitry.petrov
My actual motivation for looking in to this behavior was that of code coverage where JaCoCo suddenly started complaining about this piece of code due to inline function being called (String::toByteArray() in this case) bringing in the TypeCastException.