Kotlin generates redundant bytecode


#1

Reference (it’s Chinese so I’ll translate the important part here): https://lgzh1215.github.io/2017/10/18/huadian/

We have:

class A<T : Any>(val data: T)
class B(val string: String)

fun test(a: A<*>) {
    a.data as B   // mention the bytecode corresponds to this line
    a.data.string // a.data is Smart casted to B
}

And we look at the generated bytecode:

...
  L1
    LINENUMBER 5 L1
    ALOAD 0
    INVOKEVIRTUAL A.getData ()Ljava/lang/Object; // a.data
    DUP
    IFNONNULL L2   // <============================ null check
    NEW kotlin/TypeCastException
    DUP
    LDC "null cannot be cast to non-null type B"
    INVOKESPECIAL kotlin/TypeCastException.<init> (Ljava/lang/String;)V
    ATHROW
   L2
    CHECKCAST B    // <============================ if NotNull then cast
    POP
   L3
...

It checks if a.data is null. If not, throw TypeCastException("null cannot be cast to non-null type B").

However, according to the definition of a.data, it should always be a NotNull variable.
So it’s impossible for a.data to be null.

Which means the null check is redundant.

Although I can cast it to a Nullable, this is an unignorable bug.

This happens in Kotlin 1.1 .

Any ideas?


#2

for cases like that I recommend you to create an issue over at https://youtrack.jetbrains.com/issues, because this does not seem to need a discussion but a fix


#3

By default Kotlin is pessimistic on nullability. Your function a is public so could be called from Java with a null parameter. It will check explicitly for this (there is a way to disable this if desired). Note that CheckCast does not throw on null values so will let an actual null value through.


#4

This helps.
Thanks! :sweat_smile: