Skip to content

Commit 2abbb45

Browse files
committed
Better diagnostics for erroneous multi-line infix operations
1 parent b6b9fb9 commit 2abbb45

File tree

4 files changed

+57
-2
lines changed

4 files changed

+57
-2
lines changed

compiler/src/dotty/tools/dotc/ast/Desugar.scala

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ object desugar {
3939
*/
4040
val CheckIrrefutable: Property.Key[MatchCheck] = Property.StickyKey()
4141

42+
/** A multi-line infix operation with the infix operator starting a new line.
43+
* Used for explaining potential errors.
44+
*/
45+
val MultiLineInfix: Property.Key[Unit] = Property.StickyKey()
46+
4247
/** What static check should be applied to a Match? */
4348
enum MatchCheck {
4449
case None, Exhaustive, IrrefutablePatDef, IrrefutableGenFrom
@@ -1194,7 +1199,10 @@ object desugar {
11941199
case Tuple(args) => args.mapConserve(assignToNamedArg)
11951200
case _ => arg :: Nil
11961201
}
1197-
Apply(Select(fn, op.name).withSpan(selectPos), args)
1202+
val sel = Select(fn, op.name).withSpan(selectPos)
1203+
if (left.sourcePos.endLine < op.sourcePos.startLine)
1204+
sel.pushAttachment(MultiLineInfix, ())
1205+
Apply(sel, args)
11981206
}
11991207

12001208
if (isLeftAssoc(op.name))

compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,13 @@ trait TypeAssigner {
271271
|An extension method was tried, but could not be fully constructed:
272272
|
273273
| ${failure.tree.show.replace("\n", "\n ")}"""
274-
case _ => ""
274+
case _ =>
275+
if (tree.hasAttachment(desugar.MultiLineInfix))
276+
i""".
277+
|Note that `$name` is treated as an infix operator in Scala 3.
278+
|If you do not want that, insert a `;` or empty line in front
279+
|or drop any spaces behind the operator."""
280+
else ""
275281
}
276282
errorType(NotAMember(qualType, name, kind, addendum), tree.sourcePos)
277283
}

tests/neg/multiLineOps.scala

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
val x = 1
2+
+ 2
3+
+3 // error: Expected a toplevel definition
4+
5+
val b1 = {
6+
22
7+
* 22 // ok
8+
*/*one more*/22 // error: end of statement expected
9+
} // error: ';' expected, but '}' found
10+
11+
val b2: Boolean = {
12+
println(x)
13+
! "hello".isEmpty // error: value ! is not a member of Unit
14+
}
15+

tests/pos/multiLineOps.scala

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
val x = 1
2+
+ 2
3+
+ 3
4+
5+
class Channel {
6+
def ! (msg: String): Channel = this
7+
def send_! (msg: String): Channel = this
8+
}
9+
10+
val c = Channel()
11+
12+
def send() =
13+
c ! "hello"
14+
! "world"
15+
send_! "!"
16+
17+
val b: Boolean =
18+
"hello".isEmpty
19+
&& true &&
20+
!"hello".isEmpty
21+
22+
val b2: Boolean = {
23+
println(x)
24+
!"hello".isEmpty
25+
???
26+
}

0 commit comments

Comments
 (0)