Skip to content

Commit

Permalink
Deprecation warnings for old syntax: _ type wildcards
Browse files Browse the repository at this point in the history
* In `3.4` we emit the deprecation warning and enable the
  patch with `-rewrite`.
* In `future` we emit we make this syntax an error
  • Loading branch information
nicolasstucki committed Nov 13, 2023
1 parent 8cb4945 commit 168e47a
Show file tree
Hide file tree
Showing 62 changed files with 170 additions and 109 deletions.
12 changes: 9 additions & 3 deletions compiler/src/dotty/tools/dotc/parsing/Parsers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1870,9 +1870,15 @@ object Parsers {
val start = in.skipToken()
Ident(tpnme.USCOREkw).withSpan(Span(start, in.lastOffset, start))
else
if !inTypeMatchPattern && sourceVersion.isAtLeast(future) then
deprecationWarning(em"`_` is deprecated for wildcard arguments of types: use `?` instead")
patch(source, Span(in.offset, in.offset + 1), "?")
if !inTypeMatchPattern then
report.gradualErrorOrMigrationWarning(
em"`_` is deprecated for wildcard arguments of types: use `?` instead${rewriteNotice(`3.4-migration`)}",
in.sourcePos(),
warnFrom = `3.4`,
errorFrom = future)
if sourceVersion.isMigrating && sourceVersion.isAtLeast(`3.4-migration`) then
patch(source, Span(in.offset, in.offset + 1), "?")
end if
val start = in.skipToken()
typeBounds().withSpan(Span(start, in.lastOffset, start))
// Allow symbols -_ and +_ through for compatibility with code written using kind-projector in Scala 3 underscore mode.
Expand Down
2 changes: 1 addition & 1 deletion compiler/test-resources/repl/i13208.scala
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
//> using options -source:future -deprecation
//> using options -source:3.4-migration
scala> type M[X] = X match { case Int => String case _ => Int }
scala> type N[X] = X match { case List[_] => Int }
4 changes: 2 additions & 2 deletions compiler/test-resources/repl/i6643
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
scala> import scala.collection._
scala>:type 1
Int
scala> object IterableTest { def g[CC[_] <: Iterable[_] with IterableOps[_, _, _]](from: CC[Int]): IterableFactory[CC] = ??? }
scala> object IterableTest { def g[CC[_] <: Iterable[?] with IterableOps[?, ?, ?]](from: CC[Int]): IterableFactory[CC] = ??? }
1 warning found
-- [E003] Syntax Warning: ------------------------------------------------------
1 | object IterableTest { def g[CC[_] <: Iterable[_] with IterableOps[_, _, _]](from: CC[Int]): IterableFactory[CC] = ??? }
1 | object IterableTest { def g[CC[_] <: Iterable[?] with IterableOps[?, ?, ?]](from: CC[Int]): IterableFactory[CC] = ??? }
| ^^^^
| with as a type operator has been deprecated; use & instead
|
Expand Down
2 changes: 1 addition & 1 deletion project/Build.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1266,8 +1266,8 @@ object Build {
libraryDependencies += ("org.scalameta" % "mtags-shared_2.13.12" % mtagsVersion % SourceDeps),
ivyConfigurations += SourceDeps.hide,
transitiveClassifiers := Seq("sources"),
scalacOptions ++= Seq("-source", "3.3"), // To avoid fatal migration warnings
Compile / scalacOptions ++= Seq("-Yexplicit-nulls", "-Ysafe-init"),
Compile / scalacOptions ++= Seq("-source", "3.3"), // To avoid fatal migration warnings
Compile / sourceGenerators += Def.task {
val s = streams.value
val cacheDir = s.cacheDirectory
Expand Down
4 changes: 2 additions & 2 deletions sbt-test/compilerReporter/i14576/Test.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ object Test:
def f(x: Text) = println(x.str)
f("abc")

// under -source:future, `_` is deprecated for wildcard arguments of types: use `?` instead
val xs: List[_] = Nil
@deprecated("", "") def deprecatedFun(): Unit = ()
deprecatedFun()
2 changes: 1 addition & 1 deletion scaladoc-testcases/src/tests/exports1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class A: //unexpected
= 1
type HKT[T[_], X] //expected: final type HKT = [T[_], X] =>> a.HKT[T, X]
= T[X]
type SomeRandomType = (List[_] | Seq[_]) & String //expected: final type SomeRandomType = a.SomeRandomType
type SomeRandomType = (List[?] | Seq[?]) & String //expected: final type SomeRandomType = a.SomeRandomType
def x[T[_], X](x: X): HKT[T, X] //expected: def x[T[_], X](x: X): A.this.HKT[T, X]
= ???
def fn[T, U]: T => U
Expand Down
2 changes: 1 addition & 1 deletion scaladoc-testcases/src/tests/hkts.scala
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ trait Case14[C[_]]
class SomeClass extends Case14[List]


def method1[E, T](value: List[_ >: E]): Int = 0
def method1[E, T](value: List[? >: E]): Int = 0
def method2[F[+X] <: Option[X], A](fa: F[A]): A = fa.get

import scala.collection.immutable.ArraySeq
Expand Down
2 changes: 1 addition & 1 deletion scaladoc-testcases/src/tests/snippetTestcase2.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package tests
package snippetTestcase2

trait Quotes2[A] {
val r1: r1Module[_] = ???
val r1: r1Module[?] = ???
trait r1Module[A] {
type X
object Y {
Expand Down
2 changes: 1 addition & 1 deletion scaladoc/src/dotty/tools/scaladoc/ScaladocSettings.scala
Original file line number Diff line number Diff line change
Expand Up @@ -133,5 +133,5 @@ class ScaladocSettings extends SettingGroup with AllScalaSettings:
"List of quick links that is displayed in the header of documentation."
)

def scaladocSpecificSettings: Set[Setting[_]] =
def scaladocSpecificSettings: Set[Setting[?]] =
Set(sourceLinks, legacySourceLink, syntax, revision, externalDocumentationMappings, socialLinks, skipById, skipByRegex, deprecatedSkipPackages, docRootContent, snippetCompiler, generateInkuire, defaultTemplate, scastieConfiguration, quickLinks)
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ class StaticSiteLoader(val root: File, val args: Scaladoc.Args)(using StaticSite
(("1900","01","01"), name)

def dateFrom(tf: TemplateFile, default: String = "1900-01-01"): String =
val pageSettings = tf.settings.get("page").collect{ case m: Map[String @unchecked, _] => m }
val pageSettings = tf.settings.get("page").collect{ case m: Map[String @unchecked, ?] => m }
pageSettings.flatMap(_.get("date").collect{ case s: String => s}).getOrElse(default) // blogs without date are last

val posts = List(rootPath.resolve("_posts"))
Expand Down
2 changes: 1 addition & 1 deletion scaladoc/src/dotty/tools/scaladoc/site/common.scala
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ def loadTemplateFile(file: File, defaultTitle: Option[TemplateName] = None)(usin
}.map(_.stripPrefix("\"").stripSuffix("\""))

def listSetting(settings: Map[String, Object], name: String): Option[List[String]] = settings.get(name).map {
case elems: List[_] => elems.zipWithIndex.map {
case elems: List[?] => elems.zipWithIndex.map {
case (s: String, _) => s
case (other, index) =>
throw new RuntimeException(s"Expected a string at index $index for $name in $file but got $other")
Expand Down
4 changes: 2 additions & 2 deletions scaladoc/src/dotty/tools/scaladoc/site/templates.scala
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,10 @@ case class TemplateFile(
)

def asJavaElement(o: Object): Object = o match
case m: Map[_, _] => m.transform {
case m: Map[?, ?] => m.transform {
case (k: String, v: Object) => asJavaElement(v)
}.asJava
case l: List[_] => l.map(x => asJavaElement(x.asInstanceOf[Object])).asJava
case l: List[?] => l.map(x => asJavaElement(x.asInstanceOf[Object])).asJava
case other => other

// Library requires mutable maps..
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import dotty.tools.dotc.util.{ SourcePosition, NoSourcePosition, SourceFile, NoS
import scala.util.{ Try, Success, Failure }

class SnippetCompiler(
val snippetCompilerSettings: Seq[SnippetCompilerSetting[_]],
val snippetCompilerSettings: Seq[SnippetCompilerSetting[?]],
target: AbstractFile = new VirtualDirectory("(memory)")
):
object SnippetDriver extends Driver:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ case class DocFlexmarkRenderer(renderLink: (DocLink, String) => String)
html.raw(renderLink(node.target, node.body))

object Render extends NodeRenderer:
override def getNodeRenderingHandlers: JSet[NodeRenderingHandler[_]] =
override def getNodeRenderingHandlers: JSet[NodeRenderingHandler[?]] =
JSet(
new NodeRenderingHandler(classOf[DocLinkNode], Handler),
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ object SectionRenderingExtension extends HtmlRenderer.HtmlRendererExtension:


object Render extends NodeRenderer:
override def getNodeRenderingHandlers: JSet[NodeRenderingHandler[_]] =
override def getNodeRenderingHandlers: JSet[NodeRenderingHandler[?]] =
JSet(
new NodeRenderingHandler(classOf[Section], SectionHandler),
new NodeRenderingHandler(classOf[AnchorLink], AnchorLinkHandler)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ object SnippetRenderingExtension extends HtmlRenderer.HtmlRendererExtension:
html.raw(SnippetRenderer.renderSnippet(node.getContentChars.toString, node.getInfo.toString.split(" ").headOption))

object Render extends NodeRenderer:
override def getNodeRenderingHandlers: JSet[NodeRenderingHandler[_]] =
override def getNodeRenderingHandlers: JSet[NodeRenderingHandler[?]] =
JSet(
new NodeRenderingHandler(classOf[ExtendedFencedCodeBlock], ExtendedFencedCodeBlockHandler),
new NodeRenderingHandler(classOf[FencedCodeBlock], FencedCodeBlockHandler)
Expand Down
2 changes: 1 addition & 1 deletion staging/src/scala/quoted/staging/ExprCompilationUnit.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ import dotty.tools.dotc.CompilationUnit
import dotty.tools.dotc.util.NoSource

/** Compilation unit containing the contents of a quoted expression */
private class ExprCompilationUnit(val exprBuilder: Quotes => Expr[_]) extends CompilationUnit(NoSource)
private class ExprCompilationUnit(val exprBuilder: Quotes => Expr[?]) extends CompilationUnit(NoSource)
2 changes: 1 addition & 1 deletion staging/src/scala/quoted/staging/QuoteCompiler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ private class QuoteCompiler extends Compiler:
/** Unpickle and optionally compile the expression.
* Returns either `Left` with name of the classfile generated or `Right` with the value contained in the expression.
*/
def compileExpr(exprBuilder: Quotes => Expr[_]): Either[String, Any] =
def compileExpr(exprBuilder: Quotes => Expr[?]): Either[String, Any] =
val units = new ExprCompilationUnit(exprBuilder) :: Nil
compileUnits(units)
result
Expand Down
2 changes: 1 addition & 1 deletion tests/init/pos/Properties.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import java.util.jar.Attributes.Name as AttributeName

private[scala] trait PropertiesTrait {
protected def propCategory: String // specializes the remainder of the values
protected def pickJarBasedOn: Class[_] // props file comes from jar containing this
protected def pickJarBasedOn: Class[?] // props file comes from jar containing this

/** The name of the properties file */
protected val propFilename = "/" + propCategory + ".properties"
Expand Down
10 changes: 5 additions & 5 deletions tests/neg-deep-subtype/i4297.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
class Test {
def test[X <: Option[Int]](x: X) = x.isInstanceOf[Some[Int]]
def test1[Y <: Int, X <: Option[Y]](x: X) = x.isInstanceOf[Some[Int]]
def test2(x: Any) = x.isInstanceOf[Function1[Nothing, _]]
def test3a(x: Any) = x.isInstanceOf[Function1[Any, _]] // error
def test3b(x: Any) = x.isInstanceOf[Function1[Int, _]] // error
def test4[Y <: Int, X <: Function1[Y, Unit]](x: X) = x.isInstanceOf[Function1[Int, _]] // error
def test2(x: Any) = x.isInstanceOf[Function1[Nothing, ?]]
def test3a(x: Any) = x.isInstanceOf[Function1[Any, ?]] // error
def test3b(x: Any) = x.isInstanceOf[Function1[Int, ?]] // error
def test4[Y <: Int, X <: Function1[Y, Unit]](x: X) = x.isInstanceOf[Function1[Int, ?]] // error
def test5[Y <: Int, X <: Function1[Y, Unit]](x: X) = x.isInstanceOf[Function1[Int, Unit]] // error
def test6[Y <: Int, X <: Function1[Y, Unit]](x: X) = x.isInstanceOf[Function1[Int, Any]] // error
def test7[Y <: Int, X <: Function1[Y, Unit]](x: X) = x.isInstanceOf[Function1[_, Unit]]
def test7[Y <: Int, X <: Function1[Y, Unit]](x: X) = x.isInstanceOf[Function1[?, Unit]]
}
4 changes: 2 additions & 2 deletions tests/neg-deep-subtype/i5826b.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

class Foo {
def test1[A]: List[Int] | A => Int = {
case ls: List[_] => ls.head // error
case ls: List[?] => ls.head // error
case _ => 0
}

def test2[A]: List[Int] | A => Int = {
case ls: List[_] => ls.size
case ls: List[?] => ls.size
case _ => 0
}
}
4 changes: 2 additions & 2 deletions tests/neg-deep-subtype/or-type-trees.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ object Test1 {

def foo3(myTree: Tree | (Context => Tree)) =
myTree match
case treeFn: (_ => _) => // ok
case treeFn: (? => ?) => // ok
case _ =>
}

Expand All @@ -35,6 +35,6 @@ object Test2 {

def foo3(myTree: Tree[Type] | (Context => Tree[Type])) =
myTree match
case treeFn: (_ => _) => // ok
case treeFn: (? => ?) => // ok
case _ =>
}
8 changes: 4 additions & 4 deletions tests/neg-deep-subtype/t2755.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,16 @@ object Test {
case x: Array[Float] => x.sum.toInt
case x: Array[String] => x.size
case x: Array[AnyRef] => 5
case x: Array[_] => 6
case x: Array[?] => 6
case _ => 7
}
def f2(a: Array[_]) = a match {
def f2(a: Array[?]) = a match {
case x: Array[Int] => x(0)
case x: Array[Double] => 2
case x: Array[Float] => x.sum.toInt
case x: Array[String] => x.size
case x: Array[AnyRef] => 5
case x: Array[_] => 6
case x: Array[?] => 6
case _ => 7 // error: only null is matched
}
def f3[T](a: Array[T]) = a match {
Expand All @@ -27,7 +27,7 @@ object Test {
case x: Array[Float] => x.sum.toInt
case x: Array[String] => x.size
case x: Array[AnyRef] => 5
case x: Array[_] => 6
case x: Array[?] => 6
case _ => 7 // error: only null is matched
}

Expand Down
2 changes: 1 addition & 1 deletion tests/neg/IsInstanceOfClassTag.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ object IsInstanceOfClassTag {
xs.head.substring(0)
}

safeCast[List[_]](List[Int](1)) match {
safeCast[List[?]](List[Int](1)) match {
case None =>
case Some(xs) =>
xs.head.substring(0) // error
Expand Down
2 changes: 1 addition & 1 deletion tests/neg/IsInstanceOfClassTag2.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ object IsInstanceOfClassTag {
case Some(xs) =>
}

safeCast[List[_]](List[Int](1)) match {
safeCast[List[?]](List[Int](1)) match {
case None =>
case Some(xs) =>
}
Expand Down
2 changes: 1 addition & 1 deletion tests/neg/i12284.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
trait I[F[_], A]

def magic[F[_], A](in: I[F, A]): F[A] =
val deps: Vector[I[F, _]] = ???
val deps: Vector[I[F, ?]] = ???
val xx = deps.map(i => magic(i))
val y: Vector[F[Any]] = xx // error
???
4 changes: 2 additions & 2 deletions tests/neg/i15662.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

case class Composite[T](v: T)

def m(composite: Composite[_]): Unit =
def m(composite: Composite[?]): Unit =
composite match {
case Composite[Int](v) => println(v) // error: cannot be checked at runtime
}

def m2(composite: Composite[_]): Unit =
def m2(composite: Composite[?]): Unit =
composite match {
case Composite(v) => println(v) // ok
}
Expand Down
6 changes: 3 additions & 3 deletions tests/neg/i15893.scala
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,17 @@ transparent inline def transparentInlineMod2(inline n: NatT): NatT = inline n m
def dependentlyTypedMod2[N <: NatT](n: N): Mod2[N] = n match
case Zero(): Zero => Zero() // error
case Succ(Zero()): Succ[Zero] => Succ(Zero()) // error
case Succ(Succ(predPredN)): Succ[Succ[_]] => dependentlyTypedMod2(predPredN) // error
case Succ(Succ(predPredN)): Succ[Succ[?]] => dependentlyTypedMod2(predPredN) // error

inline def inlineDependentlyTypedMod2[N <: NatT](inline n: N): Mod2[N] = inline n match
case Zero(): Zero => Zero() // error
case Succ(Zero()): Succ[Zero] => Succ(Zero()) // error
case Succ(Succ(predPredN)): Succ[Succ[_]] => inlineDependentlyTypedMod2(predPredN) // error
case Succ(Succ(predPredN)): Succ[Succ[?]] => inlineDependentlyTypedMod2(predPredN) // error

transparent inline def transparentInlineDependentlyTypedMod2[N <: NatT](inline n: N): Mod2[N] = inline n match
case Zero(): Zero => Zero() // error
case Succ(Zero()): Succ[Zero] => Succ(Zero()) // error
case Succ(Succ(predPredN)): Succ[Succ[_]] => transparentInlineDependentlyTypedMod2(predPredN) // error
case Succ(Succ(predPredN)): Succ[Succ[?]] => transparentInlineDependentlyTypedMod2(predPredN) // error

def foo(n: NatT): NatT = mod2(n) match
case Succ(Zero()) => Zero()
Expand Down
8 changes: 4 additions & 4 deletions tests/neg/i4382.check
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
-- [E043] Type Error: tests/neg/i4382.scala:3:10 -----------------------------------------------------------------------
3 | def v1: Id[_] = ??? // error
3 | def v1: Id[?] = ??? // error
| ^^^^^
| unreducible application of higher-kinded type App.Id to wildcard arguments
|
| longer explanation available when compiling with `-explain`
-- [E043] Type Error: tests/neg/i4382.scala:6:10 -----------------------------------------------------------------------
6 | def v2: HkL[_] = ??? // error
6 | def v2: HkL[?] = ??? // error
| ^^^^^^
| unreducible application of higher-kinded type App.HkL to wildcard arguments
|
| longer explanation available when compiling with `-explain`
-- [E043] Type Error: tests/neg/i4382.scala:9:10 -----------------------------------------------------------------------
9 | def v3: HkU[_] = ??? // error
9 | def v3: HkU[?] = ??? // error
| ^^^^^^
| unreducible application of higher-kinded type App.HkU to wildcard arguments
|
| longer explanation available when compiling with `-explain`
-- [E043] Type Error: tests/neg/i4382.scala:12:10 ----------------------------------------------------------------------
12 | def v4: HkAbs[_] = ??? // error
12 | def v4: HkAbs[?] = ??? // error
| ^^^^^^^^
| unreducible application of higher-kinded type App.HkAbs to wildcard arguments
|
Expand Down
8 changes: 4 additions & 4 deletions tests/neg/i4382.scala
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
object App {
type Id[A] >: A <: A
def v1: Id[_] = ??? // error
def v1: Id[?] = ??? // error

type HkL[A] >: A
def v2: HkL[_] = ??? // error
def v2: HkL[?] = ??? // error

type HkU[A] <: A
def v3: HkU[_] = ??? // error
def v3: HkU[?] = ??? // error

type HkAbs[A]
def v4: HkAbs[_] = ??? // error
def v4: HkAbs[?] = ??? // error
}
Loading

0 comments on commit 168e47a

Please sign in to comment.