noinline and crossinline

Most likely, noinline and crossinline are keywords that you will add to your code when the Kotlin compiler tells you to add them to your code by way of an error message.

For many developers, simply doing what the compiler tells them to do is sufficient. However, in case you really want to know why the compiler is complaining… read on!

noinline: Keep the Lambda as an Object

When we mark a function as inline, the code associated with that function is used as a replacement for any calls to that function, so we avoid the overhead of the function call. Most of the time, we focus on “the code associated with that function” as being the function body. However, it also means the code associated with any lambda expressions passed as function type parameters to the function.

Take this code, for example:

inline fun beUseful(whenDone: () -> Unit) {
  // TODO something useful
  
  whenDone()
}

fun main() {
  beUseful {
    println("hello, world!")
  }
}

Because beUseful() is marked as inline, not only is the body of beUseful() inlined at the call site, but so is the lambda expression that we pass as whenDone().

Sometimes, this is fine — all we want to do with the function type is invoke() it, as we are doing here. However, in other cases, we will try to treat the function type as an object, storing it somewhere or passing it to some other function:

fun somethingElse(thingToDo: () -> Unit) {
  thingToDo()
}

inline fun beUseful(whenDone: () -> Unit) {
  // TODO something useful
  
  somethingElse(whenDone)
}

fun main() {
  beUseful {
    println("hello, world!")
  }
}

Here, we get:

Illegal usage of inline-parameter 'whenDone' in 'public inline fun beUseful(whenDone: () -> Unit): Unit
defined in root package in file klassbook.kt'. Add 'noinline' modifier to the parameter declaration

So, we can follow the directions of the compiler and add noinline to that parameter:

fun somethingElse(thingToDo: () -> Unit) {
  thingToDo()
}

inline fun beUseful(noinline whenDone: () -> Unit) {
  // TODO something useful
  
  somethingElse(whenDone)
}

fun main() {
  beUseful {
    println("hello, world!")
  }
}

This tells Kotlin to not treat that parameter as inline, so it is able to be treated an an object and be passed around.


Prev Table of Contents Next

This book is licensed under the Creative Commons Attribution-ShareAlike 4.0 International license.