From 026be415486d75001f10cf12b1e827b73654035d Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sat, 19 Sep 2020 17:05:11 +0200 Subject: [PATCH 1/2] Fix #9829: Allow `as` in place of `@` for pattern bindings --- compiler/src/dotty/tools/dotc/parsing/Parsers.scala | 8 ++++++-- .../dotty/internal/StringContextMacro.scala | 2 +- .../src-bootstrapped/scala/internal/quoted/Matcher.scala | 4 ++-- library/src-bootstrapped/scala/quoted/util/ExprMap.scala | 2 +- tests/init/crash/fors.scala | 4 ++-- tests/neg/Iter3.scala | 2 +- tests/neg/ensureReported.scala | 2 +- tests/neg/i1716.scala | 2 +- tests/neg/i3200.scala | 2 +- tests/neg/i3200b.scala | 8 ++++---- tests/neg/i3332.scala | 2 +- tests/neg/i3812b.scala | 4 ++-- tests/neg/i8407.scala | 2 +- tests/neg/i8715.scala | 2 +- tests/neg/i9310.scala | 2 +- tests/neg/multi-patterns.scala | 2 +- tests/neg/patternUnsoundness.scala | 2 +- tests/pos/Iter2.scala | 2 +- tests/pos/i1540.scala | 2 +- tests/pos/i1540b.scala | 2 +- tests/pos/i3412.scala | 2 +- tests/pos/i4177.scala | 2 +- tests/pos/i4564.scala | 2 +- tests/pos/i5402.scala | 2 +- tests/pos/simpleExtractors-2.scala | 4 ++-- tests/pos/t10533.scala | 2 +- tests/pos/t3136.scala | 2 +- tests/pos/t6675.scala | 2 +- tests/pos/trailingCommas/trailingCommas.scala | 2 +- tests/pos/virtpatmat_alts_subst.scala | 2 +- tests/run/3179.scala | 2 +- tests/run/enums-serialization-compat.scala | 6 +++--- tests/run/fors.scala | 4 ++-- tests/run/fully-abstract-interface.scala | 8 ++++---- tests/run/fully-abstract-nat-1.scala | 2 +- tests/run/fully-abstract-nat-2.scala | 2 +- tests/run/fully-abstract-nat-3.scala | 4 ++-- tests/run/fully-abstract-nat-4.scala | 2 +- tests/run/fully-abstract-nat-5.scala | 2 +- tests/run/fully-abstract-nat-6.scala | 2 +- tests/run/fully-abstract-nat-7.scala | 2 +- tests/run/fully-abstract-nat.scala | 4 ++-- tests/run/i1099.scala | 2 +- tests/run/i1432.scala | 4 ++-- tests/run/i1463.scala | 2 +- tests/run/i1991.scala | 4 ++-- tests/run/i3200c.scala | 2 +- tests/run/patmat-bind-typed.scala | 2 +- tests/run/patmat-spec.scala | 2 +- tests/run/patmatch-classtag.scala | 2 +- tests/run/t6646.scala | 4 ++-- tests/run/t8395.scala | 2 +- tests/run/unchecked-patterns.scala | 2 +- 53 files changed, 76 insertions(+), 72 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index 5aba3e43e368..595b3a3c8925 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -2631,7 +2631,10 @@ object Parsers { /** Pattern2 ::= [id `@'] InfixPattern */ val pattern2: () => Tree = () => infixPattern() match { - case p @ Ident(name) if in.token == AT => + case p @ Ident(name) if in.token == AT || in.isIdent(nme.as) => + if in.token == AT && sourceVersion.isAtLeast(`3.1`) then + deprecationWarning(s"`@` bindings have been deprecated; use `as` instead", in.offset) + val offset = in.skipToken() // compatibility for Scala2 `x @ _*` syntax @@ -2659,7 +2662,8 @@ object Parsers { /** InfixPattern ::= SimplePattern {id [nl] SimplePattern} */ def infixPattern(): Tree = - infixOps(simplePattern(), in.canStartExprTokens, simplePattern, isOperator = in.name != nme.raw.BAR) + infixOps(simplePattern(), in.canStartExprTokens, simplePattern, + isOperator = in.name != nme.raw.BAR && in.name != nme.as) /** SimplePattern ::= PatVar * | Literal diff --git a/library/src-bootstrapped/dotty/internal/StringContextMacro.scala b/library/src-bootstrapped/dotty/internal/StringContextMacro.scala index 92ba70c39214..d60da06cbd20 100644 --- a/library/src-bootstrapped/dotty/internal/StringContextMacro.scala +++ b/library/src-bootstrapped/dotty/internal/StringContextMacro.scala @@ -62,7 +62,7 @@ object StringContextMacro { val sourceFile = strCtxExpr.unseal.pos.sourceFile val (partsExpr, parts) = strCtxExpr match { - case Expr.StringContext(p1 @ Consts(p2)) => (p1.toList, p2.toList) + case Expr.StringContext(p1 as Consts(p2)) => (p1.toList, p2.toList) case _ => report.throwError("Expected statically known String Context", strCtxExpr) } diff --git a/library/src-bootstrapped/scala/internal/quoted/Matcher.scala b/library/src-bootstrapped/scala/internal/quoted/Matcher.scala index fccf8f96ae3f..6825c6336193 100644 --- a/library/src-bootstrapped/scala/internal/quoted/Matcher.scala +++ b/library/src-bootstrapped/scala/internal/quoted/Matcher.scala @@ -244,7 +244,7 @@ object Matcher { /* Term hole */ // Match a scala.internal.Quoted.patternHole typed as a repeated argument and return the scrutinee tree - case (scrutinee @ Typed(s, tpt1), Typed(TypeApply(patternHole, tpt :: Nil), tpt2)) + case (scrutinee as Typed(s, tpt1), Typed(TypeApply(patternHole, tpt :: Nil), tpt2)) if patternHole.symbol == qctx.tasty.Definitions_InternalQuotedMatcher_patternHole && s.tpe <:< tpt.tpe && tpt2.tpe.derivesFrom(defn.RepeatedParamClass) => @@ -259,7 +259,7 @@ object Matcher { /* Higher order term hole */ // Matches an open term and wraps it into a lambda that provides the free variables - case (scrutinee, pattern @ Apply(TypeApply(Ident("higherOrderHole"), List(Inferred())), Repeated(args, _) :: Nil)) + case (scrutinee, pattern as Apply(TypeApply(Ident("higherOrderHole"), List(Inferred())), Repeated(args, _) :: Nil)) if pattern.symbol == qctx.tasty.Definitions_InternalQuotedMatcher_higherOrderHole => def bodyFn(lambdaArgs: List[Tree]): Tree = { diff --git a/library/src-bootstrapped/scala/quoted/util/ExprMap.scala b/library/src-bootstrapped/scala/quoted/util/ExprMap.scala index 64be17340a9b..735aaeb12315 100644 --- a/library/src-bootstrapped/scala/quoted/util/ExprMap.scala +++ b/library/src-bootstrapped/scala/quoted/util/ExprMap.scala @@ -51,7 +51,7 @@ trait ExprMap { tree case Super(qual, mix) => tree - case tree @ Apply(fun, args) => + case tree as Apply(fun, args) => val MethodType(_, tpes, _) = fun.tpe.widen Apply.copy(tree)(transformTerm(fun, Type.of[Any]), transformTerms(args, tpes)) case TypeApply(fun, args) => diff --git a/tests/init/crash/fors.scala b/tests/init/crash/fors.scala index d8f76473f773..50ed4bf69a38 100644 --- a/tests/init/crash/fors.scala +++ b/tests/init/crash/fors.scala @@ -26,7 +26,7 @@ object Test extends App { var n = 0 for (_ <- xs) n += 1; println(n) for ((x, y) <- xs zip ys) print(x + " "); println() - for (p @ (x, y) <- xs zip ys) print(p._1 + " "); println() + for (p as (x, y) <- xs zip ys) print(p._1 + " "); println() // iterators for (x <- it) print(x + " "); println() @@ -53,7 +53,7 @@ object Test extends App { var n = 0 for (_ <- xs) n += 1; println(n) for ((x, y) <- xs zip ys) print(x + " "); println() - for (p @ (x, y) <- xs zip ys) print(p._1 + " "); println() + for (p as (x, y) <- xs zip ys) print(p._1 + " "); println() // iterators for (x <- it) print(x + " "); println() diff --git a/tests/neg/Iter3.scala b/tests/neg/Iter3.scala index 68dfdc1ac6de..db363432a021 100644 --- a/tests/neg/Iter3.scala +++ b/tests/neg/Iter3.scala @@ -147,7 +147,7 @@ object Iter2 { flatten(map(f(_).buildIterator)) override def ++[B >: A](that: IterableOnce[B]): ArrayIterator[B] = { - val thatIterator @ ArrayIterator(elems2, len2) = fromIterator(that.iterator) + val thatIterator as ArrayIterator(elems2, len2) = fromIterator(that.iterator) if (len == 0) thatIterator else if (len2 == 0) this.asInstanceOf[ArrayIterator[B]] else { diff --git a/tests/neg/ensureReported.scala b/tests/neg/ensureReported.scala index 38e1e1307fd4..712c541f8e40 100644 --- a/tests/neg/ensureReported.scala +++ b/tests/neg/ensureReported.scala @@ -1,6 +1,6 @@ object AnonymousF { val f = { - case l @ List(1) => // error: missing parameter type + case l as List(1) => // error: missing parameter type Some(l) } } diff --git a/tests/neg/i1716.scala b/tests/neg/i1716.scala index fab79c833e4c..b9994d3fd1cc 100644 --- a/tests/neg/i1716.scala +++ b/tests/neg/i1716.scala @@ -1,7 +1,7 @@ object Fail { def f(m: Option[Int]): Unit = { m match { - case x @ Some[_] => // error: unbound wildcard type + case x as Some[_] => // error: unbound wildcard type case _ => } } diff --git a/tests/neg/i3200.scala b/tests/neg/i3200.scala index 7d905810b6ab..8e7da443a758 100644 --- a/tests/neg/i3200.scala +++ b/tests/neg/i3200.scala @@ -1,6 +1,6 @@ object Test { case object Bob { override def equals(other: Any) = true } def main(args: Array[String]): Unit = { - val m : Bob.type = (5: Any) match { case x @ Bob => x } // error + val m : Bob.type = (5: Any) match { case x as Bob => x } // error } } diff --git a/tests/neg/i3200b.scala b/tests/neg/i3200b.scala index 51de3e3964b8..9b647838ba4a 100644 --- a/tests/neg/i3200b.scala +++ b/tests/neg/i3200b.scala @@ -1,8 +1,8 @@ object Test { def main(args: Array[String]): Unit = { - val a: Nil.type = (Vector(): Any) match { case n @ Nil => n } // error - val b: Nil.type = (Vector(): Any) match { case n @ (m @ Nil) => n } // error - val c: Int = (1.0: Any) match { case n @ 1 => n } // error - val d: Int = (1.0: Any) match { case n @ (m @ 1) => n } // error + val a: Nil.type = (Vector(): Any) match { case n as Nil => n } // error + val b: Nil.type = (Vector(): Any) match { case n as (m as Nil) => n } // error + val c: Int = (1.0: Any) match { case n as 1 => n } // error + val d: Int = (1.0: Any) match { case n as (m as 1) => n } // error } } diff --git a/tests/neg/i3332.scala b/tests/neg/i3332.scala index e2964a22050e..64aad9c97777 100644 --- a/tests/neg/i3332.scala +++ b/tests/neg/i3332.scala @@ -16,6 +16,6 @@ object Test { case _ => println("nope") } def test(x: Any) = x match { - case _: String | _ @ A() => 1 + case _: String | _ as A() => 1 } } diff --git a/tests/neg/i3812b.scala b/tests/neg/i3812b.scala index e9b0c291ef3f..8a222a2e8ce3 100644 --- a/tests/neg/i3812b.scala +++ b/tests/neg/i3812b.scala @@ -19,9 +19,9 @@ object Test { Some(x) match { case Some(Z2.v) => () } // ok Some(x) match { case Some(4) | Some(Z1.v) => () } // error - Some(x) match { case a @ Some(Z1.v) => () } // error + Some(x) match { case a as Some(Z1.v) => () } // error Some(x) match { case Some(4) | Some(Z2.v) => () } // ok - Some(x) match { case a @ Some(Z2.v) => () } // ok + Some(x) match { case a as Some(Z2.v) => () } // ok } } diff --git a/tests/neg/i8407.scala b/tests/neg/i8407.scala index 34d7fa20914c..744bb1487700 100644 --- a/tests/neg/i8407.scala +++ b/tests/neg/i8407.scala @@ -1,6 +1,6 @@ object Test: val xs = List(1, 2, 3, 4, 5) xs match { - case List(1, 2, xs1 @ xs2: _*) => println(xs2) // error // error + case List(1, 2, xs1 as xs2: _*) => println(xs2) // error // error case _ => () } \ No newline at end of file diff --git a/tests/neg/i8715.scala b/tests/neg/i8715.scala index aedb32cffdcb..f5607e39a615 100644 --- a/tests/neg/i8715.scala +++ b/tests/neg/i8715.scala @@ -1,2 +1,2 @@ @main -def Test = List(42) match { case List(xs @ (ys: _*)) => xs } // error +def Test = List(42) match { case List(xs as (ys: _*)) => xs } // error diff --git a/tests/neg/i9310.scala b/tests/neg/i9310.scala index 7e57e8c99092..7d23e0b7a18e 100644 --- a/tests/neg/i9310.scala +++ b/tests/neg/i9310.scala @@ -1,5 +1,5 @@ //AE-d101cfe6d25117a51897609e673f6c8e74d31e6e -val foo @ this = 0 +val foo as this = 0 class Foo { foo { } // error } \ No newline at end of file diff --git a/tests/neg/multi-patterns.scala b/tests/neg/multi-patterns.scala index 2aabdf3f5b0b..3cacb40e7bac 100644 --- a/tests/neg/multi-patterns.scala +++ b/tests/neg/multi-patterns.scala @@ -1,4 +1,4 @@ object Test { val (a :: as), bs = List(1, 2, 3) // error - val B @ List(), C: List[Int] = List() // error + val B as List(), C: List[Int] = List() // error } \ No newline at end of file diff --git a/tests/neg/patternUnsoundness.scala b/tests/neg/patternUnsoundness.scala index 5401faf4be19..1db64979dd2d 100644 --- a/tests/neg/patternUnsoundness.scala +++ b/tests/neg/patternUnsoundness.scala @@ -10,7 +10,7 @@ object patternUnsoundness extends App { val y: C[Object] = x y match { - case d @ D(x) => d.s = new Integer(1) // error + case d as D(x) => d.s = new Integer(1) // error } val z: String = x.s // used to throw ClassCast exception diff --git a/tests/pos/Iter2.scala b/tests/pos/Iter2.scala index ff4ab32e0c21..193a715e388f 100644 --- a/tests/pos/Iter2.scala +++ b/tests/pos/Iter2.scala @@ -193,7 +193,7 @@ object Iter2 { flatten(map(f(_).buildIterator)) override def ++[B >: A](that: IterableOnce[B]): ArrayIterator[B] = { - val thatIterator @ ArrayIterator(elems2, len2) = fromIterator(that.iterator) + val thatIterator as ArrayIterator(elems2, len2) = fromIterator(that.iterator) if (len == 0) thatIterator else if (len2 == 0) this else { diff --git a/tests/pos/i1540.scala b/tests/pos/i1540.scala index 0fdfea23555d..096a19aee060 100644 --- a/tests/pos/i1540.scala +++ b/tests/pos/i1540.scala @@ -8,7 +8,7 @@ object Casey1 { def unapply(a: Casey1) = a } object Test { def main(args: Array[String]): Unit = { - val c @ Casey1(x) = new Casey1(0) + val c as Casey1(x) = new Casey1(0) assert(x == c.get) } } diff --git a/tests/pos/i1540b.scala b/tests/pos/i1540b.scala index f4408b0c7aab..64a09a43061d 100644 --- a/tests/pos/i1540b.scala +++ b/tests/pos/i1540b.scala @@ -8,7 +8,7 @@ object Casey1 { def unapply[T](a: Casey1[T]) = a } object Test { def main(args: Array[String]): Unit = { - val c @ Casey1(x) = new Casey1(0) + val c as Casey1(x) = new Casey1(0) assert(x == c.get) } } diff --git a/tests/pos/i3412.scala b/tests/pos/i3412.scala index ff21986d3143..071fcee9fb53 100644 --- a/tests/pos/i3412.scala +++ b/tests/pos/i3412.scala @@ -1,3 +1,3 @@ class Test { - val A @ List() = List() + val A as List() = List() } diff --git a/tests/pos/i4177.scala b/tests/pos/i4177.scala index dfcedf92d424..13dde628a77a 100644 --- a/tests/pos/i4177.scala +++ b/tests/pos/i4177.scala @@ -6,7 +6,7 @@ class Test { val a: PartialFunction[Int, String] = { case Foo(x) => x } val b: PartialFunction[Int, String] = { case x => x.toString } - val e: PartialFunction[String, String] = { case x @ "abc" => x } + val e: PartialFunction[String, String] = { case x as "abc" => x } val f: PartialFunction[String, String] = x => x match { case "abc" => x } val g: PartialFunction[String, String] = x => x match { case "abc" if x.isEmpty => x } diff --git a/tests/pos/i4564.scala b/tests/pos/i4564.scala index 795d04223352..66e97aabd795 100644 --- a/tests/pos/i4564.scala +++ b/tests/pos/i4564.scala @@ -10,7 +10,7 @@ object ClashNoSig { // ok def unapply(x: ClashNoSig) = x ClashNoSig(2) match { - case c @ ClashNoSig(y) => c.copy(y + c._1) + case c as ClashNoSig(y) => c.copy(y + c._1) } } case class ClashNoSig private (x: Int) { diff --git a/tests/pos/i5402.scala b/tests/pos/i5402.scala index fa4e23ed9ce6..647dd43afeb3 100644 --- a/tests/pos/i5402.scala +++ b/tests/pos/i5402.scala @@ -9,7 +9,7 @@ object Main { case 1 => 1 case 0 | 0 => 0 case 2 | 2 | 2 | 3 | 2 | 3 => 0 - case 4 | (_ @ 4) => 0 + case 4 | (_ as 4) => 0 case _ => -1 } diff --git a/tests/pos/simpleExtractors-2.scala b/tests/pos/simpleExtractors-2.scala index ad9d165aa37c..ba0cecab5d78 100644 --- a/tests/pos/simpleExtractors-2.scala +++ b/tests/pos/simpleExtractors-2.scala @@ -1,7 +1,7 @@ class Foo { def bar(x: Any): Unit = x match { case Some(Some(i: Int)) => println(i) - case Some(s @ Some(i)) => println(s) - case s @ Some(r @ Some(i)) => println(s) + case Some(s as Some(i)) => println(s) + case s as Some(r as Some(i)) => println(s) } } diff --git a/tests/pos/t10533.scala b/tests/pos/t10533.scala index d84e87b0bc21..714ec72979c1 100644 --- a/tests/pos/t10533.scala +++ b/tests/pos/t10533.scala @@ -1,5 +1,5 @@ object Foo { - val b @ Bar(_) = Bar(1)(2)(3) + val b as Bar(_) = Bar(1)(2)(3) } case class Bar(a: Int)(b: Int)(c: Int) diff --git a/tests/pos/t3136.scala b/tests/pos/t3136.scala index 239bd8f54f4d..86a2c81e3045 100644 --- a/tests/pos/t3136.scala +++ b/tests/pos/t3136.scala @@ -13,7 +13,7 @@ object NullaryMethodType { object Test { def TEST(tp: Type): String = tp match { - case PolyType(ps1, PolyType(ps2, res @ PolyType(a, b))) => "1" + tp // couldn't find a simpler version that still crashes + case PolyType(ps1, PolyType(ps2, res as PolyType(a, b))) => "1" + tp // couldn't find a simpler version that still crashes case NullaryMethodType(meh) => "2" + meh } } diff --git a/tests/pos/t6675.scala b/tests/pos/t6675.scala index f3bebea5be94..599ba89dbb14 100644 --- a/tests/pos/t6675.scala +++ b/tests/pos/t6675.scala @@ -7,7 +7,7 @@ object LeftOrRight { object Test { (Left((0, 0)): Either[(Int, Int), (Int, Int)]) match { - case LeftOrRight(pair @ (a, b)) => a // false -Xlint warning: "extractor pattern binds a single value to a Product2 of type (Int, Int)" + case LeftOrRight(pair as (a, b)) => a // false -Xlint warning: "extractor pattern binds a single value to a Product2 of type (Int, Int)" } (Left((0, 0)): Either[(Int, Int), (Int, Int)]) match { diff --git a/tests/pos/trailingCommas/trailingCommas.scala b/tests/pos/trailingCommas/trailingCommas.scala index 6170fda0fe9b..f0423bc1e00f 100644 --- a/tests/pos/trailingCommas/trailingCommas.scala +++ b/tests/pos/trailingCommas/trailingCommas.scala @@ -114,7 +114,7 @@ trait SimplePattern { // test '@' syntax in patterns Some(1) match { - case Some(x @ 1, + case Some(x as 1, ) => x } diff --git a/tests/pos/virtpatmat_alts_subst.scala b/tests/pos/virtpatmat_alts_subst.scala index e27c52f9c772..00bd897ea3b5 100644 --- a/tests/pos/virtpatmat_alts_subst.scala +++ b/tests/pos/virtpatmat_alts_subst.scala @@ -1,6 +1,6 @@ case class Foo(s: String) { def appliedType(tycon: Any) = tycon match { - case Foo(sym @ ("NothingClass" | "AnyClass")) => println(sym) + case Foo(sym as ("NothingClass" | "AnyClass")) => println(sym) } } diff --git a/tests/run/3179.scala b/tests/run/3179.scala index 79c06c8fb1cc..0eb13bd54fef 100644 --- a/tests/run/3179.scala +++ b/tests/run/3179.scala @@ -1,7 +1,7 @@ object Test { def main(args: Array[String]): Unit = { ("": Any) match { - case a @ Test => 1 + case a as Test => 1 case _ => 2 } } diff --git a/tests/run/enums-serialization-compat.scala b/tests/run/enums-serialization-compat.scala index 940e726c05a0..3dfb559429bb 100644 --- a/tests/run/enums-serialization-compat.scala +++ b/tests/run/enums-serialization-compat.scala @@ -31,19 +31,19 @@ extension (ref: AnyRef) def aliases(compare: AnyRef) = assert(ref eq compare, co val read = use(ByteArrayInputStream(buf.toByteArray)) val in = use(ObjectInputStream(read)) - val Seq(Red @ _, Green @ _, Blue @ _, Indigo @ _) = (1 to 4).map(_ => in.readObject) + val Seq(Red as _, Green as _, Blue as _, Indigo as _) = (1 to 4).map(_ => in.readObject) Red aliases JColor.Red Green aliases SColor.Green Blue aliases SColorTagged.Blue Indigo aliases SColorTagged.Indigo - val Seq(A @ _, C @ _, G @ _, T @ _) = (1 to 4).map(_ => in.readObject) + val Seq(A as _, C as _, G as _, T as _) = (1 to 4).map(_ => in.readObject) A aliases Nucleobase.A C aliases Nucleobase.C G aliases Nucleobase.G T aliases Nucleobase.T - val Seq(IntTag @ _, UnitTag @ _) = (1 to 2).map(_ => in.readObject) + val Seq(IntTag as _, UnitTag as _) = (1 to 2).map(_ => in.readObject) IntTag aliases MyClassTag.IntTag UnitTag aliases MyClassTag.UnitTag diff --git a/tests/run/fors.scala b/tests/run/fors.scala index 188f60664bbb..a7057d23ae1e 100644 --- a/tests/run/fors.scala +++ b/tests/run/fors.scala @@ -26,7 +26,7 @@ object Test extends App { var n = 0 for (_ <- xs) n += 1; println(n) for ((x, y) <- xs zip ys) print(x + " "); println() - for (p @ (x, y) <- xs zip ys) print(p._1 + " "); println() + for (p as (x, y) <- xs zip ys) print(p._1 + " "); println() // iterators for (x <- it) print(x + " "); println() @@ -53,7 +53,7 @@ object Test extends App { var n = 0 for (_ <- xs) n += 1; println(n) for ((x, y) <- xs zip ys) print(x + " "); println() - for (p @ (x, y) <- xs zip ys) print(p._1 + " "); println() + for (p as (x, y) <- xs zip ys) print(p._1 + " "); println() // iterators for (x <- it) print(x + " "); println() diff --git a/tests/run/fully-abstract-interface.scala b/tests/run/fully-abstract-interface.scala index 86156586c85d..7d05b3dc342c 100644 --- a/tests/run/fully-abstract-interface.scala +++ b/tests/run/fully-abstract-interface.scala @@ -20,7 +20,7 @@ object Test { const1 match { case AppliedOp(_, _, _) => println("test1 fail") - case c @ Constant(n) => + case c as Constant(n) => println("test1 OK") println(s"$n = ${c.eval}") } @@ -41,9 +41,9 @@ object Test { println(applied.eval) applied match { - case c @ Constant(n) => + case c as Constant(n) => println("test3 fail") - case a @ AppliedOp(op, x, y) => + case a as AppliedOp(op, x, y) => println("test3 OK") println(s"AppliedOp($op, $x, $y) = ${a.eval}") } @@ -304,7 +304,7 @@ object ListImplementation extends Arithmetic { def opClassTag: ClassTag[Op] = new ClassTag[Constant] { def runtimeClass: Class[_] = classOf[List[_]] override def unapply(x: Any): Option[List[Any]] = x match { - case op @ (("+" | "*") :: Nil) => + case op as (("+" | "*") :: Nil) => // Test that it is: // type Op <: List[Any] // List(id: "+" | "*") Some(op) diff --git a/tests/run/fully-abstract-nat-1.scala b/tests/run/fully-abstract-nat-1.scala index 2be9a62bb594..263437d33a0b 100644 --- a/tests/run/fully-abstract-nat-1.scala +++ b/tests/run/fully-abstract-nat-1.scala @@ -32,7 +32,7 @@ object Test { } def divOpt(a: Nat, b: Nat): Option[(Nat, Nat)] = b match { - case s @ Succ(_) => + case s as Succ(_) => // s is of type Nat though we know it is a Succ Some(safeDiv(a, s.asInstanceOf[Succ])) case _ => None diff --git a/tests/run/fully-abstract-nat-2.scala b/tests/run/fully-abstract-nat-2.scala index 30e34ba9b8ac..305c7805e92f 100644 --- a/tests/run/fully-abstract-nat-2.scala +++ b/tests/run/fully-abstract-nat-2.scala @@ -34,7 +34,7 @@ object Test { } def divOpt(a: Nat, b: Nat): Option[(Nat, Nat)] = b match { - case s @ Succ(_) => Some(safeDiv(a, s)) + case s as Succ(_) => Some(safeDiv(a, s)) case _ => None } diff --git a/tests/run/fully-abstract-nat-3.scala b/tests/run/fully-abstract-nat-3.scala index d4b4a37d2810..dfdf4edb4607 100644 --- a/tests/run/fully-abstract-nat-3.scala +++ b/tests/run/fully-abstract-nat-3.scala @@ -32,7 +32,7 @@ object Test { } def divOpt(a: Nat, b: Nat): Option[(Nat, Nat)] = b match { - case SuccRefine(s @ Succ(_)) => Some(safeDiv(a, s)) + case SuccRefine(s as Succ(_)) => Some(safeDiv(a, s)) case _ => None } @@ -97,7 +97,7 @@ object CaseNums extends Numbers { object SuccRefine extends SuccRefineExtractor { def unapply(nat: Nat): Option[Succ] = nat match { - case succ @ SuccClass(_) => Some(succ) + case succ as SuccClass(_) => Some(succ) case _ => None } } diff --git a/tests/run/fully-abstract-nat-4.scala b/tests/run/fully-abstract-nat-4.scala index a354c0121357..1063b41519a5 100644 --- a/tests/run/fully-abstract-nat-4.scala +++ b/tests/run/fully-abstract-nat-4.scala @@ -32,7 +32,7 @@ object Test { } def divOpt(a: Nat, b: Nat): Option[(Nat, Nat)] = b match { - case s @ Succ(p) => + case s as Succ(p) => Some(safeDiv(a, s.asInstanceOf[b.type & SuccOpt#Refined])) // safe unchecked cast inserted by the language extension case _ => None } diff --git a/tests/run/fully-abstract-nat-5.scala b/tests/run/fully-abstract-nat-5.scala index cb6142ff9016..f73f3fff6b88 100644 --- a/tests/run/fully-abstract-nat-5.scala +++ b/tests/run/fully-abstract-nat-5.scala @@ -32,7 +32,7 @@ object Test { } def divOpt(a: Nat, b: Nat): Option[(Nat, Nat)] = b match { - case s @ Succ(p) => + case s as Succ(p) => Some(safeDiv(a, s.asInstanceOf[Succ])) // cast should not be needed with extension case _ => None } diff --git a/tests/run/fully-abstract-nat-6.scala b/tests/run/fully-abstract-nat-6.scala index 14bff32961ba..ab51ff981b2f 100644 --- a/tests/run/fully-abstract-nat-6.scala +++ b/tests/run/fully-abstract-nat-6.scala @@ -32,7 +32,7 @@ object Test { } def divOpt(a: Nat, b: Nat): Option[(Nat, Nat)] = b match { - case s @ Succ(p) => + case s as Succ(p) => Some(safeDiv(a, s.asInstanceOf[Succ])) // this case will not be needed case _ => None } diff --git a/tests/run/fully-abstract-nat-7.scala b/tests/run/fully-abstract-nat-7.scala index 50ffdaa69062..1f6a6ee7c543 100644 --- a/tests/run/fully-abstract-nat-7.scala +++ b/tests/run/fully-abstract-nat-7.scala @@ -32,7 +32,7 @@ object Test { } def divOpt(a: Nat, b: Nat): Option[(Nat, Nat)] = b match { - case s @ Succ(p) => + case s as Succ(p) => Some(safeDiv(a, s.asInstanceOf[Succ])) // this case will not be needed case _ => None } diff --git a/tests/run/fully-abstract-nat.scala b/tests/run/fully-abstract-nat.scala index 16106902d3da..7bd302caef3e 100644 --- a/tests/run/fully-abstract-nat.scala +++ b/tests/run/fully-abstract-nat.scala @@ -22,7 +22,7 @@ object Test { val large = (BigInt(1) << 100).asInstanceOf[Succ] large match { case Zero() => println("test fail") - case s @ Succ(pred) => + case s as Succ(pred) => println("test OK") println(s"Succ(${pred.pred}) = $s") } @@ -52,7 +52,7 @@ object Test { three match { case Zero() => println("test3 fail") - case s @ Succ(pred) => + case s as Succ(pred) => println("test3 OK") println(s"Succ($pred) = ${s.value}") } diff --git a/tests/run/i1099.scala b/tests/run/i1099.scala index 15a428cc302b..b25fbb5bc1bf 100644 --- a/tests/run/i1099.scala +++ b/tests/run/i1099.scala @@ -8,7 +8,7 @@ object Test { // This is what `foo` expands to def foo2[T](x: Any)(implicit ev: ClassTag[T]) = x match { - case t @ ev(_) => true + case t as ev(_) => true case _ => false } def main(args: Array[String]): Unit = { diff --git a/tests/run/i1432.scala b/tests/run/i1432.scala index e71b76f8ef9d..a76889957122 100644 --- a/tests/run/i1432.scala +++ b/tests/run/i1432.scala @@ -2,8 +2,8 @@ object Test { def main(args: Array[String]): Unit = { val someFoo = Some("foo") - val _ @ bar = someFoo - val _ @ Some(baz) = someFoo + val _ as bar = someFoo + val _ as Some(baz) = someFoo println(bar) println(baz) } diff --git a/tests/run/i1463.scala b/tests/run/i1463.scala index 646e4412d4f7..aff09911d900 100644 --- a/tests/run/i1463.scala +++ b/tests/run/i1463.scala @@ -8,7 +8,7 @@ object Test { def f0(x: Any) = x match { case Bob2 => Bob2 } def f1(x: Any) = x match { case Bob => Bob } - // def f2(x: Any): Bob.type = x match { case x @ Bob => x } // should not type check + // def f2(x: Any): Bob.type = x match { case x as Bob => x } // should not type check def main(args: Array[String]): Unit = { assert(f0(Bob2) eq Bob2) diff --git a/tests/run/i1991.scala b/tests/run/i1991.scala index cec1dec89f75..54ef6819dfdc 100644 --- a/tests/run/i1991.scala +++ b/tests/run/i1991.scala @@ -14,9 +14,9 @@ class A[Foo](implicit tag: ClassTag[Foo]) { def testBind(x: Any) = x match { case foo0: Foo => (foo0: Foo) - case foo1 @ (_: Foo) => + case foo1 as (_: Foo) => (foo1: Foo) - case foo2 @ ExtractFoo() => + case foo2 as ExtractFoo() => (foo2: Foo) } } diff --git a/tests/run/i3200c.scala b/tests/run/i3200c.scala index 796e49a1040f..88bfbb1d12ef 100644 --- a/tests/run/i3200c.scala +++ b/tests/run/i3200c.scala @@ -9,7 +9,7 @@ object Test { } def test2(x: X) = x match { - case y @ (yy: Y.type) => + case y as (yy: Y.type) => yIs1(y) yIs1(yy) } diff --git a/tests/run/patmat-bind-typed.scala b/tests/run/patmat-bind-typed.scala index 10de921c5190..a8fb80d4f4e9 100644 --- a/tests/run/patmat-bind-typed.scala +++ b/tests/run/patmat-bind-typed.scala @@ -1,5 +1,5 @@ object Test { - def f(xs: List[Any]) = for (key @ (dummy: String) <- xs) yield key + def f(xs: List[Any]) = for (key as (dummy: String) <- xs) yield key def main(args: Array[String]): Unit = { f("abc" :: Nil) foreach println diff --git a/tests/run/patmat-spec.scala b/tests/run/patmat-spec.scala index b4919e205d74..5d623c4dfb35 100644 --- a/tests/run/patmat-spec.scala +++ b/tests/run/patmat-spec.scala @@ -6,7 +6,7 @@ object Test { } "even" match { - case s @ Even() => println(s"$s has an even number of characters") + case s as Even() => println(s"$s has an even number of characters") case s => println(s"$s has an odd number of characters") } // even has an even number of characters diff --git a/tests/run/patmatch-classtag.scala b/tests/run/patmatch-classtag.scala index 99e1ee3f05ae..e2701e0fdadc 100644 --- a/tests/run/patmatch-classtag.scala +++ b/tests/run/patmatch-classtag.scala @@ -38,7 +38,7 @@ object Test extends App { println(cdef) } x match { - case cdef @ CaseDef(s) => + case cdef as CaseDef(s) => val x: CaseDef = cdef println(s) } diff --git a/tests/run/t6646.scala b/tests/run/t6646.scala index b96851077bf9..327d32109a0a 100644 --- a/tests/run/t6646.scala +++ b/tests/run/t6646.scala @@ -8,8 +8,8 @@ object Test { val l = List(PrimaryKey, NoNull, lower) // withFilter must be generated in these - for (option @ NoNull <- l) println("Found " + option) - for (option @ `lower` <- l) println("Found " + option) + for (option as NoNull <- l) println("Found " + option) + for (option as `lower` <- l) println("Found " + option) for ((`lower`, i) <- l.zipWithIndex) println("Found " + i) // no withFilter diff --git a/tests/run/t8395.scala b/tests/run/t8395.scala index f2b687e2b561..77c5fff0634a 100644 --- a/tests/run/t8395.scala +++ b/tests/run/t8395.scala @@ -1,6 +1,6 @@ object Test { def baz(x: Object) = { - val s @ (_s: String) = x + val s as (_s: String) = x x } def main(args: Array[String]): Unit = { diff --git a/tests/run/unchecked-patterns.scala b/tests/run/unchecked-patterns.scala index 07539312d79f..60f41ee03402 100644 --- a/tests/run/unchecked-patterns.scala +++ b/tests/run/unchecked-patterns.scala @@ -3,7 +3,7 @@ object Test extends App { val (y1: Some[Int] @unchecked) = Some(1): Option[Int] val a :: as: @unchecked = List(1, 2, 3) - val lst @ b :: bs: @unchecked = List(1, 2, 3) + val lst as b :: bs: @unchecked = List(1, 2, 3) val (1, c): @unchecked = (1, 2) object Positive { def unapply(i: Int): Option[Int] = Some(i).filter(_ > 0) } From c9caa7e607c2540ae3e632a95c643596e19c50d3 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 24 Sep 2020 12:52:09 +0200 Subject: [PATCH 2/2] Update syntax.md --- docs/docs/internals/syntax.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/internals/syntax.md b/docs/docs/internals/syntax.md index 4c0e48c6534a..f8c2915cdf07 100644 --- a/docs/docs/internals/syntax.md +++ b/docs/docs/internals/syntax.md @@ -273,7 +273,7 @@ TypeCaseClause ::= ‘case’ InfixType ‘=>’ Type [nl] Pattern ::= Pattern1 { ‘|’ Pattern1 } Alternative(pats) Pattern1 ::= Pattern2 [‘:’ RefinedType] Bind(name, Typed(Ident(wildcard), tpe)) | ‘given’ PatVar ‘:’ RefinedType -Pattern2 ::= [id ‘@’] InfixPattern Bind(name, pat) +Pattern2 ::= [id ‘as’] InfixPattern Bind(name, pat) InfixPattern ::= SimplePattern { id [nl] SimplePattern } InfixOp(pat, op, pat) SimplePattern ::= PatVar Ident(wildcard) | Literal Bind(name, Ident(wildcard))