Home > OS >  How can I fix Kotlin Overload Resolution Ambiguity with extension functions and type bounds
How can I fix Kotlin Overload Resolution Ambiguity with extension functions and type bounds

Time:09-16

I want to define an Option type, and then pseudo-polymorphically define a getOrNull operation.

sealed interface Option<out T>
data class Some<out T>(val value: T): Option<T>
object None: Option<Nothing>

fun <T> Option<T>.getOrNull(): T? = when (this) {
    is Some<T> -> getOrNull()
    is None -> getOrNull()
}

fun <T> Some<T>.getOrNull(): T = value
fun None.getOrNull(): Nothing? = null

This all works fine.

But if I tighten the generic type to disallow Option(null) by specifying T: Any

fun <T: Any> Option<T>.getOrNull(): T? = when (this) {
    is Some<T> -> getOrNull()
    is None -> getOrNull()
}

then I get

Kotlin: Overload resolution ambiguity: 
public fun <T : Any> Option<TypeVariable(T)>.getOrNull(): TypeVariable(T)? defined in root package in file Delme.kt
public fun <T> Some<TypeVariable(T)>.getOrNull(): TypeVariable(T) defined in root package in file Delme.kt

for the line is Some<T> -> getOrNull()

How can I tell the compiler which of the two subclass extension functions it should be calling?

CodePudding user response:

The thing is, when you constrain the T of Option<T>.getOrNull but NOT the T of Some<T>.getOrNull you take away the fact that one was more specific than the other (a subtype). Now, they are just "different", hence the resolution ambiguity (the compiler cannot "order" them by specificity anymore).

You can solve it by also constraining Some<T>.getOrNull with Any:

fun <T : Any> Some<T>.getOrNull(): T = value
  • Related