Skip to content

Parse unary operators as regular identifiers when backquoted #15198

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

Merged
merged 1 commit into from
Jun 12, 2022
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
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/parsing/Parsers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2293,10 +2293,10 @@ object Parsers {
isOperator = !(location.inArgs && followingIsVararg()))

/** PrefixExpr ::= [PrefixOperator'] SimpleExpr
* PrefixOperator ::= ‘-’ | ‘+’ | ‘~’ | ‘!’
* PrefixOperator ::= ‘-’ | ‘+’ | ‘~’ | ‘!’ (if not backquoted)
*/
val prefixExpr: Location => Tree = location =>
if isIdent && nme.raw.isUnary(in.name)
if in.token == IDENTIFIER && nme.raw.isUnary(in.name)
&& in.canStartExprTokens.contains(in.lookahead.token)
then
val start = in.offset
Expand Down
2 changes: 1 addition & 1 deletion docs/_docs/internals/syntax.md
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ InfixExpr ::= PrefixExpr
| InfixExpr MatchClause
MatchClause ::= ‘match’ <<< CaseClauses >>> Match(expr, cases)
PrefixExpr ::= [PrefixOperator] SimpleExpr PrefixOp(expr, op)
PrefixOperator ::= ‘-’ | ‘+’ | ‘~’ | ‘!’
PrefixOperator ::= ‘-’ | ‘+’ | ‘~’ | ‘!’ -- unless backquoted
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment is not necessary, since the lexemes are spelled out. The spec text does say, "one of the identifiers...", so it must add, "which must not be enclosed in backquotes." (Where backquote is allowed, it must be shown in a production.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which spec are you referring to?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And do you think I should remove the comment? I think it's kind of ambiguous without it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean the spec under scala 2 https://scala-lang.org/files/archive/spec/2.13/06-expressions.html#prefix-operations

Personally, I find it more precise as it is. If it doesn't say you can use

'`' '~' '`'

then you can't, modulo bugs. Backquotes are not some metacharacter with respect to syntax. Or they are not onions, as in, "Would you like onions with that?"

However, there are two groups of consumers for the two syntax pages, so maybe they would say the comment is clarifying. I don't know which group, but hopefully they will voice their preference.

SimpleExpr ::= SimpleRef
| Literal
| ‘_’
Expand Down
2 changes: 1 addition & 1 deletion docs/_docs/reference/syntax.md
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ InfixExpr ::= PrefixExpr
| InfixExpr MatchClause
MatchClause ::= ‘match’ <<< CaseClauses >>>
PrefixExpr ::= [PrefixOperator] SimpleExpr
PrefixOperator ::= ‘-’ | ‘+’ | ‘~’ | ‘!’
PrefixOperator ::= ‘-’ | ‘+’ | ‘~’ | ‘!’ -- unless backquoted
SimpleExpr ::= SimpleRef
| Literal
| ‘_’
Expand Down
4 changes: 4 additions & 0 deletions tests/neg/unary-with-type-params.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
object Test {
def +[T](x: T): String = "x"
+[Int](6): String // error: expression expected but '[' found
}
6 changes: 6 additions & 0 deletions tests/pos/unary-with-type-params.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
object Test {
def +[T](x: T): String = "x"
`+`[Int](6): String // Parser can treat + as identifier when backquoted and followed by a type argument
`+`(6): String // Parser can treat + as identifier when backquoted and followed by a parenthesized argument
+(6): Int // Parser prioritizes + as unary when possible
}