Skip to content

Commit

Permalink
Merge pull request #9605 from 7mind/parse-variant-underscore-placehol…
Browse files Browse the repository at this point in the history
…ders

Parse `+_` and `-_` in types as identifiers to support Scala 3.2 placeholder syntax
  • Loading branch information
lrytz committed May 10, 2021
2 parents 5a04e29 + 0a00169 commit 8e4f76b
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 3 deletions.
11 changes: 8 additions & 3 deletions src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
Expand Up @@ -1139,11 +1139,16 @@ self =>
else
atPos(start)(makeSafeTupleType(inParens(types())))
case _ =>
if (isWildcardType) {
if (settings.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
} else
path(thisOK = false, typeOK = true) match {
case r @ SingletonTypeTree(_) => r
case r => convertToTypeId(r)
Expand Down
7 changes: 7 additions & 0 deletions test/files/neg/variant-placeholders-future.check
@@ -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
^
2 errors
6 changes: 6 additions & 0 deletions test/files/neg/variant-placeholders-future.scala
@@ -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
@@ -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
^
2 errors
8 changes: 8 additions & 0 deletions test/files/neg/variant-placeholders-nofuture.scala
@@ -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
}
35 changes: 35 additions & 0 deletions test/files/pos/variant-placeholders-future.scala
@@ -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)))
}
}

0 comments on commit 8e4f76b

Please sign in to comment.