diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index bf929cdd5ce7..eb17b5664e6c 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -432,6 +432,13 @@ object Parsers { def commaSeparated[T](part: () => T): List[T] = tokenSeparated(COMMA, part) + /** Is the token following the current one in `tokens`? */ + def lookaheadIn(tokens: Token*): Boolean = { + val lookahead = in.lookaheadScanner + lookahead.nextToken() + tokens.contains(lookahead.token) + } + /* --------- OPERAND/OPERATOR STACK --------------------------------------- */ var opStack: List[OpInfo] = Nil @@ -799,11 +806,7 @@ object Parsers { /** Is current ident a `*`, and is it followed by a `)` or `,`? */ def isPostfixStar: Boolean = - in.name == nme.raw.STAR && { - val lookahead = in.lookaheadScanner - lookahead.nextToken() - (lookahead.token == RPAREN || lookahead.token == COMMA) - } + in.name == nme.raw.STAR && lookaheadIn(RPAREN, COMMA) def infixTypeRest(t: Tree): Tree = infixOps(t, canStartTypeTokens, refinedType, isType = true, isOperator = !isPostfixStar) @@ -842,7 +845,7 @@ object Parsers { /** SimpleType ::= SimpleType TypeArgs * | SimpleType `#' id * | StableId - * | [‘-’ | ‘+’ | ‘~’ | ‘!’] StableId + * | ['~'] StableId * | Path `.' type * | `(' ArgTypes `)' * | `_' TypeBounds @@ -861,7 +864,7 @@ object Parsers { val start = in.skipToken() typeBounds().withPos(Position(start, in.lastOffset, start)) } - else if (isIdent && nme.raw.isUnary(in.name)) + else if (isIdent(nme.raw.TILDE) && lookaheadIn(IDENTIFIER, BACKQUOTED_IDENT)) atPos(in.offset) { PrefixOp(typeIdent(), path(thisOK = true)) } else path(thisOK = false, handleSingletonType) match { case r @ SingletonTypeTree(_) => r diff --git a/tests/pos/i3909.scala b/tests/pos/i3909.scala new file mode 100644 index 000000000000..a6e665ba9419 --- /dev/null +++ b/tests/pos/i3909.scala @@ -0,0 +1,8 @@ +class ~(x: Int) +object Test { + new ~(1) // Syntax error + new `~`(1) // Syntax error + + def ~(x: Int) = 1 + ~(1) // OK +}