Ruckus
04/14/2022, 6:04 PMinterface Gen<A : Gen.A, B : Gen.B> {
fun a(): A
fun b(): B
open class A
open class B
}
class Values
class Scope<A : Gen.A, B : Gen.B>(
val gen: Gen<A, B>
) {
operator fun String.invoke(values: context(Values) B.() -> Unit) {
with(Values()) {
values(this, gen.b())
}
}
}
operator fun <A : Gen.A, B : Gen.B> Gen<A, B>.invoke(
rules: context(Scope<A, B>) A.() -> Unit
) {
with(Scope(this)) {
rules(this, a())
}
}
This does not compile:
object MyGen : Gen<MyGen.A, MyGen.B> {
override fun a() = A()
override fun b() = B()
open class A : Gen.A() {
val a = "a"
}
open class B : Gen.B() {
val b = "b"
}
}
fun main() {
MyGen {
a {
// `this` is `Any?`, but should be `MyGen.B`
println(b) // Error: Unresolved reference: b
}
}
}
Is my assumption flawed that this
should be MyGen.B
where I marked it?a
shows
public final operator fun String.invoke(
values: @ContextFunctionTypeParams(count = 1)() (P.() -> Unit)
): Unit
Which may indicate the problem, but I don't know.Youssef Shoaib [MOD]
04/14/2022, 6:21 PMScope
has:
fun <S: Gen.A, P: Gen.B> Scope<S, P>.scopeId() = this
(this is really useful when debugging weird context receivers issues since you can't quite see a list of context receivers rn)
and hitting Ctrl-Shift-P in IDEA says that the Scope
is of type Scope<MyGen.A, out Any?>
which is really weirdoperator fun <A : Gen.A, B : Gen.B> Gen<A, B>.invoke(
rules: context(Scope<A, B>) A.(TypeWrapper<B>) -> Unit
) {
with(Scope(this)) {
rules(this, a(), TypeWrapper.IMPL)
}
}
fun main() {
MyGen {
a {
scopeId()
// `this` now shows `MyGen.B`
println(b) // Error: Unresolved reference: b
}
}
}
fun <S: Gen.A, P: Gen.B> Scope<S, P>.scopeId() = this
Ruckus
04/14/2022, 6:25 PMYoussef Shoaib [MOD]
04/14/2022, 6:25 PMRuckus
04/14/2022, 6:39 PMTypeWrapper
for a workaround as well. Not just for the overhead, but it also is much more semantically clear what the parameter is there for (and I can throw on a deprecation annotation for good measure).Youssef Shoaib [MOD]
04/14/2022, 9:09 PMtype()
). In the same thread, I provided this list of TypeWrappers up to 22 type params.