Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AutoBuilder will not build Kotlin data class with Duration #1579

Open
wesalvaro opened this issue Aug 17, 2023 · 3 comments
Open

AutoBuilder will not build Kotlin data class with Duration #1579

wesalvaro opened this issue Aug 17, 2023 · 3 comments
Labels
Component: value P3 Status: accepted type=documentation Documentation that is other than for an API

Comments

@wesalvaro
Copy link

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 Kotlin Duration, I get the follow error:

[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

Perhaps because Duration is an inline class?

public inline class Duration internal constructor(private val rawValue: Long) : Comparable<Duration> {
@eamonnmcmanus
Copy link
Member

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.


@eamonnmcmanus eamonnmcmanus added Component: value type=documentation Documentation that is other than for an API Status: accepted labels Aug 17, 2023
@chaoren chaoren added P2 P3 and removed P2 labels Aug 17, 2023
@wesalvaro
Copy link
Author

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... 😅

@Rasel688
Copy link

[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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Component: value P3 Status: accepted type=documentation Documentation that is other than for an API
Projects
None yet
Development

No branches or pull requests

4 participants