Rob Elliot
03/14/2025, 10:40 AMfun <T : CharSequence> foo(input: T): Pair<T, Int> = input to input.length
fun foo(): Pair<String, Int> = foo("defaultvalue")
but switching it to a default argument does not:
// does not compile, Type mismatch. Required: T Found: String
fun <T : CharSequence> foo(input: T = "defaultvalue"): Pair<T, Int> = input to input.length
Intuitively I would expect it to work.Youssef Shoaib [MOD]
03/14/2025, 10:45 AMfoo<StringBuilder>().first
is expected to magically create a string builder out of nowhereRob Elliot
03/14/2025, 10:46 AMfoo<StringBuilder>().first
is a compilation error.Youssef Shoaib [MOD]
03/14/2025, 10:48 AMfun <T : CharSequence> foo(input: T = TODO()): Pair<T, Int> = input to input.length
Rob Elliot
03/14/2025, 10:51 AMStringBuilder
and String
are not compatible subtypes of CharSequence
, so it cannot resolve T
.Youssef Shoaib [MOD]
03/14/2025, 10:53 AMinline fun <reified T : CharSequence> foo(input: T = "defaultvalue"): Pair<T, Int> = magicallyCreate<T>() to input.length
So how's the compiler to know that explicitly specifying the type parameter is not allowed if the default value is used?Rob Elliot
03/14/2025, 10:55 AMYoussef Shoaib [MOD]
03/14/2025, 10:55 AMfun <T : CharSequence> foo(input: T? = null): Pair<T, Int> {
val input: T = input ?: "defaultvalue"
return input to input.length
}
And of course String
is not automatically T
.Rob Elliot
03/14/2025, 10:56 AMYoussef Shoaib [MOD]
03/14/2025, 10:56 AMT
on its own. What you're asking for is a lower bound on T
, which doesn't even exist in Kotlin.
Default values actually compile to something sort-of similar to what I showed. They're not macro-inlined or anything like that.Youssef Shoaib [MOD]
03/14/2025, 11:00 AMfoo<StringBuilder>()
) where it'd fail. I guess the error could be somehow propagated to the call site, but I can imagine some situations where that'd be undesirable.
Also, the type of the default value is not part of the API signature of a function. The fact that it has default values is, but the type of a default value itself isn't. Supporting this would mean that changing the type of a default value results in binary-incompatible changes, which doesn't quite fit the mental model for default valuesKlitos Kyriacou
03/14/2025, 11:41 AMfun <T : CharSequence> foo(
@Suppress("UNCHECKED_CAST") input: T = "defaultvalue" as T
): Pair<T, Int> = input to input.length
Also, you need to specify a parameter type at the call site, such as foo<String>()
Rob Elliot
03/14/2025, 11:51 AMfun foo(arg: Baz) = TODO(); fun foo() = foo(defaultValue)
and fun foo(arg: Baz = defaultValue) = TODO()
.Youssef Shoaib [MOD]
03/14/2025, 11:53 AMfun <T : CharSequence> foo(input: T): Pair<T, Int> = input to input.length
fun <T : CharSequence> foo(): Pair<T, Int> = foo("defaultvalue") // doesn't compile
Maybe that clears it up a bit more? The type parameters are considered part of the signature that needs to be preserved, and they're not influenced by default values at allRob Elliot
03/14/2025, 11:55 AM