Skip to content

Commit d447989

Browse files
committed
Refactor settings, only set deprecated flag replacement after validation
1 parent 69564cb commit d447989

File tree

7 files changed

+98
-64
lines changed

7 files changed

+98
-64
lines changed

community-build/src/scala/dotty/communitybuild/projects.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,7 @@ object projects:
503503
project = "verify",
504504
sbtTestCommand = "verifyJVM/test",
505505
sbtDocCommand = "verifyJVM/doc",
506-
scalacOptions = SbtCommunityProject.scalacOptions.filter(_ != "-Xcheck-macros") // TODO enable -Xcheck-macros
506+
scalacOptions = SbtCommunityProject.scalacOptions.filter(flag != "-Xcheck-macros" && flag != "-Xlint") // TODO enable -Xcheck-macros, wrong flag -Xlint
507507
)
508508

509509
lazy val discipline = SbtCommunityProject(

compiler/src/dotty/tools/dotc/Run.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
377377
runCtx.withProgressCallback: cb =>
378378
_progress = Progress(cb, this, fusedPhases.map(_.traversals).sum)
379379
val cancelAsyncTasty: () => Unit =
380-
if !myAsyncTastyWritten && Phases.picklerPhase.exists && !ctx.settings.YearlyTastyOutput.isDefault then
380+
if !myAsyncTastyWritten && Phases.picklerPhase.exists && !ctx.settings.XearlyTastyOutput.isDefault then
381381
initializeAsyncTasty()
382382
else () => {}
383383

compiler/src/dotty/tools/dotc/config/ScalaSettings.scala

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -355,8 +355,8 @@ private sealed trait XSettings:
355355

356356
val XmacroSettings: Setting[List[String]] = MultiStringSetting(AdvancedSetting, "Xmacro-settings", "setting1,setting2,..settingN", "List of settings which exposed to the macros")
357357

358-
// Deprecated
359-
val Xlint: Setting[List[ChoiceWithHelp[String]]] = UncompleteMultiChoiceHelpSetting(
358+
@deprecated(message = "Superseded by -Wshadow, Scheduled for removal in 3.6.0", since = "3.5.0")
359+
val Xlint: Setting[List[ChoiceWithHelp[String]]] = MultiChoiceHelpSetting(
360360
AdvancedSetting,
361361
name = "Xlint",
362362
helpArg = "advanced warning",
@@ -464,21 +464,36 @@ private sealed trait YSettings:
464464
val YinstrumentDefs: Setting[Boolean] = BooleanSetting(ForkSetting, "Yinstrument-defs", "Add instrumentation code that counts method calls; needs -Yinstrument to be set, too.")
465465

466466
// Deprecated: lifted from -Y to -X
467+
@deprecated(message = "Lifted to -X, Scheduled for removal in 3.6.0", since = "3.5.0")
467468
val YtermConflict: Setting[String] = ChoiceSetting(ForkSetting, "Yresolve-term-conflict", "strategy", "Resolve term conflicts", List("package", "object", "error"), "error", deprecation = Some(Deprecation("Use -Xresolve-term-conflict instead.", "-Xresolve-term-conflict")))
469+
@deprecated(message = "Lifted to -X, Scheduled for removal in 3.6.0", since = "3.5.0")
468470
val YnoGenericSig: Setting[Boolean] = BooleanSetting(ForkSetting, "Yno-generic-signatures", "Suppress generation of generic signatures for Java.", deprecation = Some(Deprecation("Use -Xno-generic-signatures instead.", "-Xno-generic-signatures")))
471+
@deprecated(message = "Lifted to -X, Scheduled for removal in 3.6.0", since = "3.5.0")
469472
val Ydumpclasses: Setting[String] = StringSetting(ForkSetting, "Ydump-classes", "dir", "Dump the generated bytecode to .class files (useful for reflective compilation that utilizes in-memory classloaders).", default = "", deprecation = Some(Deprecation("Use -Xdump-classes instead.", "-Xdump-classes")))
473+
@deprecated(message = "Lifted to -X, Scheduled for removal in 3.6.0", since = "3.5.0")
470474
val YjarCompressionLevel: Setting[Int] = IntChoiceSetting(ForkSetting, "Yjar-compression-level", "compression level to use when writing jar files", Deflater.DEFAULT_COMPRESSION to Deflater.BEST_COMPRESSION, Deflater.DEFAULT_COMPRESSION, deprecation = Some(Deprecation("Use -Xjar-compression-level instead.", "-Xjar-compression-level")))
475+
@deprecated(message = "Lifted to -X, Scheduled for removal in 3.6.0", since = "3.5.0")
471476
val YkindProjector: Setting[String] = ChoiceSetting(ForkSetting, "Ykind-projector", "[underscores, enable, disable]", "Allow `*` as type lambda placeholder to be compatible with kind projector. When invoked as -Ykind-projector:underscores will repurpose `_` to be a type parameter placeholder, this will disable usage of underscore as a wildcard.", List("disable", "", "underscores"), "disable", legacyArgs = true, deprecation = Some(Deprecation("Use -Xkind-projector instead.", "-Xkind-projector")))
477+
@deprecated(message = "Lifted to -X, Scheduled for removal in 3.6.0", since = "3.5.0")
472478
val YdropComments: Setting[Boolean] = BooleanSetting(ForkSetting, "Ydrop-docs", "Drop documentation when scanning source files.", aliases = List("-Ydrop-comments"), deprecation = Some(Deprecation("Use -Xdrop-docs instead.", "-Xdrop-docs")))
479+
@deprecated(message = "Lifted to -X, Scheduled for removal in 3.6.0", since = "3.5.0")
473480
val YcookComments: Setting[Boolean] = BooleanSetting(ForkSetting, "Ycook-docs", "Cook the documentation (type check `@usecase`, etc.)", aliases = List("-Ycook-comments"), deprecation = Some(Deprecation("Use -Xcook-docs instead.", "-Xcook-docs")))
481+
@deprecated(message = "Lifted to -X, Scheduled for removal in 3.6.0", since = "3.5.0")
474482
val YreadComments: Setting[Boolean] = BooleanSetting(ForkSetting, "Yread-docs", "Read documentation from tasty.", deprecation = Some(Deprecation("Use -Xread-docs instead.", "-Xread-docs")))
483+
@deprecated(message = "Lifted to -X, Scheduled for removal in 3.6.0", since = "3.5.0")
475484
val YnoDecodeStacktraces: Setting[Boolean] = BooleanSetting(ForkSetting, "Yno-decode-stacktraces", "Show raw StackOverflow stacktraces, instead of decoding them into triggering operations.", deprecation = Some(Deprecation("Use -Xno-decode-stacktraces instead.", "-Xno-decode-stacktraces")))
485+
@deprecated(message = "Lifted to -X, Scheduled for removal in 3.6.0", since = "3.5.0")
476486
val YnoEnrichErrorMessages: Setting[Boolean] = BooleanSetting(ForkSetting, "Yno-enrich-error-messages", "Show raw error messages, instead of enriching them with contextual information.", deprecation = Some(Deprecation("Use -Xno-enrich-error-messages instead.", "-Xno-enrich-error-messages")))
487+
@deprecated(message = "Lifted to -X, Scheduled for removal in 3.6.0", since = "3.5.0")
477488
val YdebugMacros: Setting[Boolean] = BooleanSetting(ForkSetting, "Ydebug-macros", "Show debug info when quote pattern match fails", deprecation = Some(Deprecation("Use -Xdebug-macros instead.", "-Xdebug-macros")))
489+
@deprecated(message = "Lifted to -X, Scheduled for removal in 3.6.0", since = "3.5.0")
478490
val YjavaTasty: Setting[Boolean] = BooleanSetting(ForkSetting, "Yjava-tasty", "Pickler phase should compute TASTy for .java defined symbols for use by build tools", aliases = List("-Ypickle-java"), preferPrevious = true, deprecation = Some(Deprecation("Use -Xjava-tasty instead.", "-Xjava-tasty")))
491+
@deprecated(message = "Lifted to -X, Scheduled for removal in 3.6.0", since = "3.5.0")
479492
val YearlyTastyOutput: Setting[AbstractFile] = OutputSetting(ForkSetting, "Yearly-tasty-output", "directory|jar", "Destination to write generated .tasty files to for use in pipelined compilation.", NoAbstractFile, aliases = List("-Ypickle-write"), preferPrevious = true, deprecation = Some(Deprecation("Use -Xearly-tasty-output instead.", "-Xearly-tasty-output")))
493+
@deprecated(message = "Lifted to -X, Scheduled for removal in 3.6.0", since = "3.5.0")
480494
val YallowOutlineFromTasty: Setting[Boolean] = BooleanSetting(ForkSetting, "Yallow-outline-from-tasty", "Allow outline TASTy to be loaded with the -from-tasty option.", deprecation = Some(Deprecation("Use -Xallow-outline-from-tasty instead.", "-Xallow-outline-from-tasty")))
481495

482496
// Deprecated: lifted from -Y to -W
497+
@deprecated(message = "Lifted to -W, Scheduled for removal in 3.6.0", since = "3.5.0")
483498
val YcheckInit: Setting[Boolean] = BooleanSetting(ForkSetting, "Ysafe-init", "Ensure safe initialization of objects.", deprecation = Some(Deprecation("Use -Wsafe-init instead.", "-Wsafe-init")))
484499
end YSettings

compiler/src/dotty/tools/dotc/config/Settings.scala

Lines changed: 41 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -53,17 +53,16 @@ object Settings:
5353
sstate: SettingsState,
5454
arguments: List[String],
5555
errors: List[String],
56-
warnings: List[String]) {
56+
warnings: List[String]):
5757

5858
def fail(msg: String): Settings.ArgsSummary =
5959
ArgsSummary(sstate, arguments.tail, errors :+ msg, warnings)
6060

6161
def warn(msg: String): Settings.ArgsSummary =
6262
ArgsSummary(sstate, arguments.tail, errors, warnings :+ msg)
6363

64-
def deprecated(msg: String, extraArgs: List[String]): Settings.ArgsSummary =
65-
ArgsSummary(sstate, extraArgs ++ arguments.tail, errors, warnings :+ msg)
66-
}
64+
def deprecated(extraArg: String, msg: String): Settings.ArgsSummary =
65+
ArgsSummary(sstate, extraArg +: arguments.tail, errors, warnings :+ msg)
6766

6867
@unshared
6968
val settingCharacters = "[a-zA-Z0-9_\\-]*".r
@@ -86,8 +85,7 @@ object Settings:
8685
propertyClass: Option[Class[?]] = None,
8786
deprecation: Option[Deprecation] = None,
8887
// kept only for -Xkind-projector option compatibility
89-
legacyArgs: Boolean = false)(private[Settings] val idx: Int
90-
):
88+
legacyArgs: Boolean = false)(private[Settings] val idx: Int):
9189

