Vampire
03/12/2024, 3:09 PM@JvmName
to be able to produce valid bytecode?Youssef Shoaib [MOD]
03/12/2024, 3:24 PMfun foo(bar: Int)
fun foo(baz: Int, unit: Unit = Unit)
hfhbd
03/12/2024, 3:25 PMephemient
03/12/2024, 3:36 PM@JvmName
and sufficient @Suppress
you can
@JvmName("fooX")
@Suppress("CONFLICTING_OVERLOADS")
fun foo(x: Int) { println("foo(x = $x)") }
@JvmName("fooY")
@Suppress("CONFLICTING_OVERLOADS")
fun foo(y: Int) { println("foo(y = $y)")}
foo(x = 1)
foo(y = 2)
Vampire
03/12/2024, 4:18 PMVampire
03/12/2024, 4:28 PMvararg pleaseUseNamedArguments: Unit,
๐Landry Norris
03/12/2024, 8:15 PMephemient
03/12/2024, 11:14 PMephemient
03/12/2024, 11:15 PMdmitriy.novozhilov
03/13/2024, 10:34 AMVampire
03/13/2024, 12:18 PMJvmName
.dmitriy.novozhilov
03/13/2024, 12:23 PMVampire
03/13/2024, 12:42 PMdmitriy.novozhilov
03/13/2024, 12:47 PMVampire
03/13/2024, 12:47 PMVampire
03/13/2024, 12:47 PMVampire
03/13/2024, 12:49 PMf(a = 2)
, where a
is a parameter specified in the declaration of f
. Such calls are treated the same way as normal calls, but the overload resolution sets are filtered to only contain callables which have matching formal parameter names for all named parameters from the call.
>
> Important: this filtering is done before we perform selection of the overload candidate set w.r.t. rules for the respective type of call.Vampire
03/13/2024, 12:50 PMdmitriy.novozhilov
03/13/2024, 12:53 PM// FILE: a.kt
package a
fun foo() {} // (1)
// FILE: b.kt
package b
fun foo() {} // (2)
// FILE: c.kt
import a.*
import b.*
fun test() {
foo() // ambiguity between (1) and (2)
}
But you can't declare two functions with same signature in one namespace (package/class), as it produce conflict of overloads
// FILE: a.kt
fun foo() {} // conflicting
fun foo() {} // overloads
Vampire
03/13/2024, 12:57 PMVampire
03/13/2024, 12:57 PMdmitriy.novozhilov
03/13/2024, 12:59 PM@BinarySignatureName
proposal will be implementedVampire
03/13/2024, 1:00 PMVampire
03/13/2024, 1:01 PMdmitriy.novozhilov
03/13/2024, 1:02 PMdynamic
in js), but we are trying to minimize their number to keep the language unifieddmitriy.novozhilov
03/13/2024, 1:03 PMYoussef Shoaib [MOD]
03/13/2024, 1:05 PMfun main() {
println(foo(a = 0))
println(foo(b = 0))
// println(foo(0)) errors
}
fun foo(a: Int, unit: Unit1 = UnitImpl) = a
fun foo(b: Int, unit: Unit2 = UnitImpl) = b + 42
sealed interface Unit1
sealed interface Unit2
private object UnitImpl: Unit1, Unit2
(Using Unitx
because naming is hard)
Note that UnitImpl
is private so that it can never be specified, and hence one can't discriminate between the overloads except by using the names. You might choose to make it public so that one can avoid using named parameters and instead doing UnitImpl as Unit1
Vampire
03/13/2024, 1:05 PMThis can be said about anything, actually
E.g. about ternary operatorNo, that's just a very missed feature you refuse to implement. ๐
Vampire
03/13/2024, 1:07 PMBtw, here's a perfectly legal way to do what you want in Kotlin while ensuring that no overload is preferred when no named parameter is usedHow is it, compared to your other proposal at the beginning of the thread? ๐
Youssef Shoaib [MOD]
03/13/2024, 1:09 PMfoo(0)
to the unit-less overload, this one instead ensures that there's no possible disambiguation without simply specifying the parameter namesVampire
03/13/2024, 1:10 PMYoussef Shoaib [MOD]
03/13/2024, 1:12 PMUnitImpl
implement them. I'm using one object because old Android habits. I think this solution is "good enough".Vampire
03/13/2024, 1:14 PMVampire
03/13/2024, 1:14 PMYoussef Shoaib [MOD]
03/13/2024, 1:17 PMUnit1
vs Unit2
Vampire
03/13/2024, 2:11 PMephemient
03/13/2024, 2:29 PMsealed class Nothing1
sealed class Nothing2
fun foo(x: Int, unused: Nothing1? = null) {}
fun foo(y: Int, unused: Nothing2? = null) {}
Youssef Shoaib [MOD]
03/13/2024, 2:30 PMobject Unit1
and object Unit2
Vampire
03/13/2024, 2:35 PMNullPointerException
at org.jetbrains.kotlinx.serialization.compiler.backend.ir.SerialInfoImplJvmIrGenerator.getImplClass(SerialInfoImplJvmIrGenerator.kt:57) >:-DYoussef Shoaib [MOD]
03/13/2024, 2:36 PMsealed
btw, it was just meant to prevent someone from implementing it and thus choosing an overload in a convoluted wayVampire
03/13/2024, 2:36 PMVampire
03/13/2024, 4:08 PMopen
it should not be necessary, should it?Vampire
03/13/2024, 6:01 PMfun foo(bar: Int, @Suppress("UNUSED_PARAMETER") overloadSelector: ByBar? = null) = ...
fun foo(baz: Int, @Suppress("UNUSED_PARAMETER") overloadSelector: ByBaz? = null) = ...
class ByBar private constructor()
class ByBaz private constructor()
Now I can from Kotlin consumer do
foo(bar = 1)
foo(baz = 2)
And for example from Groovy consumer
foo(1, null as ByBar)
foo(2, null as ByBaz)
or from Java consumer
foo(1, (ByBar) null)
foo(2, (ByBaz) null)