Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/Compiler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
10 changes: 6 additions & 4 deletions compiler/src/dotty/tools/dotc/config/ScalaSettings.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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.")
Expand All @@ -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 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",
Expand Down Expand Up @@ -299,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 =
Expand All @@ -311,7 +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 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:
Expand Down Expand Up @@ -453,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.")
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/core/Symbols.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions compiler/src/dotty/tools/dotc/reporting/ConsoleReporter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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 _ =>
}
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/reporting/Reporter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
6 changes: 3 additions & 3 deletions compiler/src/dotty/tools/dotc/transform/init/Checker.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
}
Expand Down
10 changes: 10 additions & 0 deletions compiler/src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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.wrongArrow =>
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` */
Expand Down
22 changes: 11 additions & 11 deletions compiler/test/dotty/tools/dotc/CompilationTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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")),
Expand Down Expand Up @@ -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"),
Expand Down Expand Up @@ -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:
Expand All @@ -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"

Expand All @@ -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"
Expand All @@ -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"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
22 changes: 22 additions & 0 deletions tests/warn/i21187.scala
Original file line number Diff line number Diff line change
@@ -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"))
Loading