9290
validateSettingString(prefix.getOrElse(name))
9391
aliases.foreach(validateSettingString)
@@ -120,28 +118,36 @@ object Settings:
120118

121119
def tryToSet(state: ArgsSummary): ArgsSummary =
122120
val ArgsSummary(sstate, arg :: args, errors, warnings) = state: @unchecked
121+
123122
def update(value: Any, args: List[String]): ArgsSummary =
124-
var dangers = warnings
125-
val valueNew =
126-
if sstate.wasChanged(idx) && isMultivalue then
127-
val valueList = value.asInstanceOf[List[String]]
128-
val current = valueIn(sstate).asInstanceOf[List[String]]
129-
valueList.filter(current.contains).foreach(s => dangers :+= s"Setting $name set to $s redundantly")
130-
current ++ valueList
131-
else
132-
if sstate.wasChanged(idx) then
133-
assert(!preferPrevious, "should have shortcutted with ignoreValue, side-effect may be present!")
134-
dangers :+= s"Flag $name set repeatedly"
135-
value
136-
ArgsSummary(updateIn(sstate, valueNew), args, errors, dangers)
123+
deprecation match
124+
case Some(Deprecation(msg, replacedBy)) =>
125+
val deprecatedMsg = s"Option $name is deprecated: $msg"
126+
if argValRest.isBlank() then state.deprecated(replacedBy, deprecatedMsg)
127+
else state.deprecated(s"$replacedBy:$argValRest", deprecatedMsg)
128+
129+
case None =>
130+
var dangers = warnings
131+
val valueNew =
132+
if sstate.wasChanged(idx) && isMultivalue then
133+
val valueList = value.asInstanceOf[List[String]]
134+
val current = valueIn(sstate).asInstanceOf[List[String]]
135+
valueList.filter(current.contains).foreach(s => dangers :+= s"Setting $name set to $s redundantly")
136+
current ++ valueList
137+
else
138+
if sstate.wasChanged(idx) then
139+
assert(!preferPrevious, "should have shortcutted with ignoreValue, side-effect may be present!")
140+
dangers :+= s"Flag $name set repeatedly"
141+
value
142+
ArgsSummary(updateIn(sstate, valueNew), args, errors, dangers)
137143
end update
138144

