From 887c65620b5df26b0c1cecff605068c340495fb0 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Sat, 11 Jul 2026 22:00:57 -0400 Subject: [PATCH] [2.x] Allow opt-out of transient warning **Problem** We want to opt out of the transient key warning. **Solution** This implements an optout via nowarn annotation. --- build.sbt | 4 ++++ .../sbt/internal/util/appmacro/Cont.scala | 13 +++++++--- .../internal/util/appmacro/ContextUtil.scala | 24 +++++++++++++++++++ .../project-load/warning-optout/build.sbt | 7 ++++++ .../warning-optout/project/plugins.sbt | 1 + .../sbt-test/project-load/warning-optout/test | 1 + 6 files changed, 47 insertions(+), 3 deletions(-) create mode 100644 sbt-app/src/sbt-test/project-load/warning-optout/build.sbt create mode 100644 sbt-app/src/sbt-test/project-load/warning-optout/project/plugins.sbt create mode 100644 sbt-app/src/sbt-test/project-load/warning-optout/test diff --git a/build.sbt b/build.sbt index be5d01642..af8605502 100644 --- a/build.sbt +++ b/build.sbt @@ -664,6 +664,10 @@ lazy val coreMacrosProj = (project in file("core-macros")) name := "Core Macros", SettingKey[Boolean]("exportPipelining") := false, mimaSettings, + mimaBinaryIssueFilters ++= Seq( + exclude[ReversedMissingMethodProblem]("sbt.internal.util.appmacro.ContextUtil.*"), + exclude[DirectMissingMethodProblem]("sbt.internal.util.appmacro.ContextUtil#Input.*"), + ), ) // Fixes scope=Scope for Setting (core defined in collectionProj) to define the settings system used in build definitions diff --git a/core-macros/src/main/scala/sbt/internal/util/appmacro/Cont.scala b/core-macros/src/main/scala/sbt/internal/util/appmacro/Cont.scala index 464a8ae82..2afb57a57 100644 --- a/core-macros/src/main/scala/sbt/internal/util/appmacro/Cont.scala +++ b/core-macros/src/main/scala/sbt/internal/util/appmacro/Cont.scala @@ -306,7 +306,7 @@ trait Cont: .asExprOf[BuildWideCacheConfiguration] inputs.foreach: input => if !input.isCacheInput then - if !Cont.transientAllowSet(input.sym.name) then + if !Cont.transientAllowSet(input.sym.name) && !input.isWarnSuppressed then report.warning( s"transient key ${input.sym.name} is excluded from the cache input" ) @@ -430,6 +430,7 @@ trait Cont: val WrapOutputName = "wrapOutput_\u2603\u2603" val WrapOutputDirectoryName = "wrapOutputDirectory_\u2603\u2603" + var nowarnQuals: Set[String] = Set.empty // Called when transforming the tree to add an input. // For `qual` of type F[A], and a `selection` qual.value. val record = [a] => @@ -470,12 +471,18 @@ trait Cont: }.asTerm) case None => oldTree case _ => - // todo cache opt-out attribute - inputBuf += Input(TypeRepr.of[a], qual, replacement, freshName("q")) + inputBuf += Input( + TypeRepr.of[a], + qual, + replacement, + freshName("q"), + isWarnSuppressed = nowarnQuals.contains(qual.show), + ) oldTree } val exprWithConfig = cacheConfigExprOpt.map(config => '{ $config; $expr }).getOrElse(expr) + nowarnQuals = collectNowarnQuals(exprWithConfig.asTerm) val body = transformWrappers(exprWithConfig.asTerm, record, Symbol.spliceOwner) val r = inputBuf.toList match case Nil => pure(body) diff --git a/core-macros/src/main/scala/sbt/internal/util/appmacro/ContextUtil.scala b/core-macros/src/main/scala/sbt/internal/util/appmacro/ContextUtil.scala index b3547d3d6..78f053d7c 100644 --- a/core-macros/src/main/scala/sbt/internal/util/appmacro/ContextUtil.scala +++ b/core-macros/src/main/scala/sbt/internal/util/appmacro/ContextUtil.scala @@ -76,11 +76,13 @@ trait ContextUtil[C <: Quotes & scala.Singleton](val valStart: Int): private val cacheLevelSym = Symbol.requiredClass("sbt.util.cacheLevel") private val transientSym = Symbol.requiredClass("scala.transient") + private val nowarnAnnotSym = Symbol.requiredClass("scala.annotation.nowarn") final class Input( val tpe: TypeRepr, val qual: Term, val term: Term, val name: String, + val isWarnSuppressed: Boolean, ): override def toString: String = s"Input($tpe, $qual, $term, $name, $tags)" @@ -194,6 +196,28 @@ trait ContextUtil[C <: Quotes & scala.Singleton](val valStart: Int): def idTransform[F[_]]: TermTransform[F] = in => in + /** Collects `qual.show` for each `.value` call wrapped in `@nowarn`, e.g. `(state.value: @nowarn)`. */ + def collectNowarnQuals(tree: Term): Set[String] = + val result = mutable.HashSet[String]() + @tailrec def extractQual(t: Term): Unit = t match + case Inlined(_, _, inner) => extractQual(inner) + case Typed(inner, _) => extractQual(inner) + case Apply(TypeApply(Select(_, _), _ :: Nil), qual :: Nil) => result += qual.show + case Apply(TypeApply(Ident(_), _ :: Nil), qual :: Nil) => result += qual.show + case _ => () + object scanner extends TreeTraverser: + override def traverseTree(t: Tree)(owner: Symbol): Unit = t match + case Typed(inner, tpt) => + tpt.tpe match + case AnnotatedType(_, annot) if annot.tpe.typeSymbol == nowarnAnnotSym => + extractQual(inner) + case _ => + super.traverseTree(t)(owner) + case _ => super.traverseTree(t)(owner) + end scanner + scanner.traverseTree(tree)(Symbol.spliceOwner) + result.toSet + def collectDefs(tree: Term, isWrapper: (String, TypeRepr, Term) => Boolean): Set[Symbol] = val defs = mutable.HashSet[Symbol]() object traverser extends TreeTraverser: diff --git a/sbt-app/src/sbt-test/project-load/warning-optout/build.sbt b/sbt-app/src/sbt-test/project-load/warning-optout/build.sbt new file mode 100644 index 000000000..541f1dc69 --- /dev/null +++ b/sbt-app/src/sbt-test/project-load/warning-optout/build.sbt @@ -0,0 +1,7 @@ +import scala.annotation.nowarn + +lazy val check = taskKey[Unit]("") +check := { + val s = (state.value: @nowarn) + println("hi") +} diff --git a/sbt-app/src/sbt-test/project-load/warning-optout/project/plugins.sbt b/sbt-app/src/sbt-test/project-load/warning-optout/project/plugins.sbt new file mode 100644 index 000000000..7bd8d3d31 --- /dev/null +++ b/sbt-app/src/sbt-test/project-load/warning-optout/project/plugins.sbt @@ -0,0 +1 @@ +Compile / scalacOptions += "-Werror" diff --git a/sbt-app/src/sbt-test/project-load/warning-optout/test b/sbt-app/src/sbt-test/project-load/warning-optout/test new file mode 100644 index 000000000..4e3db8162 --- /dev/null +++ b/sbt-app/src/sbt-test/project-load/warning-optout/test @@ -0,0 +1 @@ +> about