CLOVIS
08/27/2026, 8:00 PMinterface Foo<In> {
fun <Out> foo(block: FooDsl<In, Out>.() -> Unit) { … }
}
class FooDsl<In, Out> {
fun one(a: In)
fun two(a: In, b: Out)
}
val f = object : Foo<String> { … }
The compiler knows how to infer this one:
f.foo {
two("a", 5)
}
because the only missing piece is Out and it's provided.
However, the compiler doesn't know how to infer this one:
f.foo {
one("a")
}
because Out never appears.
However, as the library author, I have knowledge in this situation that what the user intended is for In === Out , which the user can verbosely write as:
f.foo<String> {
one("a")
}
I'd be great if I could somehow hint this to the compiler.CLOVIS
08/27/2026, 8:01 PMYoussef Shoaib [MOD]
08/27/2026, 8:16 PMone extensions with the In == Out version having higher priority. No clue if it works, but worth a shotYoussef Shoaib [MOD]
08/27/2026, 8:21 PMinterface Foo<In> {
fun <Out> foo(block: FooDsl<In, Out>.() -> Unit) { }
}
class FooDsl<In, Out> {
fun two(a: In, b: Out) {}
}
fun <In> FooDsl<In, In>.one(a: In) {}
fun <In, Out> FooDsl<In, Out>.one(a: In, unit: Unit = Unit) {}
val f = object: Foo<String> {}
fun main() {
f.foo {
two("a", 5)
}
f.foo {
one("a")
}
f.foo {
two("a", 5)
one("a")
}
}Youssef Shoaib [MOD]
08/27/2026, 8:46 PMf.foo {
one("a")
two("a", 5) // Argument type mismatch: actual type is 'Int', but 'String' was expected.
}
f.foo {
two("a", 5)
one("a")
}
which you might not want, but I think it makes sense here.Alejandro Serrano.Mena
08/28/2026, 7:18 AMCLOVIS
08/28/2026, 6:56 PMAnyCLOVIS
08/28/2026, 7:02 PMCLOVIS
08/28/2026, 7:02 PMCLOVIS
08/28/2026, 7:03 PMIn is bound into the wrapper type Foo . It's only Out that needs to be specified, in the case of one(a: In) . But since in the case where we don't know Out I want to infer it as In … then I can just declare one(a: Out) , no?CLOVIS
08/28/2026, 7:07 PMexclude() which has no argument at allCLOVIS
08/28/2026, 7:07 PMYoussef Shoaib [MOD]
08/29/2026, 8:09 AMexclude as well. There's the order-dependence I highlighted, but I think that's fine. There isn't too much you can do to avoid extension functions here. Well, you can do something like this:
object FooDslExt {
context(dsl: FooDsl<In, In>)
fun <In> exclude() {}
}
interface Foo<In> {
fun <Out> foo(block: context(FooDsl<In, Out>) FooDslExt.() -> Unit)
}
Because builder inference works on contextsCLOVIS
08/29/2026, 9:25 AM