From eeef2602dc97f84c798713d7a2c924ea2b0d6012 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Sat, 30 Jan 2016 21:53:27 -0800 Subject: SI-8044 Allow binding backquoted varid in patterns Previously, a varid could not be backquoted, so that it was not possible to introduce variables with names such as `type` in a match expression. This commit allows backquoted varids in `case x @ _` and `case x: Int`. In neither position is a stable id accepted, that is, an id with leading uppercase. Therefore, this commit merely relaxes the backquoted varid to be taken as a normal varid in these contexts. --- spec/01-lexical-syntax.md | 2 ++ spec/08-pattern-matching.md | 4 ++-- src/compiler/scala/tools/nsc/ast/parser/Parsers.scala | 15 ++++++++------- test/files/neg/t8044.check | 4 ++++ test/files/neg/t8044.scala | 4 ++++ test/files/pos/t8044.scala | 7 +++++++ 6 files changed, 27 insertions(+), 9 deletions(-) create mode 100644 test/files/neg/t8044.check create mode 100644 test/files/neg/t8044.scala create mode 100644 test/files/pos/t8044.scala diff --git a/spec/01-lexical-syntax.md b/spec/01-lexical-syntax.md index 0232ed9a34..4e92c7cf7b 100644 --- a/spec/01-lexical-syntax.md +++ b/spec/01-lexical-syntax.md @@ -49,6 +49,8 @@ classes (Unicode general category given in parentheses): ```ebnf op ::= opchar {opchar} varid ::= lower idrest +boundvarid ::= varid + | ‘`’ varid ‘`’ plainid ::= upper idrest | varid | op diff --git a/spec/08-pattern-matching.md b/spec/08-pattern-matching.md index 3b481eea86..6753fa3ec7 100644 --- a/spec/08-pattern-matching.md +++ b/spec/08-pattern-matching.md @@ -10,10 +10,10 @@ chapter: 8 ```ebnf Pattern ::= Pattern1 { ‘|’ Pattern1 } - Pattern1 ::= varid ‘:’ TypePat + Pattern1 ::= boundvarid ‘:’ TypePat | ‘_’ ‘:’ TypePat | Pattern2 - Pattern2 ::= varid [‘@’ Pattern3] + Pattern2 ::= boundvarid [‘@’ Pattern3] | Pattern3 Pattern3 ::= SimplePattern | SimplePattern {id [nl] SimplePattern} diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index 9c0174d89b..1e239f91a6 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -1901,19 +1901,20 @@ self => } /** {{{ - * Pattern1 ::= varid `:' TypePat + * Pattern1 ::= boundvarid `:' TypePat * | `_' `:' TypePat * | Pattern2 - * SeqPattern1 ::= varid `:' TypePat + * SeqPattern1 ::= boundvarid `:' TypePat * | `_' `:' TypePat * | [SeqPattern2] * }}} */ def pattern1(): Tree = pattern2() match { case p @ Ident(name) if in.token == COLON => - if (treeInfo.isVarPattern(p)) + if (nme.isVariableName(name)) { + p.removeAttachment[BackquotedIdentifierAttachment.type] atPos(p.pos.start, in.skipToken())(Typed(p, compoundType())) - else { + } else { syntaxError(in.offset, "Pattern variables must start with a lower-case letter. (SLS 8.1.1.)") p } @@ -1921,9 +1922,9 @@ self => } /** {{{ - * Pattern2 ::= varid [ @ Pattern3 ] + * Pattern2 ::= boundvarid [ @ Pattern3 ] * | Pattern3 - * SeqPattern2 ::= varid [ @ SeqPattern3 ] + * SeqPattern2 ::= boundvarid [ @ SeqPattern3 ] * | SeqPattern3 * }}} */ @@ -1935,7 +1936,7 @@ self => case Ident(nme.WILDCARD) => in.nextToken() pattern3() - case Ident(name) if treeInfo.isVarPattern(p) => + case Ident(name) if nme.isVariableName(name) => in.nextToken() atPos(p.pos.start) { Bind(name, pattern3()) } case _ => p diff --git a/test/files/neg/t8044.check b/test/files/neg/t8044.check new file mode 100644 index 0000000000..678bf8c700 --- /dev/null +++ b/test/files/neg/t8044.check @@ -0,0 +1,4 @@ +t8044.scala:3: error: not found: value _ + def f = 42 match { case `_` : Int => `_` } // doesn't leak quoted underscore + ^ +one error found diff --git a/test/files/neg/t8044.scala b/test/files/neg/t8044.scala new file mode 100644 index 0000000000..930c30c5a5 --- /dev/null +++ b/test/files/neg/t8044.scala @@ -0,0 +1,4 @@ + +trait T { + def f = 42 match { case `_` : Int => `_` } // doesn't leak quoted underscore +} diff --git a/test/files/pos/t8044.scala b/test/files/pos/t8044.scala new file mode 100644 index 0000000000..8259f06a8a --- /dev/null +++ b/test/files/pos/t8044.scala @@ -0,0 +1,7 @@ + +trait T { + def f = 42 match { case `x` @ _ => x } + def g = 42 match { case `type` @ _ => `type` } + def h = 42 match { case `type` : Int => `type` } + def i = (null: Any) match { case _: Int | _: String => 17 } +} -- cgit v1.2.3