139145
def ignoreValue(args: List[String]): ArgsSummary =
140146
ArgsSummary(sstate, args, errors, warnings)
141147

142148
def missingArg =
143149
val msg = s"missing argument for option $name"
144-
if ignoreInvalidArgs then state.warn(msg + ", the tag was ignored") else state.fail(msg)
150+
if ignoreInvalidArgs then state.warn(msg + ", the tag was ignored") else state.fail(msg)
145151

146152
def invalidChoices(invalid: List[String]) =
147153
val msg = s"invalid choice(s) for $name: ${invalid.mkString(",")}"
@@ -160,33 +166,30 @@ object Settings:
160166
update(argValue, args)
161167

162168
def setInt(argValue: String, args: List[String]) =
163-
try
164-
val x = argValue.toInt
169+
argValue.toIntOption.map: intValue =>
165170
choices match
166-
case Some(r: Range) if x < r.head || r.last < x =>
171+
case Some(r: Range) if intValue < r.head || r.last < intValue =>
167172
state.fail(s"$argValue is out of legal range ${r.head}..${r.last} for $name")
168-
case Some(xs) if !xs.contains(x) =>
173+
case Some(xs) if !xs.contains(intValue) =>
169174
state.fail(s"$argValue is not a valid choice for $name")
170175
case _ =>
171-
update(x, args)
172-
catch case _: NumberFormatException =>
176+
update(intValue, args)
177+
.getOrElse:
173178
state.fail(s"$argValue is not an integer argument for $name")
174179

