Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why Kotlin function with default parameters creates a method with unused parameter

Tags:

kotlin

See this example code in Kotlin:

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

After decompiling it to Java code (Tools -> Kotlin -> Show Kotlin Bytecode -> Decompile) I got the following code

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);
}

I noticed that the resulting Java method has an unused Object var3 parameter.

I kind of thought that it may be related to functions in a class but when decompiling this code

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

I got this code

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);
   }
}

As you can see the Object parameter is still unused and just sits there. Upon additional tests I noticed the same behavior for extension methods. The same goes when the default parameter is last (i.e. fun foo(bar: Int, baz: Int = 0) {})

I've also done a basic test to check what is that value set to when calling that function using the code below

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

And

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

After decompiling it I got the following code

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

And

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

Which makes even less sense whatsoever.

My question is: Why does Kotlin generate an unused parameter for functions with default parameters? Is it a bug?

like image 636
Mibac Avatar asked Sep 03 '17 15:09

Mibac


People also ask

How do you pass a default parameter in Kotlin?

Kotlin Default Argument In Kotlin, you can provide default values to parameters in function definition. If the function is called with arguments passed, those arguments are used as parameters. However, if the function is called without passing argument(s), default arguments are used.

What is use of default parameters in function?

Default function parameters allow named parameters to be initialized with default values if no value or undefined is passed.

What is default parameter What are the importance of default parameter?

When no value is passed in the function definition, a default value is being set for the function definition, known as the default parameter. It allows the named parameters to get initialized with a default value when either undefined or no value is passed.

When a lambda function has only one parameter what is its default name Kotlin?

Only one parameter can be marked as vararg . If a vararg parameter is not the last one in the list, values for the subsequent parameters can be passed using named argument syntax, or, if the parameter has a function type, by passing a lambda outside the parentheses.


1 Answers

According to this, currently it's unused, but is reserved for adding super calls with defaults later.

You can see it in action here:

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

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

which will generate a bytecode-to-Java Foo of:

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);
      }
   }
}
like image 70
fal Avatar answered Sep 29 '22 13:09

fal