Почему функция Kotlin с параметрами по умолчанию создает метод с неиспользуемым параметром

Смотрите этот пример кода в Kotlin:

fun foo(bar: Int = 0, baz: Int) {
    /* ... */
}

После декомпиляции кода Java (Tools → Kotlin → Show Kotlin Bytecode → Decompile) я получил следующий код

public static final void foo(int bar, int baz) {
}

// $FF: synthetic method
// $FF: bridge method
public static void foo$default(int var0, int var1, int var2, Object var3) {
  if ((var2 & 1) != 0) {
     var0 = 0;
  }

  foo(var0, var1);
}

Я заметил, что полученный Java-метод имеет неиспользуемый параметр Object var3.

Мне кажется, что это может быть связано с функциями в классе, но при декомпиляции этого кода

class Foo {
    fun foo(bar: Int = 0, baz: Int) {
        /* ... */
    }
}

Я получил этот код

public final class Foo {
   public final void foo(int bar, int baz) {
   }

   // $FF: synthetic method
   // $FF: bridge method
   public static void foo$default(Foo var0, int var1, int var2, int var3, Object var4) {
      if ((var3 & 1) != 0) {
         var1 = 0;
      }

      var0.foo(var1, var2);
   }
}

Как вы видите, параметр Object по-прежнему не используется и просто сидит там. При дополнительных тестах я заметил такое же поведение для методов расширения. То же самое происходит, когда последний параметр по умолчанию (т.е. fun foo(bar: Int, baz: Int = 0) {})

Я также провел базовый тест, чтобы проверить, что это за значение, установленное при вызове этой функции, используя код ниже

fun main(args: Array<String>) {
    foo(baz = 2)
}

и

class Something {
    init {
        foo(baz = 2)
    }
}

После декомпиляции я получил следующий код

public static final void main(@NotNull String[] args) {
      Intrinsics.checkParameterIsNotNull(args, "args");
      foo$default(0, 2, 1, (Object)null);
}

и

public final class Something {
   public Something() {
      FooKt.foo$default(0, 2, 1, (Object)null);
   }
}

Что еще меньше имеет смысл.

Мой вопрос: почему Kotlin генерирует неиспользуемый параметр для функций с параметрами по умолчанию? Это ошибка?

Ответы

Ответ 1

В соответствии с этим, в настоящее время он не используется, но зарезервирован для добавления супервызов с настройками по умолчанию позже.

Вы можете увидеть это в действии здесь:

open class Foo {
    open fun foo(bar: Int = 0, baz: Int) {
        /* ... */
    }
}

class Blah: Foo() {
    override fun foo(bar: Int, baz: Int) {
    }
}

который сгенерирует байт-код-к-Java Foo из:

public class Foo {
   public void foo(int bar, int baz) {
   }

   // $FF: synthetic method
   // $FF: bridge method
   public static void foo$default(Foo var0, int var1, int var2, int var3, Object var4) {
      if(var4 != null) {
         throw new UnsupportedOperationException("Super calls with default arguments not supported in this target, function: foo");
      } else {
         if((var3 & 1) != 0) {
            var1 = 0;
         }

         var0.foo(var1, var2);
      }
   }
}