Complex generics

Hello, I am writing some method which I wan’t to be using with dsl like code, however I am stuck on following problem. I have reduced the code that is troubling me to following

package somePackage

/**
 *
 */
class SomeClass(
    val someString: String? = null,
    val someInteger: Int? = null,
    val someBoolean: Boolean? = null
)

fun main() {
    val map: Map< String, SomeClass.() -> Any?> = mapOf(
        "someString" to {someString},
        "someInteger" to {someInteger},
        "someBoolean" to {someBoolean}
    )
}

The function of type SomeClass.() -> Any? passed as value to map should serve as projection function over instance of SomeClass. The projection function works fine if it is passed as single argument, however I need to have to populate the map with entries like above.

Idea does not show any errors in the editor, however when I try to compile the code, the compilation fails with following.

Error:(13, 51) Kotlin: Type inference failed. Expected type mismatch: inferred type is Map<String, () -> ???> but Map<String, SomeClass.() -> Any?> was expected
Error:(14, 26) Kotlin: Unresolved reference: someString
Error:(15, 27) Kotlin: Unresolved reference: someInteger
Error:(16, 27) Kotlin: Unresolved reference: someBoolean

EDIT: even the code completion in the editor works inside the lambda with receiver, so in the editor, the type inference works, so I don’t know why the compiler cannot infer it.

I have come to a workaround with using method reference, but the code just look more tidy with the lambda receiver function.

Example of what I am trying to achieve and comparison with method reference

private val validator = requiredFields(
    "someString" to SomeClass::someString,
    "someInteger" to SomeClass::someInteger
).all()

private val validator1 = requiredFields<SomeClass>(
    "someString" to { someString },
    "someInteger" to { someInteger }
).all()

Here, the parameter is vararg of Pair, but the problem is the same.

Is there any way to have the DSL cleaner than with method reference?
Why the lambda receiver version does not compile? Is it maybe made like this on purpose?

From the announcement of 1.3.40 Early Access Preview

Early Access Preview for Kotlin 1.3.40 is now open. We begin stabilization process of new type inference . Now new type inference , which has been experimental since 1.3.0, is enabled by default in the plugin, but not for compilation. Thus, if code without errors in IDE does not compile, please, report the issue to our issue tracker . The feature can be disabled by unchecking Enable new type inference algorithm for IDE analysis (experimental) checkbox in Settings -> Build, Execution, Deployment -> Compiler -> Kotlin Compiler .

1 Like

thank, I didn’t know about this.