Search code examples
kotlinguice

How to bind a Kotlin Function in Guice


I have a Kotlin class similar to this:

class MyClass @Inject constructor(val work: (Int) -> Unit)) { ... }

Neither the bind nor the @Provides is working:

class FunctionModule : AbstractModule() {

    override fun configure() {
        bind(object : TypeLiteral<Function1<Int, Unit>>() {}).toInstance({})
    }

    @Provides
    fun workFunction(): (Int) -> Unit = { Unit }
    }
}

I keep getting the error:

No implementation for kotlin.jvm.functions.Function1< ? super java.lang.Integer, kotlin.Unit> was bound.

How can I inject an implementation for a Kotlin function using Guice?


Solution

  • tl;dr - Use:

    bind(object : TypeLiteral<Function1<Int, @JvmSuppressWildcards Unit>>() {})
        .toInstance({})
    

    In the class

    class MyClass @Inject constructor(val work: (Int) -> Unit)) { ... }
    

    the parameter work has a type (as least according to Guice) of:

    kotlin.jvm.functions.Function1<? super java.lang.Integer, kotlin.Unit>
    

    However,

    bind(object : TypeLiteral<Function1<Int, Unit>>() {}).toInstance({})
    

    registers a type of kotlin.jvm.functions.Function1<? super java.lang.Integer, **? extends** kotlin.Unit>

    Changing bind to bind(object : TypeLiteral<Function1<Int, **@JvmSuppressWildcards** Unit>>() {}).toInstance({}) to remove the variance on the return type allows Guice to properly inject the function.