Skip to content

Commit efbb347

Browse files
committed
Don't assume leading infix if next line is indented less
Don't assume that an operator `op` is a leading infix operator if `op` appears on its own line, and next line is indented less. Fixes #12395
1 parent 69c800b commit efbb347

File tree

3 files changed

+20
-5
lines changed

3 files changed

+20
-5
lines changed

Diff for: compiler/src/dotty/tools/dotc/parsing/Scanners.scala

+5-1
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,8 @@ object Scanners {
369369
* - it does not follow a blank line, and
370370
* - it is followed by at least one whitespace character and a
371371
* token that can start an expression.
372+
* - if the operator appears on its own line, the next line must have at least
373+
* the same indentation width as the operator. See pos/i12395 for a test where this matters.
372374
* If a leading infix operator is found and the source version is `3.0-migration`, emit a change warning.
373375
*/
374376
def isLeadingInfixOperator(nextWidth: IndentWidth = indentWidth(offset), inConditional: Boolean = true) =
@@ -397,7 +399,9 @@ object Scanners {
397399
// force a NEWLINE a after current token if it is on its own line
398400
lookahead.nextToken()
399401
assumeStartsExpr(lookahead)
400-
|| lookahead.token == NEWLINE && assumeStartsExpr(lookahead.next)
402+
|| lookahead.token == NEWLINE
403+
&& assumeStartsExpr(lookahead.next)
404+
&& indentWidth(offset) <= indentWidth(lookahead.next.offset)
401405
}
402406
&& {
403407
currentRegion match

Diff for: docs/docs/reference/changed-features/operators.md

+6-4
Original file line numberDiff line numberDiff line change
@@ -128,10 +128,12 @@ would have treated the continuations `++ " world"` or `|| xs.isEmpty` as separat
128128

129129
To make this syntax work, the rules are modified to not infer semicolons in front of leading infix operators.
130130
A _leading infix operator_ is
131-
- a symbolic identifier such as `+`, or `approx_==`, or an identifier in backticks,
132-
- that starts a new line,
133-
- that precedes a token on the same or the next line that can start an expression,
134-
- and that is immediately followed by at least one whitespace character.
131+
- a symbolic identifier such as `+`, or `approx_==`, or an identifier in backticks that
132+
- starts a new line, and
133+
- is not following a blank line, and
134+
- is followed by at least one whitespace character and a token that can start an expression.
135+
- Furthermore, if the operator appears on its own line, the next line must have at least
136+
the same indentation width as the operator.
135137

136138
Example:
137139

Diff for: tests/pos/i12395.scala

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
@main def main : Unit =
2+
val x = 1
3+
4+
val y = x match
5+
case 1 => 1
6+
case _ =>
7+
println("bad")
8+
???
9+
println(x)

0 commit comments

Comments
 (0)