context receivers on companion objects, is this so...
# language-evolution
j
context receivers on companion objects, is this something that will be supported? if so, will the behavior be?
Copy code
interface NumberFactory {
	fun create(): Int
}

class Something {

	context(NumberFactory)
	companion object {
		fun generate(): Int {
			return this@NumberFactory.create()
		}
	}
}

fun main() {

	val number1 = object : NumberFactory {
		override fun create(): Int {
			return 1
		}
	}

	val number2 = object : NumberFactory {
		override fun create(): Int {
			return 2
		}
	}

	while (true) {
		with(if (Random().nextBoolean()) {
			number1
		} else {
			number2
		}) {
			Something.generate()
		}.also(::println)
	}
will we be seeing 1 and 2 in the above output or will it only be 1s the whole time (assuming the first factory picked by random is number1)?
y
That doesn't make sense as a feature. defining a context on a class (or in this case an object) means that, when the object is created, the context should be available, and so it doesn't make sense for objects to have that at all. Instead, what you really want is this:
Copy code
class Something {

	companion object {
        context(NumberFactory)
		fun generate(): Int {
			return this@NumberFactory.create()
		}
	}
}
Which is already supported
j
what is not supported is:
Copy code
interface NumberFactory {
	fun create(): Int
}

interface Generator {
    fun generate(): Int
}

class Something {
	companion object : Generator {
        context(NumberFactory)
		override fun generate(): Int {
			return this@NumberFactory.create()
		}
	}
}
unless you put the context on top of the generate in the interface too I was exploring whether context on top of the companion object would somehow get into the companion functions, in other words
Copy code
context(...) companion obect { fun f1() {} fun f2() {} }
would then be the same as
Copy code
companion obect { context(...) fun f1() {} context(...) fun f2() {} }
y
Well of course it won't be supported. An interface defines what exactly is needed to call its methods. Adding an extra context is therefore not going to make you compatible with the interface. It's a design issue, not a language issue. You can also have generator defined as:
Copy code
interface Generator<in Ctx> {
  context(Ctx) fun generate(): Int
}
So that anyone calling generate must either know what kind of context this generator wants and provide it, or they must ask the caller themselves to provide that context.