Kotlin: define constructors that throw for async functions#2813
Kotlin: define constructors that throw for async functions#2813bendk wants to merge 1 commit intomozilla:mainfrom
Conversation
These constructors always just throw an exception, since Kotlin doesn't supprot async constructors. This is less confusing for users than just skipping the codegen (mozilla#2804).
|
How about adding |
|
In #2804 we discussed making the codegen fail at build time, however I went with this approach for a couple reasons:
I'm not totally sure this is the right way though, a build-time failure would be nicer in many cases compared to generating code that's just going to throw when you use it. However, that second bullet feels important to me. Maybe we could extend the language-specific config code that allows function/method renaming to also allow skipping codegen for functions/methods. That would give those users a decent path forward: they just need to add the constructor to that skip configuration. |
|
I'm not sure I understood the comment correctly, but |
|
My comment wasn't a response to yours, we just happened to post at the same time. It was more me thinking out-loud on other ways to handle this. Adding |
|
I think this will be confusing to many users, but we can simulate async constructors in Kotlin by adding class Foo private constructor(public val v: String) {
override fun toString() = "Foo($v)"
companion object {
suspend operator fun invoke(v: Int): Foo {
return Foo(v.toString())
}
}
}
fun main() = runBlocking {
println(Foo(15)) // invoking Foo.Companion.invoke(15)
} |
|
If I understand it right this will result in runtime error. I am not particularly fond of this solution since CI checks will pass and give a false sense of safety. Rust supports conditional compilation so it's possible to handle differences for android/ios by providing alternative constructors. As such build error isn't a problem but would help catch issues early on during CI pass |
The motivation for this is avoiding async constructors (mozilla#2813). We'd like things to fail at build time if you have an async constructor and are generating bindings for a language that doesn't support them. However, this prevents a valid use case: I want the async constructor on languages that do support them, but not on the others. This change allows us to support that. Users would need to exclude the constructor on languages that don't support it. Actually, now that think about it I don't think any built-in language supports async constructors, but maybe external binding generators could or this could be useful for some other feature.
The motivation for this is avoiding async constructors (mozilla#2813). We'd like things to fail at build time if you have an async constructor and are generating bindings for a language that doesn't support them. However, this prevents a valid use case: I want the async constructor on languages that do support them, but not on the others. This change allows us to support that. Users would need to exclude the constructor on languages that don't support it. Actually, now that think about it I don't think any built-in language supports async constructors, but maybe external binding generators could or this could be useful for some other feature.
The motivation for this is avoiding async constructors (mozilla#2813). We'd like things to fail at build time if you have an async constructor and are generating bindings for a language that doesn't support them. However, this prevents a valid use case: I want the async constructor on languages that do support them, but not on the others. This change allows us to support that. Users would need to exclude the constructor on languages that don't support it. Actually, now that think about it I don't think any built-in language supports async constructors, but maybe external binding generators could or this could be useful for some other feature.
The motivation for this is avoiding async constructors (mozilla#2813). We'd like things to fail at build time if you have an async constructor and are generating bindings for a language that doesn't support them. However, this prevents a valid use case: I want the async constructor on languages that do support them but not on ones that don't. This change allows us to support that by allowing users to exclude the constructor on languages that don't support it. Actually, now that think about it I don't think any built-in language supports async constructors, but maybe external binding generators could or this could be useful for some other feature.
I agree with this and made #2822 as a way to move us towards build-time errors. |
mhammond
left a comment
There was a problem hiding this comment.
IIUC, you don't want to do this now, but would rather throw at bindgen time?
| constructor({% call kt::arg_list(cons, true) -%}) { | ||
| throw InternalException("async primary constructors are not supported on Kotlin"); | ||
| } | ||
| // Note no constructor generated for this object as it is async. |

These constructors always just throw an exception, since Kotlin doesn't supprot async constructors. This is less confusing for users than just skipping the codegen (#2804).