175180
def setOutput(argValue: String, args: List[String]) =
176181
val path = Directory(argValue)
177182
val isJar = path.ext.isJar
178-
if (!isJar && !path.isDirectory)
183+
if (!isJar && !path.isDirectory) then
179184
state.fail(s"'$argValue' does not exist or is not a directory or .jar file")
180-
else {
185+
else
181186
val output = if (isJar) JarArchive.create(path) else new PlainDirectory(path)
182187
update(output, args)
183-
}
184188

185189
def setVersion(argValue: String, args: List[String]) =
186-
ScalaVersion.parse(argValue) match {
190+
ScalaVersion.parse(argValue) match
187191
case Success(v) => update(v, args)
188192
case Failure(ex) => state.fail(ex.getMessage)
189-
}
190193

191194
def appendList(strings: List[String], args: List[String]) =
192195
choices match
@@ -195,9 +198,8 @@ object Settings:
195198
case invalid => invalidChoices(invalid)
196199
case _ => update(strings, args)
197200

198-
199201
def doSet(argRest: String) =
200-
((summon[ClassTag[T]], args): @unchecked) match {
202+
((summon[ClassTag[T]], args): @unchecked) match
201203
case (BooleanTag, _) =>
202204
if sstate.wasChanged(idx) && preferPrevious then ignoreValue(args)
203205
else setBoolean(argRest, args)
@@ -211,7 +213,6 @@ object Settings:
211213
else if argAfterParam then
212214
doSetArg(args.head, args.tail)
213215
else missingArg
214-
}
215216

216217
def doSetArg(arg: String, argsLeft: List[String]) = summon[ClassTag[T]] match
217218
case ListTag =>
@@ -237,17 +238,9 @@ object Settings:
237238
def argValRest: String =
238239
if(prefix.isEmpty) arg.dropWhile(_ != ':').drop(1) else arg.drop(prefix.get.length)
239240

240-
if matches(arg) then
241-
deprecation match
242-
case Some(Deprecation(msg, replacedBy, mapArguments)) =>
243-
val (adjustedOption, state1) = mapArguments(argValRest, state)
244-
val substitutedArg = if adjustedOption.nonEmpty then
245-
s"$replacedBy:$adjustedOption"
246-
else replacedBy
247-
state1.deprecated(s"Option $name is deprecated: $msg", List(substitutedArg))
248-
case None => doSet(argValRest)
249-
else
250-
state
241+
if matches(arg) then doSet(argValRest)
242+
else state
243+
251244
end tryToSet
252245
end Setting
253246

