From f1d5ced6371ae310d5cbcce39ac85ca526bd22f3 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Sat, 30 Aug 2025 01:10:24 -0700 Subject: [PATCH 1/2] Lint function arrow intended context function --- .../tools/dotc/config/ScalaSettings.scala | 2 ++ .../src/dotty/tools/dotc/typer/Typer.scala | 10 +++++++++ tests/warn/i21187.scala | 22 +++++++++++++++++++ 3 files changed, 34 insertions(+) create mode 100644 tests/warn/i21187.scala diff --git a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala index a2c557ea2987..ec0ec3bf12f6 100644 --- a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -168,6 +168,7 @@ private sealed trait WarningSettings: private val WunstableInlineAccessors = BooleanSetting(WarningSetting, "WunstableInlineAccessors", "Warn an inline methods has references to non-stable binary APIs.") private val WtoStringInterpolated = BooleanSetting(WarningSetting, "Wtostring-interpolated", "Warn a standard interpolator used toString on a reference type.") private val WrecurseWithDefault = BooleanSetting(WarningSetting, "Wrecurse-with-default", "Warn when a method calls itself with a default argument.") + private val WdubiousContextual = BooleanSetting(WarningSetting, "Wwrong-arrow", "Warn if function arrow was used instead of context literal ?=>.") private val Wunused: Setting[List[ChoiceWithHelp[String]]] = MultiChoiceHelpSetting( WarningSetting, name = "Wunused", @@ -311,6 +312,7 @@ private sealed trait WarningSettings: def unstableInlineAccessors(using Context): Boolean = allOr(WunstableInlineAccessors) def toStringInterpolated(using Context): Boolean = allOr(WtoStringInterpolated) def recurseWithDefault(using Context): Boolean = allOr(WrecurseWithDefault) + def dubiousContextual(using Context): Boolean = allOr(WdubiousContextual) def checkInit(using Context): Boolean = allOr(WcheckInit) /** -X "Extended" or "Advanced" settings */ diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index def6fac0556e..c17a539ca4fa 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -3824,6 +3824,16 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer val ifun = desugar.makeContextualFunction(paramTypes, paramNamesOrNil, tree, erasedParams) typr.println(i"make contextual function $tree / $pt ---> $ifun") typedFunctionValue(ifun, pt) + .tap: + case tree @ Block((m1: DefDef) :: _, _: Closure) if ctx.settings.Whas.dubiousContextual => + m1.rhs match + case Block((m2: DefDef) :: _, _: Closure) if m1.paramss.lengthCompare(m2.paramss) == 0 => + val p1s = m1.symbol.info.asInstanceOf[MethodType].paramInfos + val p2s = m2.symbol.info.asInstanceOf[MethodType].paramInfos + if p1s.corresponds(p2s)(_ =:= _) then + report.warning(em"Context function adapts a lambda with the same parameter types, possibly ?=> was intended.", tree.srcPos) + case _ => + case _ => } /** Typecheck and adapt tree, returning a typed tree. Parameters as for `typedUnadapted` */ diff --git a/tests/warn/i21187.scala b/tests/warn/i21187.scala new file mode 100644 index 000000000000..d6ea131afdfb --- /dev/null +++ b/tests/warn/i21187.scala @@ -0,0 +1,22 @@ +//> using options -Wall + +def oops(msg: String) = sys.error(msg) + +class Zone +object Zone: + inline def apply[T](inline f: Zone ?=> T): T = f(using new Zone) + +inline def zone[A](inline f: Zone ?=> A) = Zone.apply(z => f(using z)) // warn suspicious contextualizing + +def zone_?[A](f: Zone ?=> A) = Zone.apply(z => f(using z)) // warn + +// intended +//inline def zone[A](inline f: Zone ?=> A): A = Zone.apply(z ?=> f(using z)) + +@main def hello = + // this swallows exceptions! + zone(oops("here")) // warn function value is not used + zone_?(oops("here")) // warn + + // this doesn't + Zone(oops("not here")) From a83aa217aba9e8476e637faa8c0204706af1de24 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Wed, 3 Sep 2025 08:17:20 -0700 Subject: [PATCH 2/2] Internal symbols must align with user-facing strings --- compiler/src/dotty/tools/dotc/Compiler.scala | 2 +- .../tools/dotc/config/ScalaSettings.scala | 12 +++++----- .../src/dotty/tools/dotc/core/Symbols.scala | 4 ++-- .../dotc/reporting/ConsoleReporter.scala | 6 ++--- .../dotty/tools/dotc/reporting/Reporter.scala | 2 +- .../tools/dotc/transform/init/Checker.scala | 6 ++--- .../src/dotty/tools/dotc/typer/Typer.scala | 2 +- .../dotty/tools/dotc/CompilationTests.scala | 22 +++++++++---------- .../dotc/config/ScalaSettingsTests.scala | 6 ++--- 9 files changed, 31 insertions(+), 31 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/Compiler.scala b/compiler/src/dotty/tools/dotc/Compiler.scala index f82f7956b34b..66044dd9462d 100644 --- a/compiler/src/dotty/tools/dotc/Compiler.scala +++ b/compiler/src/dotty/tools/dotc/Compiler.scala @@ -171,7 +171,7 @@ class Compiler { val rctx = if ctx.settings.Xsemanticdb.value then ctx.addMode(Mode.ReadPositions) - else if ctx.settings.YcheckInitGlobal.value then + else if ctx.settings.YsafeInitGlobal.value then ctx.addMode(Mode.ReadPositions) else ctx diff --git a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala index ec0ec3bf12f6..2d048befe171 100644 --- a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -159,7 +159,7 @@ private sealed trait WarningSettings: self: SettingGroup => val Whelp: Setting[Boolean] = BooleanSetting(WarningSetting, "W", "Print a synopsis of warning options.") - val XfatalWarnings: Setting[Boolean] = BooleanSetting(WarningSetting, "Werror", "Fail the compilation if there are any warnings.", aliases = List("-Xfatal-warnings")) + val Werror: Setting[Boolean] = BooleanSetting(WarningSetting, "Werror", "Fail the compilation if there are any warnings.", aliases = List("-Xfatal-warnings")) val Wall: Setting[Boolean] = BooleanSetting(WarningSetting, "Wall", "Enable all warning settings.") private val WvalueDiscard: Setting[Boolean] = BooleanSetting(WarningSetting, "Wvalue-discard", "Warn when non-Unit expression results are unused.") private val WNonUnitStatement = BooleanSetting(WarningSetting, "Wnonunit-statement", "Warn when block statements are non-Unit expressions.") @@ -168,7 +168,7 @@ private sealed trait WarningSettings: private val WunstableInlineAccessors = BooleanSetting(WarningSetting, "WunstableInlineAccessors", "Warn an inline methods has references to non-stable binary APIs.") private val WtoStringInterpolated = BooleanSetting(WarningSetting, "Wtostring-interpolated", "Warn a standard interpolator used toString on a reference type.") private val WrecurseWithDefault = BooleanSetting(WarningSetting, "Wrecurse-with-default", "Warn when a method calls itself with a default argument.") - private val WdubiousContextual = BooleanSetting(WarningSetting, "Wwrong-arrow", "Warn if function arrow was used instead of context literal ?=>.") + private val WwrongArrow = BooleanSetting(WarningSetting, "Wwrong-arrow", "Warn if function arrow was used instead of context literal ?=>.") private val Wunused: Setting[List[ChoiceWithHelp[String]]] = MultiChoiceHelpSetting( WarningSetting, name = "Wunused", @@ -300,7 +300,7 @@ private sealed trait WarningSettings: def typeParameterShadow(using Context) = allOr("type-parameter-shadow") - val WcheckInit: Setting[Boolean] = BooleanSetting(WarningSetting, "Wsafe-init", "Ensure safe initialization of objects.") + val WsafeInit: Setting[Boolean] = BooleanSetting(WarningSetting, "Wsafe-init", "Ensure safe initialization of objects.") object Whas: def allOr(s: Setting[Boolean])(using Context): Boolean = @@ -312,8 +312,8 @@ private sealed trait WarningSettings: def unstableInlineAccessors(using Context): Boolean = allOr(WunstableInlineAccessors) def toStringInterpolated(using Context): Boolean = allOr(WtoStringInterpolated) def recurseWithDefault(using Context): Boolean = allOr(WrecurseWithDefault) - def dubiousContextual(using Context): Boolean = allOr(WdubiousContextual) - def checkInit(using Context): Boolean = allOr(WcheckInit) + def wrongArrow(using Context): Boolean = allOr(WwrongArrow) + def safeInit(using Context): Boolean = allOr(WsafeInit) /** -X "Extended" or "Advanced" settings */ private sealed trait XSettings: @@ -455,7 +455,7 @@ private sealed trait YSettings: val YnoKindPolymorphism: Setting[Boolean] = BooleanSetting(ForkSetting, "Yno-kind-polymorphism", "Disable kind polymorphism. (This flag has no effect)", deprecation = Deprecation.removed()) val YexplicitNulls: Setting[Boolean] = BooleanSetting(ForkSetting, "Yexplicit-nulls", "Make reference types non-nullable. Nullable types can be expressed with unions: e.g. String|Null.") val YnoFlexibleTypes: Setting[Boolean] = BooleanSetting(ForkSetting, "Yno-flexible-types", "Disable turning nullable Java return types and parameter types into flexible types, which behave like abstract types with a nullable lower bound and non-nullable upper bound.") - val YcheckInitGlobal: Setting[Boolean] = BooleanSetting(ForkSetting, "Ysafe-init-global", "Check safe initialization of global objects.") + val YsafeInitGlobal: Setting[Boolean] = BooleanSetting(ForkSetting, "Ysafe-init-global", "Check safe initialization of global objects.") val YrequireTargetName: Setting[Boolean] = BooleanSetting(ForkSetting, "Yrequire-targetName", "Warn if an operator is defined without a @targetName annotation.") val YrecheckTest: Setting[Boolean] = BooleanSetting(ForkSetting, "Yrecheck-test", "Run basic rechecking (internal test only).") val YccDebug: Setting[Boolean] = BooleanSetting(ForkSetting, "Ycc-debug", "Used in conjunction with captureChecking language import, debug info for captured references.") diff --git a/compiler/src/dotty/tools/dotc/core/Symbols.scala b/compiler/src/dotty/tools/dotc/core/Symbols.scala index c8ede8bfdec2..d86c50cbe2e3 100644 --- a/compiler/src/dotty/tools/dotc/core/Symbols.scala +++ b/compiler/src/dotty/tools/dotc/core/Symbols.scala @@ -84,8 +84,8 @@ object Symbols extends SymUtils { ctx.settings.YretainTrees.value || denot.owner.isTerm || // no risk of leaking memory after a run for these denot.isOneOf(InlineOrProxy) || // need to keep inline info - ctx.settings.Whas.checkInit || // initialization check - ctx.settings.YcheckInitGlobal.value + ctx.settings.Whas.safeInit || // initialization check + ctx.settings.YsafeInitGlobal.value /** The last denotation of this symbol */ private var lastDenot: SymDenotation = uninitialized diff --git a/compiler/src/dotty/tools/dotc/reporting/ConsoleReporter.scala b/compiler/src/dotty/tools/dotc/reporting/ConsoleReporter.scala index 3dc73983056a..3604b5b6ebf9 100644 --- a/compiler/src/dotty/tools/dotc/reporting/ConsoleReporter.scala +++ b/compiler/src/dotty/tools/dotc/reporting/ConsoleReporter.scala @@ -23,9 +23,9 @@ class ConsoleReporter( super.doReport(dia) if ctx.settings.Xprompt.value then dia match - case _: Error => Reporter.displayPrompt(reader, writer) - case _: Warning if ctx.settings.XfatalWarnings.value => Reporter.displayPrompt(reader, writer) - case _ => + case _: Error => Reporter.displayPrompt(reader, writer) + case _: Warning => if ctx.settings.Werror.value then Reporter.displayPrompt(reader, writer) + case _ => } } diff --git a/compiler/src/dotty/tools/dotc/reporting/Reporter.scala b/compiler/src/dotty/tools/dotc/reporting/Reporter.scala index aadac68b37e1..af92d0e0efdf 100644 --- a/compiler/src/dotty/tools/dotc/reporting/Reporter.scala +++ b/compiler/src/dotty/tools/dotc/reporting/Reporter.scala @@ -224,7 +224,7 @@ abstract class Reporter extends interfaces.ReporterResult { incompleteHandler(dia, ctx) def finalizeReporting()(using Context) = - if (hasWarnings && ctx.settings.XfatalWarnings.value) + if (hasWarnings && ctx.settings.Werror.value) report(new Error("No warnings can be incurred under -Werror (or -Xfatal-warnings)", NoSourcePosition)) /** Summary of warnings and errors */ diff --git a/compiler/src/dotty/tools/dotc/transform/init/Checker.scala b/compiler/src/dotty/tools/dotc/transform/init/Checker.scala index 4d5c467cf4fe..d34f95bedef1 100644 --- a/compiler/src/dotty/tools/dotc/transform/init/Checker.scala +++ b/compiler/src/dotty/tools/dotc/transform/init/Checker.scala @@ -29,7 +29,7 @@ class Checker extends Phase: override val runsAfter = Set(Pickler.name) override def isEnabled(using Context): Boolean = - super.isEnabled && (ctx.settings.Whas.checkInit || ctx.settings.YcheckInitGlobal.value) + super.isEnabled && (ctx.settings.Whas.safeInit || ctx.settings.YsafeInitGlobal.value) def traverse(traverser: InitTreeTraverser)(using Context): Boolean = monitor(phaseName): val unit = ctx.compilationUnit @@ -50,10 +50,10 @@ class Checker extends Phase: cancellable { val classes = traverser.getClasses() - if ctx.settings.Whas.checkInit then + if ctx.settings.Whas.safeInit then Semantic.checkClasses(classes)(using checkCtx) - if ctx.settings.YcheckInitGlobal.value then + if ctx.settings.YsafeInitGlobal.value then val obj = new Objects obj.checkClasses(classes)(using checkCtx) } diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index c17a539ca4fa..2c7398af1e28 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -3825,7 +3825,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer typr.println(i"make contextual function $tree / $pt ---> $ifun") typedFunctionValue(ifun, pt) .tap: - case tree @ Block((m1: DefDef) :: _, _: Closure) if ctx.settings.Whas.dubiousContextual => + case tree @ Block((m1: DefDef) :: _, _: Closure) if ctx.settings.Whas.wrongArrow => m1.rhs match case Block((m2: DefDef) :: _, _: Closure) if m1.paramss.lengthCompare(m2.paramss) == 0 => val p1s = m1.symbol.info.asInstanceOf[MethodType].paramInfos diff --git a/compiler/test/dotty/tools/dotc/CompilationTests.scala b/compiler/test/dotty/tools/dotc/CompilationTests.scala index c54cc65d14aa..214a1e953ef0 100644 --- a/compiler/test/dotty/tools/dotc/CompilationTests.scala +++ b/compiler/test/dotty/tools/dotc/CompilationTests.scala @@ -62,7 +62,7 @@ class CompilationTests { aggregateTests( compileFile("tests/rewrites/rewrites.scala", defaultOptions.and("-source", "3.0-migration").and("-rewrite", "-indent")), compileFile("tests/rewrites/rewrites3x.scala", defaultOptions.and("-rewrite", "-source", "future-migration")), - compileFile("tests/rewrites/rewrites3x-fatal-warnings.scala", defaultOptions.and("-rewrite", "-source", "future-migration", "-Xfatal-warnings")), + compileFile("tests/rewrites/rewrites3x-fatal-warnings.scala", defaultOptions.and("-rewrite", "-source", "future-migration", "-Werror")), compileFile("tests/rewrites/i21394.scala", defaultOptions.and("-rewrite", "-source", "future-migration")), compileFile("tests/rewrites/uninitialized-var.scala", defaultOptions.and("-rewrite", "-source", "future-migration")), compileFile("tests/rewrites/with-type-operator.scala", defaultOptions.and("-rewrite", "-source", "future-migration")), @@ -151,7 +151,7 @@ class CompilationTests { compileFilesInDir("tests/neg-deep-subtype", allowDeepSubtypes), compileFilesInDir("tests/neg-custom-args/captures", defaultOptions.and("-language:experimental.captureChecking", "-language:experimental.separationChecking", "-source", "3.8")), compileFile("tests/neg-custom-args/sourcepath/outer/nested/Test1.scala", defaultOptions.and("-sourcepath", "tests/neg-custom-args/sourcepath")), - compileDir("tests/neg-custom-args/sourcepath2/hi", defaultOptions.and("-sourcepath", "tests/neg-custom-args/sourcepath2", "-Xfatal-warnings")), + compileDir("tests/neg-custom-args/sourcepath2/hi", defaultOptions.and("-sourcepath", "tests/neg-custom-args/sourcepath2", "-Werror")), compileList("duplicate source", List( "tests/neg-custom-args/toplevel-samesource/S.scala", "tests/neg-custom-args/toplevel-samesource/nested/S.scala"), @@ -247,21 +247,21 @@ class CompilationTests { @Test def checkInitGlobal: Unit = { implicit val testGroup: TestGroup = TestGroup("checkInitGlobal") compileFilesInDir("tests/init-global/warn", defaultOptions.and("-Ysafe-init-global"), FileFilter.exclude(TestSources.negInitGlobalScala2LibraryTastyExcludelisted)).checkWarnings() - compileFilesInDir("tests/init-global/pos", defaultOptions.and("-Ysafe-init-global", "-Xfatal-warnings"), FileFilter.exclude(TestSources.posInitGlobalScala2LibraryTastyExcludelisted)).checkCompile() + compileFilesInDir("tests/init-global/pos", defaultOptions.and("-Ysafe-init-global", "-Werror"), FileFilter.exclude(TestSources.posInitGlobalScala2LibraryTastyExcludelisted)).checkCompile() if Properties.usingScalaLibraryTasty && !Properties.usingScalaLibraryCCTasty then compileFilesInDir("tests/init-global/warn-tasty", defaultOptions.and("-Ysafe-init-global"), FileFilter.exclude(TestSources.negInitGlobalScala2LibraryTastyExcludelisted)).checkWarnings() - compileFilesInDir("tests/init-global/pos-tasty", defaultOptions.and("-Ysafe-init-global", "-Xfatal-warnings"), FileFilter.exclude(TestSources.posInitGlobalScala2LibraryTastyExcludelisted)).checkCompile() + compileFilesInDir("tests/init-global/pos-tasty", defaultOptions.and("-Ysafe-init-global", "-Werror"), FileFilter.exclude(TestSources.posInitGlobalScala2LibraryTastyExcludelisted)).checkCompile() end if } // initialization tests - @Test def checkInit: Unit = { - implicit val testGroup: TestGroup = TestGroup("checkInit") - val options = defaultOptions.and("-Wsafe-init", "-Xfatal-warnings") + @Test def safeInit: Unit = { + given TestGroup = TestGroup("safeInit") + val options = defaultOptions.and("-Wsafe-init", "-Werror") compileFilesInDir("tests/init/neg", options).checkExpectedErrors() compileFilesInDir("tests/init/warn", defaultOptions.and("-Wsafe-init")).checkWarnings() compileFilesInDir("tests/init/pos", options).checkCompile() - compileFilesInDir("tests/init/crash", options.without("-Xfatal-warnings")).checkCompile() + compileFilesInDir("tests/init/crash", options.without("-Werror")).checkCompile() // The regression test for i12128 has some atypical classpath requirements. // The test consists of three files: (a) Reflect_1 (b) Macro_2 (c) Test_3 // which must be compiled separately. In addition: @@ -270,7 +270,7 @@ class CompilationTests { // - the output from (a) _must not_ be on the classpath while compiling (c) locally { val i12128Group = TestGroup("checkInit/i12128") - val i12128Options = options.without("-Xfatal-warnings") + val i12128Options = options.without("-Werror") val outDir1 = defaultOutputDir + i12128Group + "/Reflect_1/i12128/Reflect_1" val outDir2 = defaultOutputDir + i12128Group + "/Macro_2/i12128/Macro_2" @@ -289,7 +289,7 @@ class CompilationTests { * an error when reading the files' TASTy trees. */ locally { val tastyErrorGroup = TestGroup("checkInit/tasty-error/val-or-defdef") - val tastyErrorOptions = options.without("-Xfatal-warnings") + val tastyErrorOptions = options.without("-Werror") val classA0 = defaultOutputDir + tastyErrorGroup + "/A/v0/A" val classA1 = defaultOutputDir + tastyErrorGroup + "/A/v1/A" @@ -312,7 +312,7 @@ class CompilationTests { * an error when reading the files' TASTy trees. This fact is demonstrated by the compilation of Main. */ locally { val tastyErrorGroup = TestGroup("checkInit/tasty-error/typedef") - val tastyErrorOptions = options.without("-Xfatal-warnings").without("-Ycheck:all") + val tastyErrorOptions = options.without("-Werror").without("-Ycheck:all") val classC = defaultOutputDir + tastyErrorGroup + "/C/typedef/C" val classA0 = defaultOutputDir + tastyErrorGroup + "/A/v0/A" diff --git a/compiler/test/dotty/tools/dotc/config/ScalaSettingsTests.scala b/compiler/test/dotty/tools/dotc/config/ScalaSettingsTests.scala index c74be4901137..c7b030f0805c 100644 --- a/compiler/test/dotty/tools/dotc/config/ScalaSettingsTests.scala +++ b/compiler/test/dotty/tools/dotc/config/ScalaSettingsTests.scala @@ -111,7 +111,7 @@ class ScalaSettingsTests: // createTestCase(settings.YjavaTasty , settings.XjavaTasty), // createTestCase(settings.YearlyTastyOutput , settings.XearlyTastyOutput, ":./"), // createTestCase(settings.YallowOutlineFromTasty, settings.XallowOutlineFromTasty), - createTestCase(settings.YcheckInit , settings.WcheckInit), + createTestCase(settings.YcheckInit , settings.WsafeInit), // createTestCase(settings.Xlint , settings.Wshadow, ":all"), // this setting is not going to be mapped to replacement. Read more in the commit message ).map: (deprecatedArgument, newSetting) => val args = List(deprecatedArgument) @@ -140,7 +140,7 @@ class ScalaSettingsTests: // createTestCase(settings.YjavaTasty , settings.XjavaTasty), // createTestCase(settings.YearlyTastyOutput , settings.XearlyTastyOutput), // createTestCase(settings.YallowOutlineFromTasty, settings.XallowOutlineFromTasty), - createTestCase(settings.YcheckInit , settings.WcheckInit), + createTestCase(settings.YcheckInit , settings.WsafeInit), createTestCase(settings.Xlint , settings.Wshadow), ).map: (deprecatedArgument, newSetting) => val args = List(deprecatedArgument) @@ -181,7 +181,7 @@ class ScalaSettingsTests: // createTestCase(settings.YjavaTasty , settings.XjavaTasty), // createTestCase(settings.YearlyTastyOutput , settings.XearlyTastyOutput, ":./"), // createTestCase(settings.YallowOutlineFromTasty, settings.XallowOutlineFromTasty), - createTestCase(settings.YcheckInit , settings.WcheckInit), + createTestCase(settings.YcheckInit , settings.WsafeInit), // createTestCase(settings.Xlint , settings.Wshadow, ":all"), // this setting is not going to be mapped to replacement. Read more in the commit message ).flatten.map: (deprecatedArgument, newSetting) => val args = List(deprecatedArgument)