Skip to content

Commit d08277f

Browse files
committed
Restore infix named args deprecated syntax detection and migration. Now it only works with -source:3.7-migration, since NamedTuples are stable feature and we don't have ignore experimenal.NamedTuples feature switch
1 parent 0bdf644 commit d08277f

File tree

9 files changed

+106
-3
lines changed

9 files changed

+106
-3
lines changed

compiler/src/dotty/tools/dotc/core/StdNames.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -669,6 +669,7 @@ object StdNames {
669669
val readResolve: N = "readResolve"
670670
val zero: N = "zero"
671671
val zip: N = "zip"
672+
val `++` : N = "++"
672673
val nothingRuntimeClass: N = "scala.runtime.Nothing$"
673674
val nullRuntimeClass: N = "scala.runtime.Null$"
674675

compiler/src/dotty/tools/dotc/parsing/Parsers.scala

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1137,15 +1137,39 @@ object Parsers {
11371137
if (prec < opPrec || leftAssoc && prec == opPrec) {
11381138
opStack = opStack.tail
11391139
recur {
1140-
atSpan(opInfo.operator.span union opInfo.operand.span union top.span):
1141-
InfixOp(opInfo.operand, opInfo.operator, top)
1140+
migrateInfixOp(opInfo, isType):
1141+
atSpan(opInfo.operator.span union opInfo.operand.span union top.span):
1142+
InfixOp(opInfo.operand, opInfo.operator, top)
11421143
}
11431144
}
11441145
else top
11451146
}
11461147
recur(top)
11471148
}
11481149

