Kotlin hardly sums up the supposed (in place) parameter

I'm not sure that hard-to-fail is the right word, but here is the problem that I am facing. And it took me a while to reproduce this with the smallest possible example, so here it is:

class BaseParameterizedType<T>

fun <U: BaseParameterizedType<*>> getSpecific(clazz: KClass<in U>) : U {
     TODO()
}

fun example(arg: KClass<out BaseParameterizedType<*>>)) {
    getSpecific(arg.innerType)
}

Well, that’s why the above code doesn’t work in "TODO", but if it wasn’t there and if the function returned normally, then it certainly fails with an exception from the null pointer. I tried very hard to understand what was going wrong, so I turned to the decompiled Java code (from kotlin bytecode):

public static final void example(@NotNull KClass arg) {
  Intrinsics.checkParameterIsNotNull(arg, "arg");
  getSpecific(arg.getInnerType());
  throw null;  // <-- The problem
}

If I change the function signature getSpecific(clz: KClass<in U>) : Uto any of these forms:

  • getSpecific(clz: KClass<out U>) : U
  • getSpecific(clz: KClass<U>) : U
  • getSpecific(clz: KClass<in U>) : BaseParameterizedType<*>

or even with a function example(arg: KClass<out BaseParameterizedType<*>)or example(arg: KClass<BaseParameterizedType<*>>), then the generated code:

public static final void example(@NotNull KClass arg) {
  Intrinsics.checkParameterIsNotNull(arg, "arg");
  getSpecific(arg.getInnerType());
}

Now, say, on the call site, I change it to:

getSpecific(BaseParameterizedType::class)

throw null. , , - kotlin, , , ?

, , arg.innerType KClass<out BaseParameterizedType<*>>, , KClass<in BaseParameterizedType<*>>, U BaseParamterizedType<*>>. , - .

, throw null . , getSpecific, , .

+6
2

, Nothing ( ):

enter image description here

- KClass<in U> KClass<out BaseParameterizedType<*>>.

, out - in Nothing ( , ). , KClass<out BaseParameterizedType<*>> KClass<in U>, U := Nothing, , Nothing.

: Foo<out Any> Foo<in T> T := Any, , Foo<out Any>, , , Int. , Foo<T> T , Any , Foo<Int> . , in Nothing - out - .

, Nothing -returning, throw null -, , ( Nothing -typed ).

: KT-20849, KT-18789

+4

, @hotkey, out in Nothing Nothing . :

fun main(args: Array<String>) {
    tryToReturnNothing()
}

fun tryToReturnNothing(): Nothing{
    TODO()
}

   public static final void main(@NotNull String[] args) {
      Intrinsics.checkParameterIsNotNull(args, "args");
      tryToReturnNothing();
      throw null;  // here
   }

   @NotNull
   public static final Void tryToReturnNothing() {
      throw (Throwable)(new NotImplementedError((String)null, 1, (DefaultConstructorMarker)null));
   }

, null Nothing?, Nothing? Nothing. U U?, throw null :

fun <U: BaseParameterizedType<*>> getSpecific(clazz: KClass<in U>) : U? { // see here: change U to U?
    TODO()
}

fun example(arg: KClass<out BaseParameterizedType<*>>) {
    getSpecific(arg)
}

   @Nullable
   public static final BaseParameterizedType getSpecific(@NotNull KClass clazz) {
      Intrinsics.checkParameterIsNotNull(clazz, "clazz");
      throw (Throwable)(new NotImplementedError((String)null, 1, (DefaultConstructorMarker)null));
   }

   public static final void example(@NotNull KClass arg) {
      Intrinsics.checkParameterIsNotNull(arg, "arg");
      getSpecific(arg);
   }
+1

All Articles