aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dotty/tools/dotc/parsing/Parsers.scala39
-rw-r--r--tests/neg/i1059.scala10
-rw-r--r--tests/pos-scala2/i1059.scala10
3 files changed, 54 insertions, 5 deletions
diff --git a/src/dotty/tools/dotc/parsing/Parsers.scala b/src/dotty/tools/dotc/parsing/Parsers.scala
index 6ec75a8b2..ea9da8db9 100644
--- a/src/dotty/tools/dotc/parsing/Parsers.scala
+++ b/src/dotty/tools/dotc/parsing/Parsers.scala
@@ -259,11 +259,19 @@ object Parsers {
} finally inFunReturnType = saved
}
+ private val isScala2Mode =
+ ctx.settings.language.value.contains(nme.Scala2.toString)
+
+ def migrationWarningOrError(msg: String, offset: Int = in.offset) =
+ if (isScala2Mode)
+ ctx.migrationWarning(msg, source atPos Position(offset))
+ else
+ syntaxError(msg, offset)
+
/** Cannot use ctx.featureEnabled because accessing the context would force too much */
private def testScala2Mode(msg: String, pos: Position = Position(in.offset)) = {
- val s2 = ctx.settings.language.value.contains(nme.Scala2.toString)
- if (s2) ctx.migrationWarning(msg, source atPos pos)
- s2
+ if (isScala2Mode) ctx.migrationWarning(msg, source atPos pos)
+ isScala2Mode
}
/* ---------- TREE CONSTRUCTION ------------------------------------------- */
@@ -1309,7 +1317,20 @@ object Parsers {
*/
val pattern2 = () => infixPattern() match {
case p @ Ident(name) if isVarPattern(p) && in.token == AT =>
- atPos(p.pos.start, in.skipToken()) { Bind(name, infixPattern()) }
+ val pos = in.skipToken()
+
+ // compatibility for Scala2 `x @ _*` syntax
+ infixPattern() match {
+ case pt @ Ident(tpnme.WILDCARD_STAR) =>
+ migrationWarningOrError("The syntax `x @ _*' is no longer supported; use `x : _*' instead", p.pos.start)
+ atPos(p.pos.start, pos) { Typed(p, pt) }
+ case p =>
+ atPos(p.pos.start, pos) { Bind(name, p) }
+ }
+ case p @ Ident(tpnme.WILDCARD_STAR) =>
+ // compatibility for Scala2 `_*` syntax
+ migrationWarningOrError("The syntax `_*' is no longer supported; use `x : _*' instead", p.pos.start)
+ atPos(p.pos.start) { Typed(Ident(nme.WILDCARD), p) }
case p =>
p
}
@@ -1337,7 +1358,15 @@ object Parsers {
case t => simplePatternRest(t)
}
case USCORE =>
- wildcardIdent()
+ val wildIndent = wildcardIdent()
+
+ // compatibility for Scala2 `x @ _*` and `_*` syntax
+ // `x: _*' is parsed in `ascription'
+ if (isIdent(nme.raw.STAR)) {
+ in.nextToken()
+ if (in.token != RPAREN) syntaxError("`_*' can be used only for last argument", wildIndent.pos)
+ atPos(wildIndent.pos) { Ident(tpnme.WILDCARD_STAR) }
+ } else wildIndent
case LPAREN =>
atPos(in.offset) { makeTupleOrParens(inParens(patternsOpt())) }
case LBRACE =>
diff --git a/tests/neg/i1059.scala b/tests/neg/i1059.scala
new file mode 100644
index 000000000..1fb89afd0
--- /dev/null
+++ b/tests/neg/i1059.scala
@@ -0,0 +1,10 @@
+object Repeated {
+ val list = List(1, 2, 3)
+
+ list match {
+ case List(_, _, _, _ @ _*) => 0 // error: only allowed in Scala2 mode
+ case List(_, _, _*) => 1 // error: only allowed in Scala2 mode
+ case List(_, _: _*) => 2
+ case Nil => 3
+ }
+}
diff --git a/tests/pos-scala2/i1059.scala b/tests/pos-scala2/i1059.scala
new file mode 100644
index 000000000..cd23e1916
--- /dev/null
+++ b/tests/pos-scala2/i1059.scala
@@ -0,0 +1,10 @@
+object Repeated {
+ val list = List(1, 2, 3)
+
+ list match {
+ case List(_, _, _, _ @ _*) => 0
+ case List(_, _, _*) => 1
+ case List(_, _: _*) => 2
+ case Nil => 3
+ }
+}