Skip to content

Commit

Permalink
Add migration rewrite for deprecated assignment syntax
Browse files Browse the repository at this point in the history
  • Loading branch information
WojciechMazur committed Nov 27, 2024
1 parent a4ea8bf commit 861beee
Show file tree
Hide file tree
Showing 10 changed files with 28 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ enum MigrationVersion(val warnFrom: SourceVersion, val errorFrom: SourceVersion)
case WithOperator extends MigrationVersion(`3.4`, future)
case FunctionUnderscore extends MigrationVersion(`3.4`, future)
case NonNamedArgumentInJavaAnnotation extends MigrationVersion(`3.6`, `3.6`)
case AmbiguousNamedTupleInfixApply extends MigrationVersion(`3.6`, never)
case AmbiguousNamedTupleSyntax extends MigrationVersion(`3.6`, future)
case ImportWildcard extends MigrationVersion(future, future)
case ImportRename extends MigrationVersion(future, future)
case ParameterEnclosedByParenthesis extends MigrationVersion(future, future)
Expand Down
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 @@ -1149,8 +1149,8 @@ object Parsers {
if isType then infixOp
else infixOp.right match
case Tuple(args) if args.exists(_.isInstanceOf[NamedArg]) && !isNamedTupleOperator =>
report.errorOrMigrationWarning(AmbiguousNamedTupleInfixApply(), infixOp.right.srcPos, MigrationVersion.AmbiguousNamedTupleInfixApply)
if MigrationVersion.AmbiguousNamedTupleInfixApply.needsPatch then
report.errorOrMigrationWarning(DeprecatedInfixNamedArgumentSyntax(), infixOp.right.srcPos, MigrationVersion.AmbiguousNamedTupleSyntax)
if MigrationVersion.AmbiguousNamedTupleSyntax.needsPatch then
val asApply = cpy.Apply(infixOp)(Select(opInfo.operand, opInfo.operator.name), args)
patch(source, infixOp.span, asApply.show(using ctx.withoutColors))
asApply // allow to use pre-3.6 syntax in migration mode
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala
Original file line number Diff line number Diff line change
Expand Up @@ -216,8 +216,8 @@ enum ErrorMessageID(val isActive: Boolean = true) extends java.lang.Enum[ErrorMe
case FinalLocalDefID // errorNumber: 200
case NonNamedArgumentInJavaAnnotationID // errorNumber: 201
case QuotedTypeMissingID // errorNumber: 202
case AmbiguousNamedTupleAssignmentID // errorNumber: 203
case AmbiguousNamedTupleInfixApplyID // errorNumber: 204
case DeprecatedAssignmentSyntaxID // errorNumber: 203
case DeprecatedInfixNamedArgumentSyntaxID // errorNumber: 204

def errorNumber = ordinal - 1

Expand Down
18 changes: 8 additions & 10 deletions compiler/src/dotty/tools/dotc/reporting/messages.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3344,21 +3344,19 @@ final class QuotedTypeMissing(tpe: Type)(using Context) extends StagingMessage(Q

end QuotedTypeMissing

final class AmbiguousNamedTupleAssignment(key: Name, value: untpd.Tree)(using Context) extends SyntaxMsg(AmbiguousNamedTupleAssignmentID):
final class DeprecatedAssignmentSyntax(key: Name, value: untpd.Tree)(using Context) extends SyntaxMsg(DeprecatedAssignmentSyntaxID):
override protected def msg(using Context): String =
i"""Ambiguous syntax: this is interpreted as a named tuple with one element,
i"""Deprecated syntax: in the future it would be interpreted as a named tuple with one element,
|not as an assignment.
|
|To assign a value, use curly braces: `{${key} = ${value}}`."""

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

class AmbiguousNamedTupleInfixApply()(using Context) extends SyntaxMsg(AmbiguousNamedTupleInfixApplyID):
class DeprecatedInfixNamedArgumentSyntax()(using Context) extends SyntaxMsg(DeprecatedInfixNamedArgumentSyntaxID):
def msg(using Context) =
"Ambigious syntax: this infix call argument list is interpreted as single named tuple argument, not as an named arguments list."
+ Message.rewriteNotice("This", version = SourceVersion.`3.6-migration`)
i"""Deprecated syntax: infix named arguments lists are deprecated; in the future it would be interpreted as a single name tuple argument.
|To avoid this warning, either remove the argument names or use dotted selection."""
+ Message.rewriteNotice("This", version = SourceVersion.`3.6-migration`)

def explain(using Context) =
i"""Starting with Scala 3.6 infix named arguments are interpretted as Named Tuple.
|
|To avoid this warning, either remove the argument names or use dotted selection."""
def explain(using Context) = ""
6 changes: 3 additions & 3 deletions compiler/src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3404,7 +3404,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
/** Translate tuples of all arities */
def typedTuple(tree: untpd.Tuple, pt: Type)(using Context): Tree =
val tree1 = desugar.tuple(tree, pt)
checkAmbiguousNamedTupleAssignment(tree)
checkDeprecatedAssignmentSyntax(tree)
if tree1 ne tree then typed(tree1, pt)
else
val arity = tree.trees.length
Expand Down Expand Up @@ -3433,15 +3433,15 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
/** Checks if `tree` is a named tuple with one element that could be
* interpreted as an assignment, such as `(x = 1)`. If so, issues a warning.
*/
def checkAmbiguousNamedTupleAssignment(tree: untpd.Tuple)(using Context): Unit =
def checkDeprecatedAssignmentSyntax(tree: untpd.Tuple)(using Context): Unit =
tree.trees match
case List(NamedArg(name, value)) =>
val tmpCtx = ctx.fresh.setNewTyperState()
typedAssign(untpd.Assign(untpd.Ident(name), value), WildcardType)(using tmpCtx)
if !tmpCtx.reporter.hasErrors then
// If there are no errors typing the above, then the named tuple is
// ambiguous and we issue a warning.
report.migrationWarning(AmbiguousNamedTupleAssignment(name, value), tree.srcPos)
report.migrationWarning(DeprecatedAssignmentSyntax(name, value), tree.srcPos)
case _ => ()

/** Retrieve symbol attached to given tree */
Expand Down
20 changes: 8 additions & 12 deletions tests/neg/infix-named-args.check
Original file line number Diff line number Diff line change
Expand Up @@ -14,28 +14,24 @@
-- [E204] Syntax Warning: tests/neg/infix-named-args.scala:4:15 --------------------------------------------------------
4 | def f = 42 + (x = 1) // error // werror
| ^^^^^^^
|Ambigious syntax: this infix call argument list is interpreted as single named tuple argument, not as an named arguments list.
|Deprecated syntax: infix named arguments lists are deprecated; in the future it would be interpreted as a single name tuple argument.
|To avoid this warning, either remove the argument names or use dotted selection.
|This can be rewritten automatically under -rewrite -source 3.6-migration.
|
| longer explanation available when compiling with `-explain`
-- [E204] Syntax Warning: tests/neg/infix-named-args.scala:7:26 --------------------------------------------------------
7 | def g = new C() `multi` (x = 42, y = 27) // werror
| ^^^^^^^^^^^^^^^^
|Ambigious syntax: this infix call argument list is interpreted as single named tuple argument, not as an named arguments list.
|Deprecated syntax: infix named arguments lists are deprecated; in the future it would be interpreted as a single name tuple argument.
|To avoid this warning, either remove the argument names or use dotted selection.
|This can be rewritten automatically under -rewrite -source 3.6-migration.
|
| longer explanation available when compiling with `-explain`
-- [E204] Syntax Warning: tests/neg/infix-named-args.scala:8:21 --------------------------------------------------------
8 | def h = new C() ** (x = 42, y = 27) // werror
| ^^^^^^^^^^^^^^^^
|Ambigious syntax: this infix call argument list is interpreted as single named tuple argument, not as an named arguments list.
|Deprecated syntax: infix named arguments lists are deprecated; in the future it would be interpreted as a single name tuple argument.
|To avoid this warning, either remove the argument names or use dotted selection.
|This can be rewritten automatically under -rewrite -source 3.6-migration.
|
| longer explanation available when compiling with `-explain`
-- [E204] Syntax Warning: tests/neg/infix-named-args.scala:15:18 -------------------------------------------------------
15 | def f = this ** (x = 2) // werror
| ^^^^^^^
|Ambigious syntax: this infix call argument list is interpreted as single named tuple argument, not as an named arguments list.
|Deprecated syntax: infix named arguments lists are deprecated; in the future it would be interpreted as a single name tuple argument.
|To avoid this warning, either remove the argument names or use dotted selection.
|This can be rewritten automatically under -rewrite -source 3.6-migration.
|
| longer explanation available when compiling with `-explain`
2 changes: 1 addition & 1 deletion tests/warn/21681.check
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
-- [E203] Syntax Migration Warning: tests/warn/21681.scala:5:2 ---------------------------------------------------------
5 | (age = 29) // warn
| ^^^^^^^^^^
| Ambiguous syntax: this is interpreted as a named tuple with one element,
| Deprecated syntax: in the future it would be interpreted as a named tuple with one element,
| not as an assignment.
|
| To assign a value, use curly braces: `{age = 29}`.
2 changes: 1 addition & 1 deletion tests/warn/21681b.check
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
-- [E203] Syntax Migration Warning: tests/warn/21681b.scala:5:2 --------------------------------------------------------
5 | (age = 29) // warn
| ^^^^^^^^^^
| Ambiguous syntax: this is interpreted as a named tuple with one element,
| Deprecated syntax: in the future it would be interpreted as a named tuple with one element,
| not as an assignment.
|
| To assign a value, use curly braces: `{age = 29}`.
2 changes: 1 addition & 1 deletion tests/warn/21681c.check
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
-- [E203] Syntax Migration Warning: tests/warn/21681c.scala:7:2 --------------------------------------------------------
7 | (age = 29) // warn
| ^^^^^^^^^^
| Ambiguous syntax: this is interpreted as a named tuple with one element,
| Deprecated syntax: in the future it would be interpreted as a named tuple with one element,
| not as an assignment.
|
| To assign a value, use curly braces: `{age = 29}`.
2 changes: 1 addition & 1 deletion tests/warn/21770.check
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
-- [E203] Syntax Migration Warning: tests/warn/21770.scala:7:9 ---------------------------------------------------------
7 | f(i => (cache = Some(i))) // warn
| ^^^^^^^^^^^^^^^^^
| Ambiguous syntax: this is interpreted as a named tuple with one element,
| Deprecated syntax: in the future it would be interpreted as a named tuple with one element,
| not as an assignment.
|
| To assign a value, use curly braces: `{cache = Some(i)}`.

0 comments on commit 861beee

Please sign in to comment.