'How to capture type using builder inference in kotlin

Using the new Builder Inference feature in Kotlin allows for the type of a builder to be realised by use, rather than a more explicit declaration.

For instance


class Test<T> {
  fun add(a: T) {}
  fun secondFun(a: T) {}
  fun <T> Test<T>.lambda(a: (T) -> Unit) {}
}


@OptIn(ExperimentalTypeInference::class)
fun <T> builder(@BuilderInference x: Test<T>.() -> Unit): Test<T> {
  return Test<T>().apply(x)
}

The following code results in a builder with an Int type as T.

val x = builder {
  add(1)
} // has type Test<Int>

Yet, use of the type in further calls after the initial add leads to ambiguity by the kotlin compiler.

  val x: Test<Int> = builder {
    add(1)
    lambda { it + 1 }
  }

This fails on the use of the + with

Overload resolution ambiguity: 
public operator fun <T> Array<TypeVariable(T)>.plus(element: TypeVariable(T)): Array<TypeVariable(T)> defined in kotlin.collections
public operator fun ByteArray.plus(element: Byte): ByteArray defined in kotlin.collections
public operator fun IntArray.plus(element: Int): IntArray defined in kotlin.collections
public operator fun LongArray.plus(element: Long): LongArray defined in kotlin.collections
public operator fun ShortArray.plus(element: Short): ShortArray defined in kotlin.collections
public operator fun String?.plus(other: Any?): String defined in kotlin
public inline operator fun UByteArray.plus(element: UByte): UByteArray defined in kotlin.collections
public inline operator fun UIntArray.plus(element: UInt): UIntArray defined in kotlin.collections
public inline operator fun ULongArray.plus(element: ULong): ULongArray defined in kotlin.collections
public inline operator fun UShortArray.plus(element: UShort): UShortArray defined in kotlin.collections
public operator fun <T> Collection<TypeVariable(T)>.plus(element: TypeVariable(T)): List<TypeVariable(T)> defined in kotlin.collections
public operator fun <T> Iterable<TypeVariable(T)>.plus(element: TypeVariable(T)): List<TypeVariable(T)> defined in kotlin.collections
public operator fun <T> Set<TypeVariable(T)>.plus(element: TypeVariable(T)): Set<TypeVariable(T)> defined in kotlin.collections
public operator fun <T> Sequence<TypeVariable(T)>.plus(element: TypeVariable(T)): Sequence<TypeVariable(T)> defined in kotlin.sequences

Seemingly, it's not continuing with the idea that the type T is an int. Though IntelliJ does have the Int type hint in its own analysis for it within the lambda.

Is there a way to call the lambda DSL method with it resolving to Int without explicit typing required given that there's already been a call that can infer a type? Or is this a limitation of Builder Inference in kotlin as it's potentially looking for a more specific/general type in future uses of T.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source