1150+
private def migrateInfixOp(opInfo: OpInfo, isType: Boolean)(infixOp: InfixOp): Tree = {
1151+
def isNamedTupleOperator = opInfo.operator.name match
1152+
case nme.EQ | nme.NE | nme.eq | nme.ne | nme.`++` | nme.zip => true
1153+
case _ => false
1154+
if isType then infixOp
1155+
else infixOp.right match
1156+
case Tuple(args) if args.exists(_.isInstanceOf[NamedArg]) && !isNamedTupleOperator =>
1157+
report.errorOrMigrationWarning(DeprecatedInfixNamedArgumentSyntax(), infixOp.right.srcPos, MigrationVersion.AmbiguousNamedTupleSyntax)
1158+
if MigrationVersion.AmbiguousNamedTupleSyntax.needsPatch then
1159+
val asApply = cpy.Apply(infixOp)(Select(opInfo.operand, opInfo.operator.name), args)
1160+
patch(source, infixOp.span, asApply.show(using ctx.withoutColors))
1161+
asApply // allow to use pre-3.6 syntax in migration mode
1162+
else infixOp
1163+
case Parens(assign @ Assign(ident, value)) if !isNamedTupleOperator =>
1164+
report.errorOrMigrationWarning(DeprecatedInfixNamedArgumentSyntax(), infixOp.right.srcPos, MigrationVersion.AmbiguousNamedTupleSyntax)
1165+
if MigrationVersion.AmbiguousNamedTupleSyntax.needsPatch then
1166+
val asApply = cpy.Apply(infixOp)(Select(opInfo.operand, opInfo.operator.name), assign :: Nil)
1167+
patch(source, infixOp.span, asApply.show(using ctx.withoutColors))
1168+
asApply // allow to use pre-3.6 syntax in migration mode
1169+
else infixOp
1170+
case _ => infixOp
1171+
}
1172+
11491173
/** True if we are seeing a lambda argument after a colon of the form:
11501174
* : (params) =>
11511175
* body

compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ enum ErrorMessageID(val isActive: Boolean = true) extends java.lang.Enum[ErrorMe
217217
case NonNamedArgumentInJavaAnnotationID // errorNumber: 201
218218
case QuotedTypeMissingID // errorNumber: 202
219219
case DeprecatedAssignmentSyntaxID // errorNumber: 203
220-
case DeprecatedInfixNamedArgumentSyntaxID // errorNumber: 204 // no longer emmited
220+
case DeprecatedInfixNamedArgumentSyntaxID // errorNumber: 204
221221
case GivenSearchPriorityID // errorNumber: 205
222222
case EnumMayNotBeValueClassesID // errorNumber: 206
223223
case IllegalUnrollPlacementID // errorNumber: 207

compiler/src/dotty/tools/dotc/reporting/messages.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3370,6 +3370,14 @@ final class DeprecatedAssignmentSyntax(key: Name, value: untpd.Tree)(using Conte
33703370

33713371
override protected def explain(using Context): String = ""
33723372

3373+
class DeprecatedInfixNamedArgumentSyntax()(using Context) extends SyntaxMsg(DeprecatedInfixNamedArgumentSyntaxID):
3374+
def msg(using Context) =
3375+
i"""Deprecated syntax: infix named arguments lists are deprecated; since 3.7 it is interpreted as a single name tuple argument.
3376+
|To avoid this warning, either remove the argument names or use dotted selection."""
3377+
+ Message.rewriteNotice("This", version = SourceVersion.`3.7-migration`)
3378+
3379+
def explain(using Context) = ""
3380+
33733381
class GivenSearchPriorityWarning(
33743382
pt: Type,
33753383
cmp: Int,

compiler/test/dotty/tools/dotc/CompilationTests.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ class CompilationTests {
7979
compileFile("tests/rewrites/i20002.scala", defaultOptions.and("-indent", "-rewrite")),
8080
compileDir("tests/rewrites/annotation-named-pararamters", defaultOptions.and("-rewrite", "-source:3.6-migration")),
8181
compileFile("tests/rewrites/i21418.scala", unindentOptions.and("-rewrite", "-source:3.5-migration")),
82+
compileFile("tests/rewrites/infix-named-args.scala", defaultOptions.and("-rewrite", "-source:3.7-migration")),
8283
compileFile("tests/rewrites/ambiguous-named-tuple-assignment.scala", defaultOptions.and("-rewrite", "-source:3.6-migration")),
8384
compileFile("tests/rewrites/i21382.scala", defaultOptions.and("-indent", "-rewrite")),
8485
compileFile("tests/rewrites/unused.scala", defaultOptions.and("-rewrite", "-Wunused:all")),

tests/neg/infix-named-args.check

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,27 @@
1111
| (x: Byte): Int
1212
| (x: String): String
1313
| match arguments ((x : Int)) (a named tuple)
14+
-- [E204] Syntax Warning: tests/neg/infix-named-args.scala:2:15 --------------------------------------------------------
15+
2 | def f = 42 + (x = 1) // error // werror
16+
| ^^^^^^^
17+
|Deprecated syntax: infix named arguments lists are deprecated; since 3.7 it is interpreted as a single name tuple argument.
18+
|To avoid this warning, either remove the argument names or use dotted selection.
19+
|This can be rewritten automatically under -rewrite -source 3.6-migration.
20+
-- [E204] Syntax Warning: tests/neg/infix-named-args.scala:5:26 --------------------------------------------------------
21+
5 | def g = new C() `multi` (x = 42, y = 27) // werror
22+
| ^^^^^^^^^^^^^^^^
23+
|Deprecated syntax: infix named arguments lists are deprecated; since 3.7 it is interpreted as a single name tuple argument.
24+
|To avoid this warning, either remove the argument names or use dotted selection.
25+
|This can be rewritten automatically under -rewrite -source 3.6-migration.
26+
-- [E204] Syntax Warning: tests/neg/infix-named-args.scala:6:21 --------------------------------------------------------
27+
6 | def h = new C() ** (x = 42, y = 27) // werror
28+
| ^^^^^^^^^^^^^^^^
29+
|Deprecated syntax: infix named arguments lists are deprecated; since 3.7 it is interpreted as a single name tuple argument.
30+
|To avoid this warning, either remove the argument names or use dotted selection.
31+
|This can be rewritten automatically under -rewrite -source 3.6-migration.
32+
-- [E204] Syntax Warning: tests/neg/infix-named-args.scala:13:18 -------------------------------------------------------
33+
13 | def f = this ** (x = 2) // werror
34+
| ^^^^^^^
35+
|Deprecated syntax: infix named arguments lists are deprecated; since 3.7 it is interpreted as a single name tuple argument.
36+
|To avoid this warning, either remove the argument names or use dotted selection.
37+
|This can be rewritten automatically under -rewrite -source 3.6-migration.

tests/rewrites/infix-named-args.check

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
class C:
2+
def multi(x: Int, y: Int): Int = x + y
3+
def **(x: Int, y: Int): Int = x + y
4+
def g = new C().multi(x = 42, y = 27)
5+
def h = new C().**(x = 42, y = 27)
6+
7+
type X = (x: Int)
8+
9+
class D(d: Int):
10+
def **(x: Int): Int = d * x
11+
def **(x: X): Int = d * x.x
12+
def f = this.**(x = 2)
13+
def g = this ** 2
14+
def h = this ** ((x = 2))
15+
def i = this.**(x = (1 + 1))

tests/rewrites/infix-named-args.scala

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
class C:
2+
def multi(x: Int, y: Int): Int = x + y
3+
def **(x: Int, y: Int): Int = x + y
4+
def g = new C() `multi` (x = 42, y = 27)
5+
def h = new C() ** (x = 42, y = 27)
6+
7+
type X = (x: Int)
8+
9+
class D(d: Int):
10+
def **(x: Int): Int = d * x
11+
def **(x: X): Int = d * x.x
12+
def f = this ** (x = 2)
13+
def g = this ** 2
14+
def h = this ** ((x = 2))
15+
def i = this ** (x = (1 + 1))
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//> using options -source:3.7-migration
2+
3+
class C:
4+
def f = 42 + (x = 1) // warn // interpreted as 42.+(x = 1) under migration, x is a valid synthetic parameter name
5+
def multi(x: Int, y: Int): Int = x + y
6+
def **(x: Int, y: Int): Int = x + y
7+
def g = new C() `multi` (x = 42, y = 27) // warn
8+
def h = new C() ** (x = 42, y = 27) // warn
9+
10+
type X = (x: Int)
11+
12+
class D(d: Int):
13+
def **(x: Int): Int = d * x
14+
def f = this ** (x = 2) // warn
15+
def g = this ** 2

0 commit comments

Comments
 (0)