Open wesalvaro opened 1 year ago
We've encountered this internally. Googlers can see it at b/276527697.
Here's what I wrote there. In the discussion, we have data class Options
which has a Duration
parameter.
This is a tricky one. kotlin.time.Duration
is an inline class. That means it isn't ordinarily possible to construct it from Java code at all: new Options(myDuration)
won't work. In fact Options
doesn't have a Duration
field, it has a long
, though the Kotlin compiler does its best to hide that from Kotlin users.
Presumably the main purpose of the builder is for Java clients, since Kotlin clients can just do Options(...)
using keyword arguments and defaulting as appropriate. I think the best we can do is something like this:
data class Options(val duration: Duration) {
@AutoBuilder(callMethod = "make")
interface Builder {
fun setDuration(duration: java.time.Duration): Builder
fun build(): Options
}
companion object {
@JvmStatic fun make(duration: java.time.Duration) = Options(duration.toKotlinDuration())
}
}
I also agree that we could have a better error message here. The message is technically true: there really is no visible constructor. But the underlying problem is with the inline parameter, and perhaps we could detect that and mention it in the error message.
I like that workaround! It's an extra method, but mostly copy+paste.
As for the error message: Yeah, that would have saved me some time... 😅
[AutoBuilderNoVisible] No visible constructor for REDACTED public static abstract interface Builder { ^
at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122)
at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191)
at com.google.devtools.kotlin.compiler.plugin.codegen.concurrent.KtCodegenExecutor.afterExecute(KtCodegenExecutor.kt:39)
at com.google.devtools.kotlin.compiler.plugin.codegen.syncer.KtCodegenFloorExecutor.afterExecute(KtCodegenFloorExecutor.kt:27)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
at java.base/java.lang.Thread.run(Thread.java:1623)
Caused by: error: [AutoBuilderNoVisible] No visible constructor for REDACTED public static abstract interface Builder { ^
at com.google.devtools.kotlin.compiler.plugin.codegen.compilation.KtCodegenPluginCompilerApp.compilePlugin(KtCodegenPluginCompilerApp.kt:151)
at com.google.devtools.kotlin.compiler.plugin.codegen.KtCodegenCompiler.processKtCodegenFloor$lambda$6(KtCodegenCompiler.kt:294)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:577)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
... 2 more
I have a Kotlin data class with a nested
@AutoBuilder
.If I change one of my Kotlin data class constructor arguments from a
Long
to a KotlinDuration
, I get the follow error:Perhaps because
Duration
is aninline class
?