From 276e368946a97f9978972281afb85eb3e54f26cd Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Tue, 5 Apr 2022 18:17:23 +0200 Subject: [PATCH] Allow ? as a wildcard even without -Xsource:3 Like https://github.com/scala/scala/pull/9721, the goal here is to ease cross-compilation between Scala 2 and 3 code as we prepare for `_` as wildcard to be deprecated in Scala 3 (cf https://github.com/lampepfl/dotty/issues/5379). This is technically a source-breaking change, but using a type named ? without backticks is deprecated since 2.13.6 (#9626) and defining a type named ? without backticks is disallowed since 2.13.7 (#9735). The only known user of ? as a type name was the kind-projector plugin, but support for this syntax was removed from the plugin a year ago (https://github.com/typelevel/kind-projector/pull/186), so I believe this change won't be disruptive. --- .../scala/tools/nsc/ast/parser/Parsers.scala | 10 ++-------- test/files/neg/qmark-deprecated.check | 18 +----------------- test/files/neg/qmark-deprecated.scala | 6 +++--- ...ds-future.scala => wildcards-present.scala} | 2 -- 4 files changed, 6 insertions(+), 30 deletions(-) rename test/files/pos/{wildcards-future.scala => wildcards-present.scala} (92%) diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index 17b9fc922e3b..8b9cbafad013 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -713,13 +713,9 @@ self => def isRawIdent = in.token == IDENTIFIER def isWildcardType = in.token == USCORE || isScala3WildcardType - def isScala3WildcardType = settings.isScala3 && isRawIdent && in.name == raw.QMARK - def checkQMarkUsage() = - if (!settings.isScala3 && isRawIdent && in.name == raw.QMARK) - deprecationWarning(in.offset, - "Wrap `?` in backticks to continue to use it as an identifier, or use `-Xsource:3` to use it as a wildcard like in Scala 3.", "2.13.6") + def isScala3WildcardType = isRawIdent && in.name == raw.QMARK def checkQMarkDefinition() = - if (isRawIdent && in.name == raw.QMARK) + if (isScala3WildcardType) syntaxError(in.offset, "using `?` as a type name requires backticks.") def checkKeywordDefinition() = if (isRawIdent && scala3Keywords.contains(in.name)) @@ -1149,7 +1145,6 @@ self => val scala3Wildcard = isScala3WildcardType wildcardType(in.skipToken(), scala3Wildcard) } else { - checkQMarkUsage() path(thisOK = false, typeOK = true) match { case r @ SingletonTypeTree(_) => r case r => convertToTypeId(r) @@ -2075,7 +2070,6 @@ self => if (in.token == SUBTYPE || in.token == SUPERTYPE) wildcardType(start, scala3Wildcard) else atPos(start) { Bind(tpnme.WILDCARD, EmptyTree) } } else { - checkQMarkUsage() typ() match { case Ident(name: TypeName) if nme.isVariableName(name) => atPos(start) { Bind(name, EmptyTree) } diff --git a/test/files/neg/qmark-deprecated.check b/test/files/neg/qmark-deprecated.check index 2d96f788ab9d..930dcd9e7320 100644 --- a/test/files/neg/qmark-deprecated.check +++ b/test/files/neg/qmark-deprecated.check @@ -2,7 +2,7 @@ qmark-deprecated.scala:4: error: using `?` as a type name requires backticks. class Foo[?] // error ^ qmark-deprecated.scala:6: error: using `?` as a type name requires backticks. -class Bar[M[?] <: List[?]] // errors +class Bar[M[?] <: List[?]] // error on the definition ^ qmark-deprecated.scala:10: error: using `?` as a type name requires backticks. class ? { val x = 1 } // error @@ -22,20 +22,4 @@ qmark-deprecated.scala:35: error: using `?` as a type name requires backticks. qmark-deprecated.scala:38: error: using `?` as a type name requires backticks. type A[?] = Int // error ^ -qmark-deprecated.scala:6: warning: Wrap `?` in backticks to continue to use it as an identifier, or use `-Xsource:3` to use it as a wildcard like in Scala 3. -class Bar[M[?] <: List[?]] // errors - ^ -qmark-deprecated.scala:27: warning: Wrap `?` in backticks to continue to use it as an identifier, or use `-Xsource:3` to use it as a wildcard like in Scala 3. - val x: Array[?] = new Array[?](0) // errors - ^ -qmark-deprecated.scala:27: warning: Wrap `?` in backticks to continue to use it as an identifier, or use `-Xsource:3` to use it as a wildcard like in Scala 3. - val x: Array[?] = new Array[?](0) // errors - ^ -qmark-deprecated.scala:30: warning: Wrap `?` in backticks to continue to use it as an identifier, or use `-Xsource:3` to use it as a wildcard like in Scala 3. - def foo1[T <: Array[?]](x: T): Array[?] = x // errors - ^ -qmark-deprecated.scala:30: warning: Wrap `?` in backticks to continue to use it as an identifier, or use `-Xsource:3` to use it as a wildcard like in Scala 3. - def foo1[T <: Array[?]](x: T): Array[?] = x // errors - ^ -5 warnings 8 errors diff --git a/test/files/neg/qmark-deprecated.scala b/test/files/neg/qmark-deprecated.scala index c370cfcb2673..f37edc58ea43 100644 --- a/test/files/neg/qmark-deprecated.scala +++ b/test/files/neg/qmark-deprecated.scala @@ -3,7 +3,7 @@ class Foo[?] // error class Foo2[`?`] // ok -class Bar[M[?] <: List[?]] // errors +class Bar[M[?] <: List[?]] // error on the definition class Bar2[M[`?`] <: List[`?`]] // ok object G { @@ -24,10 +24,10 @@ object I { object I2 { type `?` = Int // ok - val x: Array[?] = new Array[?](0) // errors + val x: Array[?] = new Array[?](0) // no error reported here because we stop before running typer val y: Array[`?`] = new Array[`?`](0) // ok - def foo1[T <: Array[?]](x: T): Array[?] = x // errors + def foo1[T <: Array[?]](x: T): Array[?] = x // ok def foo2[T <: Array[`?`]](x: T): Array[`?`] = x // ok def bar1[?] = {} // error diff --git a/test/files/pos/wildcards-future.scala b/test/files/pos/wildcards-present.scala similarity index 92% rename from test/files/pos/wildcards-future.scala rename to test/files/pos/wildcards-present.scala index c9afdea17bab..56daab01d17c 100644 --- a/test/files/pos/wildcards-future.scala +++ b/test/files/pos/wildcards-present.scala @@ -1,5 +1,3 @@ -// scalac: -Xsource:3 -// object Test { val xs: List[?] = List(1, 2, 3) val ys: Map[? <: AnyRef, ? >: Null] = Map()