Skip to content

Commit

Permalink
Allow ? as a wildcard even without -Xsource:3
Browse files Browse the repository at this point in the history
Like scala#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 scala/scala3#5379).

This is technically a source-breaking change, but using a type named ? without
backticks is deprecated since 2.13.6 (scala#9626) and defining a type named ? without
backticks is disallowed since 2.13.7 (scala#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 (typelevel/kind-projector#186),
so I believe this change won't be disruptive.
  • Loading branch information
smarter committed Apr 5, 2022
1 parent 6471120 commit 276e368
Show file tree
Hide file tree
Showing 4 changed files with 6 additions and 30 deletions.
10 changes: 2 additions & 8 deletions src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
Expand Up @@ -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))
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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) }
Expand Down
18 changes: 1 addition & 17 deletions test/files/neg/qmark-deprecated.check
Expand Up @@ -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
Expand All @@ -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
6 changes: 3 additions & 3 deletions test/files/neg/qmark-deprecated.scala
Expand Up @@ -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 {
Expand All @@ -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
Expand Down
@@ -1,5 +1,3 @@
// scalac: -Xsource:3
//
object Test {
val xs: List[?] = List(1, 2, 3)
val ys: Map[? <: AnyRef, ? >: Null] = Map()
Expand Down

0 comments on commit 276e368

Please sign in to comment.