I have: ```interface FooDsl interface Foo { f...
# getting-started
c
I have:
Copy code
interface FooDsl

interface Foo {
    fun foo(block: FooDsl.() -> Unit)
}

class SpecificDsl : FooDsl

abstract class Specific : Foo {
    override fun foo(block: SpecificDsl.() -> Unit) {}
}
The intent is that
Specific.foo
's argument's receiver is a subtype of the declared receiver. That should be sound: the method will provide to the lambda a receiver that is a subtype of what is declared in the parent interface, that's fine. However, I'm hitting the Kotlin limitation with invariant parameters:
Copy code
'foo' overrides nothing.
I can kinda cheat that with an overload:
Copy code
abstract class Specific : Foo {
    @JvmName("fooSpecific")
    fun foo(block: SpecificDsl.() -> Unit) {}

    override fun foo(block: FooDsl.() -> Unit) {}
}
but it appears the compiler prefers calling the override rather than the new overload. I cannot modify
FooDsl
and
Foo
. Is there a trick to making the specific overload more specific to the eyes of the compiler?
y
I am often surprised that overriding parameters is invariant
c
I wish there was a keyword or annotation to opt-in to contravariant parameters on a specific overload
y
Deprecation to the rescue!
Copy code
abstract class Specific : Foo {
	@JvmName("fooSpecific")
	fun foo(block: SpecificDsl.() -> Unit) {}

    @Deprecated("", level = DeprecationLevel.HIDDEN)
	override fun foo(block: FooDsl.() -> Unit) {}
}
c
It's always deprecation, isn't it.
K 2
🫥 1
I had a prototype with
LowPriorityInOverloadResolution
, but deprecation is definitely better