Olaf Gottschalk
08/10/2026, 8:43 AMTransformer interface... See this:
import org.gradle.api.Transformer
import java.io.Serializable
tasks.register<Copy>("demo") {
from(layout.projectDirectory)
into(layout.buildDirectory.dir("out"))
rename(MyTransformer())
}
private class MyTransformer : Transformer<String, String>, Serializable {
override fun transform(name: String): String = name
}
This should compile. But it does not.
In Gradle < 9.7.0, the Transformer interface was declared <OUT: Any?, IN>, now it's <OUT: Any, IN>....Vampire
08/10/2026, 9:05 AMrename says you can return null to use the original name.
The method according to JavaDoc is
rename(Transformer<@Nullable String, String> renamer)
and Transformer according to JavaDoc is
Transformer<OUT extends @Nullable Object, IN>
So it seems to me it should still be nullable in 9.7.0Vampire
08/10/2026, 9:11 AMMyTransformer : Transformer<String?, String>, Serializable and then it works, which does not work in 9.7.0 either.
😵💫Vampire
08/10/2026, 9:13 AMVampire
08/10/2026, 9:14 AMOlaf Gottschalk
08/10/2026, 2:38 PMTransformer<String?, String> to Transformer<String, String> - which is ok and understandable. But then, rename was not able to take that anymore due to its signature requiring a nullable OUT... I actually thought this Slack was for bug reporting to Gradle... 😄Vampire
08/10/2026, 2:42 PMBut that needed a change fromI'd say that is neither ok nor understandable. I'd say the bug is that you need to change fromtoTransformer<String?, String>- which is ok and understandableTransformer<String, String>
String? to String there.
I don't understand why you should need to change it, can you explain to me why it is understandable for you?
Also, as I said, if you do Transformer<String, String> in 9.6.1 it does not work either.
And if something worked in 9.6.1 (the String? variant) it should not break before being deprecated in some Gradle 9.x and before a Gradle 10.x.
I actually thought this Slack was for bug reporting to Gradle... 😄No, this is a community slack where mainly users like me help fellow users. For bug reporting and feature requests there is GitHub issues.
Olaf Gottschalk
08/10/2026, 2:44 PMVampire
08/10/2026, 2:45 PMWell, they changed the signature of TransformerNo they didn't and they shouldn't without first deprecating and then in a major version breaking
Vampire
08/10/2026, 2:45 PMOlaf Gottschalk
08/10/2026, 2:46 PMVampire
08/10/2026, 2:46 PMVampire
08/10/2026, 2:47 PMOk, why don't they test such things then...?Probably because you cannot test each and every edge case? If you don't have a subclass but a lambda, it probably works without problem. And as I said, as the siganture did not change, I suspect it might be the update of the bundled Kotlin version and maybe a bug in that one.
Vampire
08/10/2026, 2:48 PMOlaf Gottschalk
08/10/2026, 2:48 PMVampire
08/10/2026, 2:48 PMVampire
08/10/2026, 2:48 PMYes, of course - but a lambda cannot be serializedThat's not necessarily true
Olaf Gottschalk
08/10/2026, 2:49 PMVampire
08/10/2026, 2:49 PMVampire
08/10/2026, 2:49 PMOlaf Gottschalk
08/10/2026, 2:49 PMVampire
08/10/2026, 2:49 PMThe more I work with Gradle, the more I get frustrated from basic lack of good programming habits on their side.I really don't know what you mean, can you elaborate? I have the quite opposite experience
Vampire
08/10/2026, 2:50 PMOk, I had a normal lambda there and when enabling config cache I get errors that it cannot be serialized. Hence, the class.What was the exact error?
Vampire
08/10/2026, 2:50 PMOlaf Gottschalk
08/10/2026, 2:52 PM1 problem was found storing the configuration cache.
- Task `:copySapDependencies` of type `org.gradle.api.tasks.Copy`: cannot serialize Gradle script object references as these are not supported with the configuration cache.
See <https://docs.gradle.org/9.7.0/userguide/configuration_cache_requirements.html#config_cache:requirements:disallowed_types>Vampire
08/10/2026, 2:52 PMVampire
08/10/2026, 2:52 PMtasks.register<Copy>("demo") {
from(layout.projectDirectory.dir("foo"))
into(layout.buildDirectory.dir("out"))
rename { it }
}
works perfectly fineVampire
08/10/2026, 2:53 PMOlaf Gottschalk
08/10/2026, 2:53 PMVampire
08/10/2026, 2:53 PMval foo = ""
tasks.register<Copy>("demo") {
from(layout.projectDirectory.dir("foo"))
into(layout.buildDirectory.dir("out"))
rename { foo }
}Olaf Gottschalk
08/10/2026, 2:54 PMVampire
08/10/2026, 2:54 PMVampire
08/10/2026, 2:54 PMval foo = ""
tasks.register<Copy>("demo") {
from(layout.projectDirectory.dir("foo"))
into(layout.buildDirectory.dir("out"))
val foo = foo
rename { foo }
}Olaf Gottschalk
08/10/2026, 2:55 PMVampire
08/10/2026, 2:55 PMfoo into a local variable foo and use that in the lambdaOlaf Gottschalk
08/10/2026, 2:55 PMVampire
08/10/2026, 2:55 PMOk, it has references to top level boolean values...Exactly, and that is the problem
Vampire
08/10/2026, 2:56 PMclass Constants {
companion object {
val foo = ""
}
}
tasks.register<Copy>("demo") {
from(layout.projectDirectory.dir("foo"))
into(layout.buildDirectory.dir("out"))
rename { Constants.foo }
}Vampire
08/10/2026, 2:56 PMOlaf Gottschalk
08/10/2026, 2:57 PMVampire
08/10/2026, 2:58 PMOlaf Gottschalk
08/10/2026, 2:59 PMVampire
08/10/2026, 3:04 PMVampire
08/10/2026, 3:04 PMVampire
08/10/2026, 3:05 PMOUT extends @Nullable ObjectVampire
08/10/2026, 3:05 PMVampire
08/10/2026, 3:06 PMVampire
08/10/2026, 3:10 PMOlaf Gottschalk
08/10/2026, 3:32 PMOlaf Gottschalk
08/10/2026, 3:33 PMOlaf Gottschalk
08/10/2026, 3:33 PMVampire
08/10/2026, 3:34 PMVampire
08/10/2026, 3:35 PMNo restriction as it's Java.The restriction comes from the nullable annotation that Kotlin is taking into consideration
Vampire
08/10/2026, 3:39 PM