Skip to content

Commit c880510

Browse files
committed
Check validity of infix operations
1 parent 7805293 commit c880510

File tree

2 files changed

+28
-4
lines changed

2 files changed

+28
-4
lines changed

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

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,23 @@ import rewrites.Rewrites.patch
2020
import util.Spans.Span
2121

2222
import util.SourcePosition
23+
import util.Spans.Span
24+
import rewrites.Rewrites.patch
2325
import transform.SymUtils._
26+
import transform.ValueClasses._
2427
import Decorators._
2528
import ErrorReporting.{err, errorType}
2629
import config.Printers.{typr, patmatch}
2730
import NameKinds.DefaultGetterName
31+
import SymDenotations.{NoCompleter, NoDenotation}
2832
import Applications.unapplyArgs
2933
import transform.patmat.SpaceEngine.isIrrefutableUnapply
3034

35+
3136
import collection.mutable
32-
import SymDenotations.{NoCompleter, NoDenotation}
33-
import dotty.tools.dotc.reporting.diagnostic.Message
34-
import dotty.tools.dotc.reporting.diagnostic.messages._
35-
import dotty.tools.dotc.transform.ValueClasses._
37+
import reporting.diagnostic.Message
38+
import reporting.diagnostic.messages._
39+
import scala.tasty.util.Chars.isOperatorPart
3640

3741
object Checking {
3842
import tpd._
@@ -716,6 +720,24 @@ trait Checking {
716720
i"Use of implicit conversion ${conv.showLocated}", NoSymbol, posd.sourcePos)
717721
}
718722

723+
/** Check that `tree` is a valid infix operation. That is, if the
724+
* operator is alphanumeric, it must be declared `@infix`.
725+
*/
726+
def checkValidInfix(tree: untpd.InfixOp, app: Tree)(implicit ctx: Context): Unit =
727+
tree.op match {
728+
case Ident(name: SimpleName)
729+
if !name.exists(isOperatorPart) && !app.symbol.hasAnnotation(defn.InfixAnnot) && false =>
730+
ctx.deprecationWarning(
731+
i"""alphanumeric method $name is not declared @infix; should not be used as infix operator.
732+
|The operation can be rewritten automatically under -migration -rewrite""",
733+
tree.op.sourcePos)
734+
if (ctx.scala2Mode) {
735+
patch(Span(tree.op.span.start, tree.op.span.start), "`")
736+
patch(Span(tree.op.span.end, tree.op.span.end), "`")
737+
}
738+
case _ =>
739+
}
740+
719741
/** Issue a feature warning if feature is not enabled */
720742
def checkFeature(name: TermName,
721743
description: => String,
@@ -1099,5 +1121,6 @@ trait NoChecking extends ReChecking {
10991121
override def checkNoForwardDependencies(vparams: List[ValDef])(implicit ctx: Context): Unit = ()
11001122
override def checkMembersOK(tp: Type, pos: SourcePosition)(implicit ctx: Context): Type = tp
11011123
override def checkInInlineContext(what: String, posd: Positioned)(implicit ctx: Context): Unit = ()
1124+
override def checkValidInfix(tree: untpd.InfixOp, app: Tree)(implicit ctx: Context): Unit = ()
11021125
override def checkFeature(name: TermName, description: => String, featureUseSite: Symbol, pos: SourcePosition)(implicit ctx: Context): Unit = ()
11031126
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1886,6 +1886,7 @@ class Typer extends Namer
18861886
def typedInfixOp(tree: untpd.InfixOp, pt: Type)(implicit ctx: Context): Tree = {
18871887
val untpd.InfixOp(l, op, r) = tree
18881888
val app = typedApply(desugar.binop(l, op, r), pt)
1889+
checkValidInfix(tree, app)
18891890
if (untpd.isLeftAssoc(op.name)) app
18901891
else {
18911892
val defs = new mutable.ListBuffer[Tree]

0 commit comments

Comments
 (0)