@@ -258,14 +251,10 @@ object Settings:
258251
*
259252
* @param msg deprecation message that will be displayed in following format: s"Option $name is deprecated: $msg"
260253
* @param replacedBy option that is substituting current option
261-
* @param updateChoices a function used to map available options to different ones with access to the state.
262-
* It allows to append additional warnings or failing the compilation depending on the case e.g.
263-
* when there is no option that can be replace deprecated one.
264254
*/
265255
case class Deprecation(
266256
msg: String,
267257
replacedBy: String,
268-
updateChoices: (String, ArgsSummary) => (String, ArgsSummary) = (option, state) => (option, state)
269258
)
270259

271260
object Setting:
@@ -287,7 +276,7 @@ object Settings:
287276
s"\n- $name${if description.isEmpty() then "" else s" :\n\t${description.replace("\n","\n\t")}"}"
288277
end Setting
289278

290-
class SettingGroup {
279+
class SettingGroup:
291280

292281
@unshared
293282
private val _allSettings = new ArrayBuffer[Setting[?]]
@@ -305,11 +294,10 @@ object Settings:
305294
userSetSettings(state.sstate).foldLeft(state)(checkDependenciesOfSetting)
306295

307296
private def checkDependenciesOfSetting(state: ArgsSummary, setting: Setting[?]) =
308-
setting.depends.foldLeft(state) { (s, dep) =>
297+
setting.depends.foldLeft(state): (s, dep) =>
309298
val (depSetting, reqValue) = dep
310299
if (depSetting.valueIn(state.sstate) == reqValue) s
311300
else s.fail(s"incomplete option ${setting.name} (requires ${depSetting.name})")
312-
}
313301

314302
/** Iterates over the arguments applying them to settings where applicable.
315303
* Then verifies setting dependencies are met.
@@ -375,9 +363,6 @@ object Settings:
375363
def MultiChoiceHelpSetting(category: SettingCategory, name: String, helpArg: String, descr: String, choices: List[ChoiceWithHelp[String]], default: List[ChoiceWithHelp[String]], aliases: List[String] = Nil, deprecation: Option[Deprecation] = None): Setting[List[ChoiceWithHelp[String]]] =
376364
publish(Setting(category, prependName(name), descr, default, helpArg, Some(choices), aliases = aliases, deprecation = deprecation))
377365

378-
def UncompleteMultiChoiceHelpSetting(category: SettingCategory, name: String, helpArg: String, descr: String, choices: List[ChoiceWithHelp[String]], default: List[ChoiceWithHelp[String]], aliases: List[String] = Nil, deprecation: Option[Deprecation] = None): Setting[List[ChoiceWithHelp[String]]] =
379-
publish(Setting(category, prependName(name), descr, default, helpArg, Some(choices), aliases = aliases, deprecation = deprecation, ignoreInvalidArgs = true))
380-
381366
def IntSetting(category: SettingCategory, name: String, descr: String, default: Int, aliases: List[String] = Nil, deprecation: Option[Deprecation] = None): Setting[Int] =
382367
publish(Setting(category, prependName(name), descr, default, aliases = aliases, deprecation = deprecation))
383368

@@ -406,5 +391,5 @@ object Settings:
406391
def OptionSetting[T: ClassTag](category: SettingCategory, name: String, descr: String, aliases: List[String] = Nil, deprecation: Option[Deprecation] = None): Setting[Option[T]] =
407392
publish(Setting(category, prependName(name), descr, None, propertyClass = Some(summon[ClassTag[T]].runtimeClass), aliases = aliases, deprecation = deprecation))
408393

409-
}
394+
end SettingGroup
410395
end Settings

compiler/src/dotty/tools/dotc/transform/Pickler.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ object Pickler {
131131
* that API and Dependency phases are complete.
132132
*/
133133
def init(using Context, ExecutionContext): AsyncTastyHolder =
134-
AsyncTastyHolder(ctx.settings.YearlyTastyOutput.value, ctx.incCallback)
134+
AsyncTastyHolder(ctx.settings.XearlyTastyOutput.value, ctx.incCallback)
135135

136136

137137
/** Asynchronously writes TASTy files to the destination -Yearly-tasty-output.

compiler/src/dotty/tools/io/FileWriters.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ object FileWriters {
150150

151151
object ReadOnlyContext:
152152
def readSettings(using ctx: Context): ReadOnlySettings = new:
153-
val jarCompressionLevel = ctx.settings.YjarCompressionLevel.value
153+
val jarCompressionLevel = ctx.settings.XjarCompressionLevel.value
154154
val debug = ctx.settings.Ydebug.value
155155

156156
def readRun(using ctx: Context): ReadOnlyRun = new:

0 commit comments

Comments
 (0)