Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[backport] Underscore changes for -Xsource:3: parse +_/-_ and prefix wildcard variables introduced by ?-syntax with ? #9620

Merged
merged 2 commits into from
May 10, 2021
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
27 changes: 17 additions & 10 deletions src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -722,9 +722,8 @@ self =>
def isRawBar = isRawIdent && in.name == raw.BAR
def isRawIdent = in.token == IDENTIFIER

def isWildcardType =
in.token == USCORE ||
currentRun.isScala3 && isRawIdent && in.name == raw.QMARK
def isWildcardType = in.token == USCORE || isScala3WildcardType
def isScala3WildcardType = currentRun.isScala3 && isRawIdent && in.name == raw.QMARK

def isIdent = in.token == IDENTIFIER || in.token == BACKQUOTED_IDENT
def isMacro = in.token == IDENTIFIER && in.name == nme.MACROkw
Expand Down Expand Up @@ -1077,9 +1076,16 @@ self =>
simpleTypeRest(in.token match {
case LPAREN => atPos(start)(makeSafeTupleType(inParens(types()), start))
case _ =>
if (isWildcardType)
wildcardType(in.skipToken())
else
if (currentRun.isScala3 && (in.name == raw.PLUS || in.name == raw.MINUS) && lookingAhead(in.token == USCORE)) {
val start = in.offset
val identName = in.name.encode.append("_").toTypeName
in.nextToken()
in.nextToken()
atPos(start)(Ident(identName))
} else if (isWildcardType) {
val scala3Wildcard = isScala3WildcardType
wildcardType(in.skipToken(), scala3Wildcard)
} else
path(thisOK = false, typeOK = true) match {
case r @ SingletonTypeTree(_) => r
case r => convertToTypeId(r)
Expand Down Expand Up @@ -1476,8 +1482,8 @@ self =>
* WildcardType ::= `_' TypeBounds
* }}}
*/
def wildcardType(start: Offset) = {
val pname = freshTypeName("_$")
def wildcardType(start: Offset, qmark: Boolean) = {
val pname = if (qmark) freshTypeName("?$") else freshTypeName("_$")
val t = atPos(start)(Ident(pname))
val bounds = typeBounds()
val param = atPos(t.pos union bounds.pos) { makeSyntheticTypeParam(pname, bounds) }
Expand Down Expand Up @@ -1989,8 +1995,9 @@ self =>
def argType(): Tree = {
val start = in.offset
if (isWildcardType) {
val scala3Wildcard = isScala3WildcardType
in.nextToken()
if (in.token == SUBTYPE || in.token == SUPERTYPE) wildcardType(start)
if (in.token == SUBTYPE || in.token == SUPERTYPE) wildcardType(start, scala3Wildcard)
else atPos(start) { Bind(tpnme.WILDCARD, EmptyTree) }
} else
typ() match {
Expand Down Expand Up @@ -2357,7 +2364,7 @@ self =>
val vds = new ListBuffer[List[ValDef]]
val start = in.offset
def paramClause(): List[ValDef] = if (in.token == RPAREN) Nil else {
val implicitmod =
val implicitmod =
if (in.token == IMPLICIT) {
if (implicitOffset == -1) { implicitOffset = in.offset ; implicitSection = vds.length }
else if (warnAt == -1) warnAt = in.offset
Expand Down
7 changes: 7 additions & 0 deletions test/files/neg/variant-placeholders-future.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
variant-placeholders-future.scala:4: error: `=', `>:', or `<:' expected
type -_ = Int // error -_ not allowed as a type def name without backticks
^
variant-placeholders-future.scala:5: error: `=', `>:', or `<:' expected
type +_ = Int // error +_ not allowed as a type def name without backticks
^
two errors found
6 changes: 6 additions & 0 deletions test/files/neg/variant-placeholders-future.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// scalac: -Xsource:3
//
object Test {
type -_ = Int // error -_ not allowed as a type def name without backticks
type +_ = Int // error +_ not allowed as a type def name without backticks
}
7 changes: 7 additions & 0 deletions test/files/neg/variant-placeholders-nofuture.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
variant-placeholders-nofuture.scala:5: error: ';' expected but '_' found.
val fnMinusPlus1: -_ => +_ = (_: Int).toLong // error -_/+_ won't parse without -Xsource:3
^
variant-placeholders-nofuture.scala:6: error: ')' expected but '_' found.
val fnMinusPlus2: (-_) => +_ = fnMinusPlus1 // error -_/+_ won't parse without -Xsource:3
^
two errors found
8 changes: 8 additions & 0 deletions test/files/neg/variant-placeholders-nofuture.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
object Test {
type `-_` = Int
type `+_` = Long

val fnMinusPlus1: -_ => +_ = (_: Int).toLong // error -_/+_ won't parse without -Xsource:3
val fnMinusPlus2: (-_) => +_ = fnMinusPlus1 // error -_/+_ won't parse without -Xsource:3
val fnMinusPlus3: -_ => (+_) = fnMinusPlus2 // error -_/+_ won't parse without -Xsource:3
}
11 changes: 11 additions & 0 deletions test/files/neg/wildcards-future.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
wildcards-future.scala:7: error: type mismatch;
found : Map[_$1,_$2] where type _$2 >: Null, type _$1 <: AnyRef
required: Map[String,String]
underscores : Map[String, String] // error wildcard variables starting with `_`
^
wildcards-future.scala:9: error: type mismatch;
found : Map[?$1,?$2] where type ?$2 >: Null, type ?$1 <: AnyRef
required: Map[String,String]
qmarks : Map[String, String] // error – wildcard variables should start with `?` to differentiate from the old syntax
^
two errors found
11 changes: 11 additions & 0 deletions test/files/neg/wildcards-future.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// scalac: -Xsource:3
//
object Test {
val underscores: Map[_ <: AnyRef, _ >: Null] = Map()
val qmarks: Map[? <: AnyRef, ? >: Null] = Map()

underscores : Map[String, String] // error wildcard variables starting with `_`

qmarks : Map[String, String] // error – wildcard variables should start with `?` to differentiate from the old syntax
// (and have a mildly more readable error...)
}
35 changes: 35 additions & 0 deletions test/files/pos/variant-placeholders-future.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// scalac: -Xsource:3
//
object Test {
type `-_` = Int
type `+_` = Long

val fnMinusPlus1: -_ => +_ = (_: Int).toLong
val fnMinusPlus2: (-_) => +_ = fnMinusPlus1
val fnMinusPlus3: -_ => (+_) = fnMinusPlus2

val fnTupMinusPlus2: (=> -_, -_) => +_ = (a, b) => ((a: Int) + (b: Int)).toLong
def defMinusPlus2(byname: => -_, vararg: -_*): +_ = ((vararg.sum: Int) + (byname: -_)).toLong
val infixMinusPlus2: -_ Either +_ = Right[-_, +_](1L)

val optPlus: Option[+_] = Some[ + _ ](1L) // spaces allowed
optPlus match {
case opt: Option[ + _ ] =>
val opt1: + _ = opt.get
val opt2: Long = opt1
}

val optMinus: Option[-_] = Some[ - _ ](1) // spaces allowed
optMinus match {
case opt: Option[ - _ ] =>
val opt1: `-_` = opt.get
val optErr: - _ = opt.get
val opt2: Int = opt1
}

locally {
type `-_`[A] = A
type `+_`[A] = Option[A]
val optOpt: Option[ + _ [+_[-_[Int]]]] = Some(Some(Some(1)))
}
}