[2.x] fix: Reject java.io.File as cached task output type#8766
Merged
eed3si9n merged 5 commits intosbt:developfrom Feb 21, 2026
Merged
[2.x] fix: Reject java.io.File as cached task output type#8766eed3si9n merged 5 commits intosbt:developfrom
eed3si9n merged 5 commits intosbt:developfrom
Conversation
378ea96 to
f3d9792
Compare
Member
|
Hi, thanks for the contribution! Please check out our Contributor's Guildeline and:
|
Contributor
Author
Thanks for your detailed feedback. |
f3d9792 to
e7161a0
Compare
eed3si9n
requested changes
Feb 20, 2026
Change the behavior when a cached task's output type contains java.io.File: instead of silently skipping the cache, throw a compile-time error with a message recommending xsbti.VirtualFileRef, xsbti.HashedVirtualFileRef, or xsbti.VirtualFile, and linking to the caching documentation. Internal sbt tasks that return File types are wrapped with Def.uncached to opt out of caching. Fixes sbt#8762 Generated-by: GitHub Copilot (Claude)
e7161a0 to
890bb27
Compare
eed3si9n
reviewed
Feb 21, 2026
| ((ThisBuild / baseDirectory).value / "target" / "sona-bundle" / "bundle.zip").toPath() | ||
| ) | ||
| .toFile(), | ||
| sonaBundle := Def.uncached( |
Member
There was a problem hiding this comment.
As a general strategy, I think we should put @trainsient on Keys.scala instead of putting Def.uncached(...) in Defaults.scala since this would force the build users to also put Def.uncached(...) when they rewire the task.
Use @transient on File-returning keys in Keys.scala instead of wrapping tasks with Def.uncached in Defaults.scala. This ensures build users who rewire these tasks also get caching skipped automatically. - Add @transient to 19 File-returning taskKey definitions in Keys.scala - Revert Def.uncached wrappers from Defaults.scala - Error at compile time when File is used as cached task output type - Update error message to recommend @transient and link to docs - Update scripted tests to use @transient approach Fixes sbt#8762 Generated-by: GitHub Copilot (Claude Opus 4.6)
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Fixes #8762
When a task returns
java.io.File(e.g.assembly / assemblyOutputPath), the result gets cached byActionCache. SinceFileserializes as an absolute path string, the cached value becomes stale whenscalaVersionchanges via++ 2.13.18!— the path still contains the old Scala version directory.Reproduction (from #8762)
Solution
In
Cont.scala'scallActionCachemethod, detect when the task's return typeAcontainsjava.io.Fileat compile time usingcontainsFileType[A]. When it does, skip wrapping the task body withActionCache.cache(...), while still processing anyDef.declareOutput(...)calls vialetOutput. This way:taskKey[File]tasks are never cached (sinceFileisn't content-addressable)Def.declareOutput(...)continues to work correctly for File tasksTests
cache/skip-file-cachescripted test: Defines ataskKey[File]that depends onscalaVersion, switches versions, and asserts the returned path updates.actions/task-map(usesDef.declareOutputwithtaskKey[File]) continues to pass.actions/* cache/* tests/* compiler-project/*etc. — all pass.