Skip to content

Commit

Permalink
Deprecation warnings for old syntax: var x = _
Browse files Browse the repository at this point in the history
* In `3.4` we emit the deprecation warning
* In `future` we emit we make this syntax an error
* Add patch. Not ideal because we need to use the full path of `uninitialized`
  • Loading branch information
nicolasstucki committed Nov 7, 2023
1 parent f61026d commit 5c35b48
Show file tree
Hide file tree
Showing 18 changed files with 68 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ object projects:
project = "shapeless-3",
sbtTestCommand = "testJVM; testJS",
sbtDocCommand = forceDoc("typeable", "deriving"),
scalacOptions = SbtCommunityProject.scalacOptions.filter(_ != "-Ysafe-init"), // due to -Xfatal-warnings
scalacOptions = "-source" :: "3.3" :: SbtCommunityProject.scalacOptions.filter(_ != "-Ysafe-init"), // due to -Xfatal-warnings
)

lazy val xmlInterpolator = SbtCommunityProject(
Expand Down
13 changes: 8 additions & 5 deletions compiler/src/dotty/tools/dotc/parsing/Parsers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3655,11 +3655,14 @@ object Parsers {
subExpr() match
case rhs0 @ Ident(name) if placeholderParams.nonEmpty && name == placeholderParams.head.name
&& !tpt.isEmpty && mods.is(Mutable) && lhs.forall(_.isInstanceOf[Ident]) =>
if sourceVersion.isAtLeast(future) then
deprecationWarning(
em"""`= _` has been deprecated; use `= uninitialized` instead.
|`uninitialized` can be imported with `scala.compiletime.uninitialized`.""",
rhsOffset)
report.gradualErrorOrMigrationWarning(
em"""`= _` has been deprecated; use `= uninitialized` instead.
|`uninitialized` can be imported with `scala.compiletime.uninitialized`.${rewriteNotice(`3.4-migration`)}""",
in.sourcePos(rhsOffset),
warnFrom = `3.4`,
errorFrom = future)
if sourceVersion.isMigrating && sourceVersion.isAtLeast(`3.4-migration`) then
patch(source, Span(rhsOffset, rhsOffset + 1), "scala.compiletime.uninitialized")
placeholderParams = placeholderParams.tail
atSpan(rhs0.span) { Ident(nme.WILDCARD) }
case rhs0 => rhs0
Expand Down
1 change: 1 addition & 0 deletions compiler/test/dotty/tools/dotc/CompilationTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ class CompilationTests {
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/uninitialized-var.scala", defaultOptions.and("-rewrite", "-source", "future-migration")),
compileFile("tests/rewrites/with-type-operator.scala", defaultOptions.and("-rewrite", "-source", "future-migration")),
compileFile("tests/rewrites/filtering-fors.scala", defaultOptions.and("-rewrite", "-source", "3.2-migration")),
compileFile("tests/rewrites/refutable-pattern-bindings.scala", defaultOptions.and("-rewrite", "-source", "3.2-migration")),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import scala.collection._
import scala.jdk.CollectionConverters._
import scala.util.control.NonFatal
import scala.io.Codec
import scala.compiletime.uninitialized

import dotc._
import ast.{Trees, tpd, untpd}
Expand Down Expand Up @@ -54,14 +55,14 @@ class DottyLanguageServer extends LanguageServer
import lsp4j.jsonrpc.messages.{Either => JEither}
import lsp4j._

private[this] var rootUri: String = _
private[this] var rootUri: String = uninitialized

private[this] var myClient: DottyClient = _
private[this] var myClient: DottyClient = uninitialized
def client: DottyClient = myClient

private[this] var myDrivers: mutable.Map[ProjectConfig, InteractiveDriver] = _
private[this] var myDrivers: mutable.Map[ProjectConfig, InteractiveDriver] = uninitialized

private[this] var myDependentProjects: mutable.Map[ProjectConfig, mutable.Set[ProjectConfig]] = _
private[this] var myDependentProjects: mutable.Map[ProjectConfig, mutable.Set[ProjectConfig]] = uninitialized

def drivers: Map[ProjectConfig, InteractiveDriver] = thisServer.synchronized {
if myDrivers == null then
Expand Down
4 changes: 3 additions & 1 deletion library/src/scala/util/control/NonLocalReturns.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package scala.util.control

import scala.compiletime.uninitialized

/** Library implementation of nonlocal return.
*
* Usage:
Expand All @@ -21,7 +23,7 @@ package scala.util.control
object NonLocalReturns {
@deprecated("Use scala.util.boundary.Break instead", "3.3")
class ReturnThrowable[T] extends ControlThrowable {
private var myResult: T = _
private var myResult: T = uninitialized
def throwReturn(result: T): Nothing = {
myResult = result
throw this
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import dotty.tools.dotc.interactive.InteractiveDriver
import dotty.tools.dotc.reporting.Diagnostic
import dotty.tools.dotc.util.SourceFile

import scala.compiletime.uninitialized

/**
* MetalsDriver is a wrapper class that provides a compilation cache for InteractiveDriver.
* MetalsDriver skips running compilation if
Expand All @@ -29,7 +31,7 @@ class MetalsDriver(
override val settings: List[String]
) extends InteractiveDriver(settings):

@volatile private var lastCompiledURI: URI = _
@volatile private var lastCompiledURI: URI = uninitialized

private def alreadyCompiled(uri: URI, content: Array[Char]): Boolean =
compilationUnits.get(uri) match
Expand Down
4 changes: 3 additions & 1 deletion project/Build.scala
Original file line number Diff line number Diff line change
Expand Up @@ -578,7 +578,8 @@ object Build {
lazy val commonDottyCompilerSettings = Seq(
// Note: bench/profiles/projects.yml should be updated accordingly.
Compile / scalacOptions ++= Seq("-Yexplicit-nulls", "-Ysafe-init"),

// Use source 3.3 to avoid fatal migration warnings on scalajs-ir
scalacOptions ++= Seq("-source", "3.3"),
// Generate compiler.properties, used by sbt
(Compile / resourceGenerators) += Def.task {
import java.util._
Expand Down Expand Up @@ -1254,6 +1255,7 @@ object Build {
val mtagsVersion = "1.0.0"

Seq(
scalacOptions ++= Seq("-source", "3.3"), // To avoid fatal migration warnings
libraryDependencies ++= Seq(
"org.lz4" % "lz4-java" % "1.8.0",
"io.get-coursier" % "interface" % "1.0.18",
Expand Down
3 changes: 0 additions & 3 deletions sbt-test/compilerReporter/i14576/Test.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,5 @@ object Test:
def f(x: Text) = println(x.str)
f("abc")

// private[this] and = _ are deprecated under -source:future
private[this] var x: AnyRef = _

// under -source:future, `_` is deprecated for wildcard arguments of types: use `?` instead
val xs: List[_] = Nil
2 changes: 1 addition & 1 deletion sbt-test/compilerReporter/i14576/build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ lazy val root = (project in file("."))
},
assertDeprecationSummary := {
assert {
FakePrintWriter.messages.exists(_.contains("there were 3 deprecation warnings; re-run with -deprecation for details"))
FakePrintWriter.messages.exists(_.contains("there was 1 deprecation warning; re-run with -deprecation for details"))
}
},
assertNoDeprecationSummary := {
Expand Down
6 changes: 3 additions & 3 deletions tests/neg/i4812.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//> using options -Werror
object Test:
var prev: Any = _
var prev: Any = scala.compiletime.uninitialized

def test[T](x: T): T =
class A(val elem: (T, Boolean))
Expand Down Expand Up @@ -55,7 +55,7 @@ object Test:

def test6[T](x: T): T =
class A { var b: B = null }
class B { var a: A = null; var elem: T = _ }
class B { var a: A = null; var elem: T = scala.compiletime.uninitialized }
prev match
case prev: A => // error: the type test for A cannot be checked at runtime
prev.b.elem
Expand Down Expand Up @@ -88,7 +88,7 @@ object Test:
case x: B => x

sealed class A
var prevA: A = _
var prevA: A = scala.compiletime.uninitialized
def test10: A =
val methodCallId = System.nanoTime()
class B(val id: Long) extends A
Expand Down
6 changes: 6 additions & 0 deletions tests/neg/uninitialized-3.4.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
-- Error: tests/neg/uninitialized-3.4.scala:7:15 -----------------------------------------------------------------------
7 | var a: Int = _ // error: migration warning
| ^
| `= _` has been deprecated; use `= uninitialized` instead.
| `uninitialized` can be imported with `scala.compiletime.uninitialized`.
| This construct can be rewritten automatically under -rewrite -source 3.4-migration.
8 changes: 8 additions & 0 deletions tests/neg/uninitialized-3.4.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
//> using options -Werror

import scala.language.`3.4`
import scala.compiletime.uninitialized

class Foo:
var a: Int = _ // error: migration warning
var b: Int = uninitialized
8 changes: 8 additions & 0 deletions tests/neg/uninitialized-future-migration.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
//> using options -Werror

import scala.language.`future-migration`
import scala.compiletime.uninitialized

class Foo:
var a: Int = _ // error: migration warning
var b: Int = uninitialized
6 changes: 6 additions & 0 deletions tests/neg/uninitialized-future.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import scala.language.future
import scala.compiletime.uninitialized

class Foo:
var a: Int = _ // error
var b: Int = uninitialized
3 changes: 2 additions & 1 deletion tests/patmat/i12805-fallout.scala
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import scala.annotation.unchecked.uncheckedVariance
import scala.compiletime.uninitialized

type Untyped = Null

Expand All @@ -7,7 +8,7 @@ class Type
abstract class Tree[-T >: Untyped] {
type ThisTree[T >: Untyped] <: Tree[T]

protected var myTpe: T @uncheckedVariance = _
protected var myTpe: T @uncheckedVariance = uninitialized

def withType(tpe: Type): ThisTree[Type] = {
val tree = this.asInstanceOf[ThisTree[Type]]
Expand Down
6 changes: 6 additions & 0 deletions tests/pos/uninitialized-future-migration.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import scala.language.`future-migration`
import scala.compiletime.uninitialized

class Foo:
var a: Int = _ // warn
var b: Int = uninitialized
2 changes: 2 additions & 0 deletions tests/rewrites/uninitialized-var.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
class Foo:
var a: Int = scala.compiletime.uninitialized
2 changes: 2 additions & 0 deletions tests/rewrites/uninitialized-var.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
class Foo:
var a: Int = _

0 comments on commit 5c35b48

Please sign in to comment.