From 739dedb017f00026624d8f812eecf700bbd8729a Mon Sep 17 00:00:00 2001 From: Adrien Piquerez Date: Tue, 6 Feb 2024 15:01:56 +0100 Subject: [PATCH 1/2] Remove usage of Manifest in Structure.scala --- .../sbt/internal/EvaluateConfigurations.scala | 15 ++--- .../src/main/scala/sbt/Previous.scala | 2 +- .../src/main/scala/sbt/Structure.scala | 44 ++++----------- main/src/main/scala/sbt/Main.scala | 11 +--- main/src/main/scala/sbt/ScopedKeyData.scala | 26 ++++----- .../sbt/internal/SettingCompletions.scala | 32 ++--------- .../sbt/internal/server/SettingQuery.scala | 4 +- main/src/main/scala/sbt/nio/Settings.scala | 30 +++++----- .../scala/sbt/internal/util/Attributes.scala | 56 ++++++++++++------- 9 files changed, 87 insertions(+), 133 deletions(-) diff --git a/buildfile/src/main/scala/sbt/internal/EvaluateConfigurations.scala b/buildfile/src/main/scala/sbt/internal/EvaluateConfigurations.scala index d3a630b10..6057a9261 100644 --- a/buildfile/src/main/scala/sbt/internal/EvaluateConfigurations.scala +++ b/buildfile/src/main/scala/sbt/internal/EvaluateConfigurations.scala @@ -388,18 +388,15 @@ object Index { )(label: AttributeKey[_] => String): Map[String, AttributeKey[_]] = { val multiMap = settings.groupBy(label) val duplicates = multiMap.iterator - .collect { case (k, xs) if xs.size > 1 => (k, xs.map(_.manifest)) } - .collect { - case (k, xs) if xs.size > 1 => (k, xs) - } + .collect { case (k, xs) if xs.size > 1 => (k, xs.map(_.tag)) } + .collect { case (k, xs) if xs.size > 1 => (k, xs) } .toVector if duplicates.isEmpty then multiMap.collect { case (k, v) if validID(k) => (k, v.head) }.toMap else - sys.error( - duplicates map { case (k, tps) => - "'" + k + "' (" + tps.mkString(", ") + ")" - } mkString ("Some keys were defined with the same name but different types: ", ", ", "") - ) + val duplicateStr = duplicates + .map { case (k, tps) => s"'$k' (${tps.mkString(", ")})" } + .mkString(",") + sys.error(s"Some keys were defined with the same name but different types: $duplicateStr") } private[this] type TriggerMap = collection.mutable.HashMap[TaskId[?], Seq[TaskId[?]]] diff --git a/main-settings/src/main/scala/sbt/Previous.scala b/main-settings/src/main/scala/sbt/Previous.scala index 4db97b7f3..72e98a53a 100644 --- a/main-settings/src/main/scala/sbt/Previous.scala +++ b/main-settings/src/main/scala/sbt/Previous.scala @@ -56,7 +56,7 @@ object Previous { // private[sbt] def task: ScopedKey[Task[T]] = key.task lazy val stamped: JsonFormat[T] = - StampedFormat.withStamp(key.task.key.manifest.toString)(format) + StampedFormat.withStamp(key.task.key.tag.toString)(format) def setTask(newTask: ScopedKey[Task[T]]) = new Referenced(newTask, format) private[sbt] def read(streams: Streams): Option[T] = diff --git a/main-settings/src/main/scala/sbt/Structure.scala b/main-settings/src/main/scala/sbt/Structure.scala index 6c3ca0ed8..fe5d7a26d 100644 --- a/main-settings/src/main/scala/sbt/Structure.scala +++ b/main-settings/src/main/scala/sbt/Structure.scala @@ -10,7 +10,7 @@ package sbt import scala.annotation.targetName import sbt.internal.util.Types.* -import sbt.internal.util.{ AttributeKey, Settings, SourcePosition } +import sbt.internal.util.{ AttributeKey, KeyTag, Settings, SourcePosition } import sbt.internal.util.TupleMapExtension.* import sbt.util.OptJsonWriter import sbt.ConcurrentRestrictions.Tag @@ -259,11 +259,6 @@ object Scoped: implicit def inputScopedToKey[T](s: InputKey[T]): ScopedKey[InputTask[T]] = ScopedKey(s.scope, s.key) - private[sbt] def coerceTag[A1: ClassTag]: Manifest[A1] = - summon[ClassTag[A1]] match - case mf: Manifest[A1] => mf - case tag => ManifestFactory.classType[A1](tag.runtimeClass) - /** * Mixin trait for adding convenience vocabulary associated with specifying the [[Scope]] of a setting. * Allows specification of the Scope or part of the [[Scope]] of a setting being referenced. @@ -736,10 +731,12 @@ end TupleSyntax object TupleSyntax extends TupleSyntax -import Scoped.{ coerceTag, extendScoped } +import Scoped.extendScoped /** Constructs InputKeys, which are associated with input tasks to define a setting. */ object InputKey: + private given [A: ClassTag]: KeyTag[InputTask[A]] = + KeyTag.Task(summon[ClassTag[A]].runtimeClass) def apply[A1: ClassTag](label: String): InputKey[A1] = apply[A1](label, "", KeyRanks.DefaultInputRank) @@ -755,8 +752,6 @@ object InputKey: description: String, rank: Int, ): InputKey[A1] = - given mf: ClassTag[InputTask[A1]] = - ManifestFactory.classType[InputTask[A1]](classOf[InputTask[A1]], coerceTag[A1]) apply(AttributeKey[InputTask[A1]](label, description, rank)) def apply[A1: ClassTag]( @@ -773,8 +768,6 @@ object InputKey: extend1: Scoped, extendN: Scoped* ): InputKey[A1] = - given mf: ClassTag[InputTask[A1]] = - ManifestFactory.classType[InputTask[A1]](classOf[InputTask[A1]], coerceTag[A1]) apply(AttributeKey[InputTask[A1]](label, description, extendScoped(extend1, extendN), rank)) def apply[A1](akey: AttributeKey[InputTask[A1]]): InputKey[A1] = @@ -784,27 +777,19 @@ end InputKey /** Constructs TaskKeys, which are associated with tasks to define a setting. */ object TaskKey: + private given [A: ClassTag]: KeyTag[Task[A]] = KeyTag.Task(summon[ClassTag[A]].runtimeClass) + def apply[A1: ClassTag](label: String): TaskKey[A1] = - apply[A1]( - label = label, - description = "", - rank = Int.MaxValue, - ) + apply[A1](label = label, description = "", rank = Int.MaxValue) def apply[A1: ClassTag](label: String, description: String): TaskKey[A1] = - apply[A1]( - label = label, - description = description, - rank = Int.MaxValue, - ) + apply[A1](label = label, description = description, rank = Int.MaxValue) def apply[A1: ClassTag]( label: String, description: String, rank: Int, ): TaskKey[A1] = - given mf: ClassTag[Task[A1]] = - ManifestFactory.classType[Task[A1]](classOf[Task[A1]], coerceTag[A1]) apply(AttributeKey[Task[A1]](label, description, rank)) def apply[A1: ClassTag]( @@ -813,8 +798,6 @@ object TaskKey: extend1: Scoped, extendN: Scoped* ): TaskKey[A1] = - given mf: ClassTag[Task[A1]] = - ManifestFactory.classType[Task[A1]](classOf[Task[A1]], coerceTag[A1]) apply(AttributeKey[Task[A1]](label, description, extendScoped(extend1, extendN))) def apply[A1: ClassTag]( @@ -824,25 +807,18 @@ object TaskKey: extend1: Scoped, extendN: Scoped* ): TaskKey[A1] = - given mf: ClassTag[Task[A1]] = - ManifestFactory.classType[Task[A1]](classOf[Task[A1]], coerceTag[A1]) apply(AttributeKey[Task[A1]](label, description, extendScoped(extend1, extendN), rank)) def apply[A1](akey: AttributeKey[Task[A1]]): TaskKey[A1] = Scoped.scopedTask(Scope.ThisScope, akey) - def local[A1: ClassTag]: TaskKey[A1] = - given mf: ClassTag[Task[A1]] = - ManifestFactory.classType[Task[A1]](classOf[Task[A1]], coerceTag[A1]) - apply[A1](AttributeKey.local[Task[A1]]) + def local[A1: ClassTag]: TaskKey[A1] = apply[A1](AttributeKey.local[Task[A1]]) end TaskKey /** Constructs SettingKeys, which are associated with a value to define a basic setting. */ object SettingKey: - def apply[A1: ClassTag: OptJsonWriter]( - label: String, - ): SettingKey[A1] = + def apply[A1: ClassTag: OptJsonWriter](label: String): SettingKey[A1] = apply[A1]( label = label, description = "", diff --git a/main/src/main/scala/sbt/Main.scala b/main/src/main/scala/sbt/Main.scala index 780584abc..74e777de1 100644 --- a/main/src/main/scala/sbt/Main.scala +++ b/main/src/main/scala/sbt/Main.scala @@ -440,14 +440,14 @@ object BuiltinCommands { private[this] def quiet[T](t: => T): Option[T] = try Some(t) - catch { case _: Exception => None } + catch case _: Exception => None def settingsCommand: Command = showSettingLike( SettingsCommand, settingsPreamble, KeyRanks.MainSettingCutoff, - key => !isTask(key.manifest) + key => key.tag.isSetting ) def tasks: Command = @@ -455,7 +455,7 @@ object BuiltinCommands { TasksCommand, tasksPreamble, KeyRanks.MainTaskCutoff, - key => isTask(key.manifest) + key => key.tag.isTaskOrInputTask ) def showSettingLike( @@ -518,11 +518,6 @@ object BuiltinCommands { def withDescription(keys: Seq[AttributeKey[_]]): Seq[AttributeKey[_]] = keys.filter(_.description.isDefined) - def isTask( - mf: ClassTag[_] - )(using taskMF: ClassTag[Task[_]], inputMF: ClassTag[InputTask[_]]): Boolean = - mf.runtimeClass == taskMF.runtimeClass || mf.runtimeClass == inputMF.runtimeClass - def topNRanked(n: Int) = (keys: Seq[AttributeKey[_]]) => sortByRank(keys).take(n) def highPass(rankCutoff: Int) = diff --git a/main/src/main/scala/sbt/ScopedKeyData.scala b/main/src/main/scala/sbt/ScopedKeyData.scala index 50b99e3ac..23badf22d 100644 --- a/main/src/main/scala/sbt/ScopedKeyData.scala +++ b/main/src/main/scala/sbt/ScopedKeyData.scala @@ -8,26 +8,20 @@ package sbt import Def.ScopedKey +import sbt.internal.util.KeyTag final case class ScopedKeyData[A](scoped: ScopedKey[A], value: Any) { import sbt.internal.util.Types.const val key = scoped.key val scope = scoped.scope - def typeName: String = fold(fmtMf("Task[%s]"), fmtMf("InputTask[%s]"), key.manifest.toString) - def settingValue: Option[Any] = fold(const(None), const(None), Some(value)) + def typeName: String = key.tag.toString + def settingValue: Option[Any] = + key.tag match + case KeyTag.Setting(_) => Some(value) + case _ => None def description: String = - fold( - fmtMf("Task: %s"), - fmtMf("Input task: %s"), - "Setting: %s = %s" format (key.manifest.toString, value.toString) - ) - def fold[T](targ: OptManifest[_] => T, itarg: OptManifest[_] => T, s: => T): T = - key.manifest.runtimeClass match - case TaskClass => targ(key.manifest.typeArguments.head) - case InputTaskClass => itarg(key.manifest.typeArguments.head) - case _ => s - def fmtMf(s: String): OptManifest[_] => String = s format _ - - private val TaskClass = classOf[Task[_]] - private val InputTaskClass = classOf[InputTask[_]] + key.tag match + case KeyTag.Task(typeArg) => s"Task: $typeArg" + case KeyTag.InputTask(typeArg) => s"Input task: $typeArg" + case KeyTag.Setting(typeArg) => s"Setting: $typeArg = $value" } diff --git a/main/src/main/scala/sbt/internal/SettingCompletions.scala b/main/src/main/scala/sbt/internal/SettingCompletions.scala index 24f5b1ab5..e4a61fe18 100644 --- a/main/src/main/scala/sbt/internal/SettingCompletions.scala +++ b/main/src/main/scala/sbt/internal/SettingCompletions.scala @@ -8,7 +8,7 @@ package sbt package internal -import sbt.internal.util.{ AttributeKey, complete, Relation, Settings, Types, Util } +import sbt.internal.util.{ AttributeKey, complete, KeyTag, Relation, Settings, Types, Util } import sbt.util.Show import sbt.librarymanagement.Configuration @@ -352,40 +352,16 @@ private[sbt] object SettingCompletions { */ def configScalaID(c: String): String = Util.quoteIfKeyword(c.capitalize) - /** Applies a function on the underlying manifest for T for `key` depending if it is for a `Setting[T]`, `Task[T]`, or `InputTask[T]`. */ - @nowarn - def keyType[S](key: AttributeKey[_])( - onSetting: ClassTag[_] => S, - onTask: ClassTag[_] => S, - onInput: ClassTag[_] => S - )(using tm: ClassTag[Task[_]], im: ClassTag[InputTask[_]]): S = - def argTpe = key.manifest.typeArguments.head match - case m: Manifest[_] => m - case _ => sys.error(s"Manifest not found for ${key} typeArgument") - val TaskClass = tm.runtimeClass - val InputTaskClass = im.runtimeClass - key.manifest.runtimeClass match - case TaskClass => onTask(argTpe) - case InputTaskClass => onInput(argTpe) - case _ => onSetting(key.manifest) - - /** For a Task[T], InputTask[T], or Setting[T], this returns the manifest for T. */ - def keyUnderlyingType(key: AttributeKey[_]): ClassTag[_] = - keyType(key)(idFun, idFun, idFun) - /** * Returns a string representation of the underlying type T for a `key` representing a `Setting[T]`, `Task[T]`, or `InputTask[T]`. * This string representation is currently a cleaned up toString of the underlying ClassTag. */ def keyTypeString[T](key: AttributeKey[_]): String = - val tagToString = (tag: ClassTag[_]) => complete.TypeString.cleanup(tag.toString) - keyType(key)(tagToString, tagToString, tagToString) + complete.TypeString.cleanup(key.tag.typeArg.toString) /** True if the `key` represents a setting or task that may be appended using an assignment method such as `+=`. */ - def appendable(key: AttributeKey[_]): Boolean = { - val underlying = keyUnderlyingType(key).runtimeClass - appendableClasses.exists(_ isAssignableFrom underlying) - } + def appendable(key: AttributeKey[_]): Boolean = + appendableClasses.exists(_.isAssignableFrom(key.tag.typeArg)) /** The simple name of the Global scope, which can be used to reference it in the default setting context. */ final val GlobalID = Scope.Global.getClass.getSimpleName.stripSuffix("$") diff --git a/main/src/main/scala/sbt/internal/server/SettingQuery.scala b/main/src/main/scala/sbt/internal/server/SettingQuery.scala index 50776c484..270f7d510 100644 --- a/main/src/main/scala/sbt/internal/server/SettingQuery.scala +++ b/main/src/main/scala/sbt/internal/server/SettingQuery.scala @@ -104,7 +104,7 @@ object SettingQuery { def getJsonWriter[A](key: AttributeKey[A]): Either[String, JsonWriter[A]] = key.optJsonWriter match { case SomeJsonWriter(jw) => Right(jw) - case NoJsonWriter() => Left(s"JsonWriter for ${key.manifest} not found") + case NoJsonWriter() => Left(s"JsonWriter for ${key.tag} not found") } def toJson[A: JsonWriter](x: A): JValue = Converter toJsonUnsafe x @@ -128,7 +128,7 @@ object SettingQuery { for { key <- key json <- getSettingJsonValue(structure, key) - } yield SettingQuerySuccess(json, key.key.manifest.toString) + } yield SettingQuerySuccess(json, key.key.tag.toString) } def handleSettingQuery(req: SettingQuery, structure: BuildStructure): SettingQueryResponse = diff --git a/main/src/main/scala/sbt/nio/Settings.scala b/main/src/main/scala/sbt/nio/Settings.scala index 5a8724a76..26816d8d7 100644 --- a/main/src/main/scala/sbt/nio/Settings.scala +++ b/main/src/main/scala/sbt/nio/Settings.scala @@ -14,7 +14,7 @@ import java.util.concurrent.ConcurrentHashMap import sbt.Keys._ import sbt.internal.Clean.ToSeqPath import sbt.internal.Continuous.FileStampRepository -import sbt.internal.util.AttributeKey +import sbt.internal.util.KeyTag import sbt.internal.{ Clean, Continuous, DynamicInput, WatchTransitiveDependencies } import sbt.nio.FileStamp.Formats._ import sbt.nio.FileStamper.{ Hash, LastModified } @@ -53,7 +53,7 @@ private[sbt] object Settings { /** * This method checks if the setting is for a task with a return type in: - * `File`, `Seq[File]`, `Path`, `Seq[Path`. If it does, then we inject a number of + * `File`, `Seq[File]`, `Path`, `Seq[Path]`. If it does, then we inject a number of * task definition settings that allow the user to check if the output paths of * the task have changed. It also adds a custom clean task that will delete the * paths returned by the task, provided that they are in the task's target directory. We also @@ -68,10 +68,11 @@ private[sbt] object Settings { setting: Def.Setting[_], fileOutputScopes: Set[Scope] ): List[Def.Setting[_]] = { - setting.key.key match { - case ak: AttributeKey[_] if taskClass.isAssignableFrom(ak.manifest.runtimeClass) => + val attributeKey = setting.key.key + attributeKey.tag match { + case tag: KeyTag.Task[?] => def default: List[Def.Setting[_]] = { - val scope = setting.key.scope.copy(task = Select(ak)) + val scope = setting.key.scope.copy(task = Select(attributeKey)) if (fileOutputScopes.contains(scope)) { val sk = setting.asInstanceOf[Def.Setting[Task[Any]]].key val scopedKey = Keys.dynamicFileOutputs in (sk.scope in sk.key) @@ -93,15 +94,15 @@ private[sbt] object Settings { addTaskDefinition(Def.setting[Task[Seq[Path]]](key, init, setting.pos)) :: outputsAndStamps(taskKey) } - ak.manifest.typeArguments match - case (t: Manifest[_]) :: Nil if seqClass.isAssignableFrom(t.runtimeClass) => - t.typeArguments match { - case p :: Nil if pathClass.isAssignableFrom(p.runtimeClass) => mkSetting[Seq[Path]] - case _ => default - } - case (t: Manifest[_]) :: Nil if pathClass.isAssignableFrom(t.runtimeClass) => - mkSetting[Path] - case _ => default + if seqClass.isAssignableFrom(tag.typeArg) then + // TODO fix this: maybe using the taskKey macro to convey the information + // t.typeArguments match { + // case p :: Nil if pathClass.isAssignableFrom(p.runtimeClass) => mkSetting[Seq[Path]] + // case _ => default + // } + default + else if pathClass.isAssignableFrom(tag.typeArg) then mkSetting[Path] + else default case _ => Nil } } @@ -161,7 +162,6 @@ private[sbt] object Settings { }) :: fileStamps(scopedKey) :: allFilesImpl(scope) :: changedInputFilesImpl(scope) } - private[this] val taskClass = classOf[Task[_]] private[this] val seqClass = classOf[Seq[_]] private[this] val pathClass = classOf[java.nio.file.Path] diff --git a/util-collection/src/main/scala/sbt/internal/util/Attributes.scala b/util-collection/src/main/scala/sbt/internal/util/Attributes.scala index bf38f3972..48b0f0567 100644 --- a/util-collection/src/main/scala/sbt/internal/util/Attributes.scala +++ b/util-collection/src/main/scala/sbt/internal/util/Attributes.scala @@ -12,15 +12,32 @@ import scala.reflect.ClassTag import sbt.util.OptJsonWriter import sjsonnew.* -// T must be invariant to work properly. +enum KeyTag[A]: + case Setting[A](typeArg: Class[?]) extends KeyTag[A] + case Task[A](typeArg: Class[?]) extends KeyTag[A] + case InputTask[A](typeArg: Class[?]) extends KeyTag[A] + + override def toString: String = this match + case Setting(typeArg) => typeArg.toString + case Task(typeArg) => s"Task[$typeArg]" + case InputTask(typeArg) => s"InputTask[$typeArg]" + + def typeArg: Class[?] + def isSetting: Boolean = isInstanceOf[Setting[?]] + def isTaskOrInputTask: Boolean = !isSetting +end KeyTag + +object KeyTag: + given [A: ClassTag]: KeyTag[A] = Setting[A](summon[ClassTag[A]].runtimeClass) + +// A must be invariant to work properly. // Because it is sealed and the only instances go through AttributeKey.apply, -// a single AttributeKey instance cannot conform to AttributeKey[T] for different Ts +// a single AttributeKey instance cannot conform to AttributeKey[A] for different As sealed trait AttributeKey[A]: /** The runtime evidence for `A`. */ - def manifest: ClassTag[A] - // def classTag: ClassTag[A] + def tag: KeyTag[A] /** The label is the identifier for the key and is camelCase by convention. */ def label: String @@ -59,37 +76,37 @@ private[sbt] abstract class SharedAttributeKey[A] extends AttributeKey[A]: override final def hashCode = label.hashCode override final def equals(o: Any) = (this eq o.asInstanceOf[AnyRef]) || (o match { - case a: SharedAttributeKey[t] => a.label == this.label && a.manifest == this.manifest + case a: SharedAttributeKey[t] => a.label == this.label && a.tag == this.tag case _ => false }) final def isLocal: Boolean = false end SharedAttributeKey object AttributeKey { - def apply[A: ClassTag: OptJsonWriter](name: String): AttributeKey[A] = + def apply[A: KeyTag: OptJsonWriter](name: String): AttributeKey[A] = make(name, None, Nil, Int.MaxValue) - def apply[A: ClassTag: OptJsonWriter](name: String, rank: Int): AttributeKey[A] = + def apply[A: KeyTag: OptJsonWriter](name: String, rank: Int): AttributeKey[A] = make(name, None, Nil, rank) - def apply[A: ClassTag: OptJsonWriter](name: String, description: String): AttributeKey[A] = + def apply[A: KeyTag: OptJsonWriter](name: String, description: String): AttributeKey[A] = apply(name, description, Nil) - def apply[A: ClassTag: OptJsonWriter]( + def apply[A: KeyTag: OptJsonWriter]( name: String, description: String, rank: Int ): AttributeKey[A] = apply(name, description, Nil, rank) - def apply[A: ClassTag: OptJsonWriter]( + def apply[A: KeyTag: OptJsonWriter]( name: String, description: String, extend: Seq[AttributeKey[_]] ): AttributeKey[A] = apply(name, description, extend, Int.MaxValue) - def apply[A: ClassTag: OptJsonWriter]( + def apply[A: KeyTag: OptJsonWriter]( name: String, description: String, extend: Seq[AttributeKey[_]], @@ -98,40 +115,39 @@ object AttributeKey { make(name, Some(description), extend, rank) private[sbt] def copyWithRank[A](a: AttributeKey[A], rank: Int): AttributeKey[A] = - make(a.label, a.description, a.extend, rank)(using a.manifest, a.optJsonWriter) + make(a.label, a.description, a.extend, rank)(using a.tag, a.optJsonWriter) - private[this] def make[A]( + private[this] def make[A: KeyTag: OptJsonWriter]( name: String, description0: Option[String], extend0: Seq[AttributeKey[_]], rank0: Int - )(using mf: ClassTag[A], ojw: OptJsonWriter[A]): AttributeKey[A] = + ): AttributeKey[A] = new SharedAttributeKey[A]: require( name.headOption.exists(_.isLower), s"A named attribute key must start with a lowercase letter: $name" ) - override def manifest: ClassTag[A] = mf + override def tag: KeyTag[A] = summon override val label: String = Util.hyphenToCamel(name) override def description: Option[String] = description0 override def extend: Seq[AttributeKey[_]] = extend0 override def rank: Int = rank0 - override def optJsonWriter: OptJsonWriter[A] = ojw + override def optJsonWriter: OptJsonWriter[A] = summon - private[sbt] def local[A](using ct: ClassTag[A], ojw: OptJsonWriter[A]): AttributeKey[A] = + private[sbt] def local[A: KeyTag: OptJsonWriter]: AttributeKey[A] = new AttributeKey[A]: - override def manifest: ClassTag[A] = ct + override def tag: KeyTag[A] = summon override def label: String = LocalLabel override def description: Option[String] = None override def extend: Seq[AttributeKey[_]] = Nil override def toString = label override def isLocal: Boolean = true override def rank: Int = Int.MaxValue - override val optJsonWriter: OptJsonWriter[A] = ojw + override val optJsonWriter: OptJsonWriter[A] = summon private[sbt] final val LocalLabel = "$" + "local" - } /** From 144b86e32eea7351604637479b5b7a1778d29926 Mon Sep 17 00:00:00 2001 From: Adrien Piquerez Date: Mon, 12 Feb 2024 15:28:57 +0100 Subject: [PATCH 2/2] fix tag of InputTask --- main-settings/src/main/scala/sbt/Structure.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main-settings/src/main/scala/sbt/Structure.scala b/main-settings/src/main/scala/sbt/Structure.scala index fe5d7a26d..fc527cd4a 100644 --- a/main-settings/src/main/scala/sbt/Structure.scala +++ b/main-settings/src/main/scala/sbt/Structure.scala @@ -736,7 +736,7 @@ import Scoped.extendScoped /** Constructs InputKeys, which are associated with input tasks to define a setting. */ object InputKey: private given [A: ClassTag]: KeyTag[InputTask[A]] = - KeyTag.Task(summon[ClassTag[A]].runtimeClass) + KeyTag.InputTask(summon[ClassTag[A]].runtimeClass) def apply[A1: ClassTag](label: String): InputKey[A1] = apply[A1](label, "", KeyRanks.DefaultInputRank)