Report missing spread operator for vararg

I have been working on a logger class, I have a method:

fun log(message: String, vararg args: Any?) {
    println(String.format(message, *args))
}

Where String.format(..) has following implementation in StringsJVM.kt

@kotlin.internal.InlineOnly
public inline fun String.Companion.format(format: String, vararg args: Any?): String = java.lang.String.format(format, *args)

After running Detekt I receive an error about spread operator performance impact. So I check the implementation of String.format() in StringsJVM.kt and I see that args will be later passed to the java.lang.String.format() with a spread operator; so it seems to be safe to use spread in my method. I go ahead and change the implementation to:

fun log(message: String, vararg args: Any?) {
    println(String.format(message, args))
}

To double-check I use ‘Go to Implementation’ on my new call String.format(message, args) - and of course I end up on the same method in the StringsJVM.kt. In my mind, I verify the flow:

  • My log function receives vararg args: Any?, then passes those to String.format(format: String, vararg args: Any?)

  • Spread operator is then applied before calling into java.lang.String.format, so the array gets unwrapped in separate items.

  • java.lang.String.format receives separate items, everyone is happy.

  • IDE is not complaining about missing spread operator, so I did everything right.

Wrong. Running log("Placeholders %s %s", "one", "two") results in an exception: array got wrapped with another array, so when unwrapped it had only one item.

It was very easy to make this mistake - propagating vararg args from parameters to another method call without spread operator feels like a natural thing to do. Maybe it’s better to add a linter check to detect such attempts and mark them as possible bug? There can be exceptions when omitted spread operator is intended, but in most cases it is most probably an error.