Skip to content

Deprecation warnings for old syntax: alphanumeric infix operators #18925

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion compiler/src/dotty/tools/dotc/parsing/Parsers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3928,7 +3928,9 @@ object Parsers {
}

private def checkAccessOnly(mods: Modifiers, where: String): Modifiers =
val mods1 = mods & (AccessFlags | Enum)
// We allow `infix to mark the `enum`s type as infix.
// Syntax rules disallow the soft infix modifier on `case`s.
val mods1 = mods & (AccessFlags | Enum | Infix)
if mods1 ne mods then
syntaxError(em"Only access modifiers are allowed on enum $where")
mods1
Expand Down
10 changes: 6 additions & 4 deletions compiler/src/dotty/tools/dotc/typer/Checking.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1081,6 +1081,7 @@ trait Checking {
!name.isOperatorName &&
!meth.isDeclaredInfix &&
!meth.maybeOwner.is(Scala2x) &&
// TODO check is meth was compiled with 3.4+ compiler
!infixOKSinceFollowedBy(tree.right) =>
val (kind, alternative) =
if (ctx.mode.is(Mode.Type))
Expand All @@ -1089,13 +1090,14 @@ trait Checking {
("extractor", (n: Name) => s"prefix syntax $n(...)")
else
("method", (n: Name) => s"method syntax .$n(...)")
def rewriteMsg = Message.rewriteNotice("The latter", version = `future-migration`)
report.errorOrMigrationWarning(
def rewriteMsg = Message.rewriteNotice("The latter", version = `3.4-migration`)
report.gradualErrorOrMigrationWarning(
em"""Alphanumeric $kind $name is not declared ${hlAsKeyword("infix")}; it should not be used as infix operator.
|Instead, use ${alternative(name)} or backticked identifier `$name`.$rewriteMsg""",
tree.op.srcPos,
from = future)
if sourceVersion == `future-migration` then {
warnFrom = `3.4`,
errorFrom = future)
if sourceVersion.isMigrating && sourceVersion.isAtLeast(`3.4-migration`) then {
patch(Span(tree.op.span.start, tree.op.span.start), "`")
patch(Span(tree.op.span.end, tree.op.span.end), "`")
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/test-resources/repl/i1374
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
scala> implicit class Padder(val sb: StringBuilder) extends AnyVal { def pad2(width: Int) = { 1 to width - sb.length foreach { sb append '*' }; sb } }
scala> implicit class Padder(val sb: StringBuilder) extends AnyVal { infix def pad2(width: Int) = { 1 to width - sb.length foreach { sb append '*' }; sb } }
// defined class Padder
def Padder(sb: StringBuilder): Padder
scala> val greeting = new StringBuilder("Hello, kitteh!")
Expand Down
2 changes: 1 addition & 1 deletion compiler/test-resources/type-printer/infix
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def foo: (Int &: String) & Boolean
scala> def foo: Int &: (Boolean & String) = ???
def foo: Int &: (Boolean & String)
scala> import scala.annotation.showAsInfix
scala> @scala.annotation.showAsInfix class Mappy[T,U]
scala> @scala.annotation.showAsInfix infix class Mappy[T,U]
// defined class Mappy
scala> def foo: (Int Mappy Boolean) && String = ???
def foo: (Int Mappy Boolean) && String
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import PositionContext.PosCtx
class CodeMarker(val name: String) extends Embedded {

/** A range of positions between this marker and `other`. */
def to(other: CodeMarker): CodeRange = CodeRange(this, other)
infix def to(other: CodeMarker): CodeRange = CodeRange(this, other)

/** The file containing this marker. */
def file: PosCtx[TestFile] = posCtx.positionOf(this)._1
Expand Down
4 changes: 2 additions & 2 deletions scaladoc-testcases/src/tests/infixTypes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ package infixTypes
import annotation.showAsInfix

@showAsInfix
trait SomeTrait[A, B]
infix trait SomeTrait[A, B]

trait SomeTrait2[A, B]
infix trait SomeTrait2[A, B]

def someTrait1[C, D]: C SomeTrait D
= ???
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -236,9 +236,9 @@ object MemberLookup extends MemberLookup {
// Scaladoc overloading support allows terminal * (and they're meaningless)
val cleanStr = str.stripSuffix("*")

if cleanStr endsWith "$" then
if cleanStr.endsWith("$") then
Selector(cleanStr.init, SelectorKind.ForceTerm)
else if cleanStr endsWith "!" then
else if cleanStr.endsWith("!") then
Selector(cleanStr.init, SelectorKind.ForceType)
else
Selector(cleanStr, SelectorKind.NoForce)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -675,7 +675,7 @@ sealed class CharReader(buffer: String) { reader =>

var offset: Int = 0
def char: Char =
if (offset >= buffer.length) endOfText else buffer charAt offset
if (offset >= buffer.length) endOfText else buffer.charAt(offset)

final def nextChar() =
offset += 1
Expand Down Expand Up @@ -712,7 +712,7 @@ sealed class CharReader(buffer: String) { reader =>
jumpWhitespace()
val (ok0, chars0) =
if (chars.charAt(0) == ' ')
(offset > poff, chars substring 1)
(offset > poff, chars.substring(1))
else
(true, chars)
val ok = ok0 && jump(chars0)
Expand Down
2 changes: 1 addition & 1 deletion scaladoc/test/dotty/tools/scaladoc/testUtils.scala
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def tastyFiles(name: String, allowEmpty: Boolean = false, rootPck: String = "tes
}
def collectFiles(dir: File): List[File] = listFilesSafe(dir).toList.flatMap {
case f if f.isDirectory => collectFiles(f)
case f if f.getName endsWith ".tasty" => f :: Nil
case f if f.getName.endsWith(".tasty") => f :: Nil
case _ => Nil
}
val outputDir = BuildInfo.test_testcasesOutputDir
Expand Down
4 changes: 2 additions & 2 deletions tests/init-global/pos/i18628.scala
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,10 @@ trait Parsers {
}

def flatMap[U](f: T => Parser[U]): Parser[U]
= Parser{ in => this(in) flatMapWithNext(f)}
= Parser{ in => this(in).flatMapWithNext(f)}

def map[U](f: T => U): Parser[U] //= flatMap{x => success(f(x))}
= Parser{ in => this(in) map(f)}
= Parser{ in => this(in).map(f)}

def ^^ [U](f: T => U): Parser[U] = map(f)
}
Expand Down
12 changes: 6 additions & 6 deletions tests/init/pos/Properties.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ private[scala] trait PropertiesTrait {
/** The loaded properties */
protected lazy val scalaProps: java.util.Properties = {
val props = new java.util.Properties
val stream = pickJarBasedOn getResourceAsStream propFilename
val stream = pickJarBasedOn.getResourceAsStream(propFilename)
if (stream ne null)
quietlyDispose(props load stream, stream.close)
quietlyDispose(props.load(stream), stream.close)

props
}
Expand All @@ -47,8 +47,8 @@ private[scala] trait PropertiesTrait {
final def setProp(name: String, value: String) = System.setProperty(name, value)
final def clearProp(name: String) = System.clearProperty(name)

final def envOrElse(name: String, alt: String) = Option(System getenv name) getOrElse alt
final def envOrNone(name: String) = Option(System getenv name)
final def envOrElse(name: String, alt: String) = Option(System.getenv(name)) getOrElse alt
final def envOrNone(name: String) = Option(System.getenv(name))

final def envOrSome(name: String, alt: Option[String]) = envOrNone(name) orElse alt

Expand All @@ -68,7 +68,7 @@ private[scala] trait PropertiesTrait {
val releaseVersion =
for {
v <- scalaPropOrNone("maven.version.number")
if !(v endsWith "-SNAPSHOT")
if !(v.endsWith("-SNAPSHOT"))
} yield v

/** The development Scala version, if this is not a final release.
Expand All @@ -82,7 +82,7 @@ private[scala] trait PropertiesTrait {
val developmentVersion =
for {
v <- scalaPropOrNone("maven.version.number")
if v endsWith "-SNAPSHOT"
if v.endsWith("-SNAPSHOT")
ov <- scalaPropOrNone("version.number")
} yield ov

Expand Down
2 changes: 1 addition & 1 deletion tests/init/pos/i15465.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ class TestSuite:
protected val it = new ItWord

protected final class ItWord:
def should(string: String) = new ItVerbString("should", string)
infix def should(string: String) = new ItVerbString("should", string)

private def registerTestToRun(fun: => Any): Unit = ()

Expand Down
11 changes: 11 additions & 0 deletions tests/neg/alphanumeric-infix-operator-3.4.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//> using options -Werror

import language.`3.4`

class Foo:
def x(i: Int) = i
infix def y(i: Int) = i

def test(foo: Foo): Unit =
foo x 1 // error (because it was compiled with 3.4+)
foo y 2 // ok: is marked as infix
6 changes: 6 additions & 0 deletions tests/neg/alphanumeric-infix-operator.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
-- Error: tests/neg/alphanumeric-infix-operator.scala:8:6 --------------------------------------------------------------
8 | foo x 1 // error (because it was compiled with 3.4+)
| ^
| Alphanumeric method x is not declared infix; it should not be used as infix operator.
| Instead, use method syntax .x(...) or backticked identifier `x`.
| The latter can be rewritten automatically under -rewrite -source 3.4-migration.
9 changes: 9 additions & 0 deletions tests/neg/alphanumeric-infix-operator.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
//> using options -Werror

class Foo:
def x(i: Int) = i
infix def y(i: Int) = i

def test(foo: Foo): Unit =
foo x 1 // error (because it was compiled with 3.4+)
foo y 2 // ok: is marked as infix
8 changes: 4 additions & 4 deletions tests/neg/i10901.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,23 @@ object BugExp4Point2D {

// N - N
@targetName("point2DConstant")
def º(y: T2): Point2D[T1,T2] = ???
infix def º(y: T2): Point2D[T1,T2] = ???


// N - C
@targetName("point2DConstantData")
def º(y: ColumnType[T2]): Point2D[T1,T2] = ???
infix def º(y: ColumnType[T2]): Point2D[T1,T2] = ???



extension [T1:Numeric, T2:Numeric](x: ColumnType[T1])
// C - C
@targetName("point2DData")
def º(y: ColumnType[T2]): Point2D[T1,T2] = ???
infix def º(y: ColumnType[T2]): Point2D[T1,T2] = ???

// C - N
@targetName("point2DDataConstant")
def º(y: T2): Point2D[T1,T2] = ???
infix def º(y: T2): Point2D[T1,T2] = ???


}
Expand Down
10 changes: 10 additions & 0 deletions tests/neg/i18933.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
-- Error: tests/neg/i18933.scala:3:8 -----------------------------------------------------------------------------------
3 | infix case B(b: B) // error // error
| ^^^^
| end of statement expected but 'case' found
-- [E006] Not Found Error: tests/neg/i18933.scala:3:2 ------------------------------------------------------------------
3 | infix case B(b: B) // error // error
| ^^^^^
| Not found: infix
|
| longer explanation available when compiling with `-explain`
3 changes: 3 additions & 0 deletions tests/neg/i18933.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
enum Extends[A, B]:
case A(a: A)
infix case B(b: B) // error // error
6 changes: 6 additions & 0 deletions tests/neg/i2033.check
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,9 @@
6 | val out = new ObjectOutputStream(println)
| ^^^^^^^
|method println is eta-expanded even though java.io.OutputStream does not have the @FunctionalInterface annotation.
-- Warning: tests/neg/i2033.scala:7:18 ---------------------------------------------------------------------------------
7 | val arr = bos toByteArray () // error
| ^^^^^^^^^^^
| Alphanumeric method toByteArray is not declared infix; it should not be used as infix operator.
| Instead, use method syntax .toByteArray(...) or backticked identifier `toByteArray`.
| The latter can be rewritten automatically under -rewrite -source 3.4-migration.
2 changes: 1 addition & 1 deletion tests/neg/rewrite-messages.check
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@
| ^^^
| Alphanumeric method foo is not declared infix; it should not be used as infix operator.
| Instead, use method syntax .foo(...) or backticked identifier `foo`.
| The latter can be rewritten automatically under -rewrite -source future-migration.
| The latter can be rewritten automatically under -rewrite -source 3.4-migration.
6 changes: 6 additions & 0 deletions tests/neg/syntax-error-recovery.check
Original file line number Diff line number Diff line change
Expand Up @@ -136,3 +136,9 @@
| Discarded non-Unit value of type Null. You may want to use `()`.
|
| longer explanation available when compiling with `-explain`
-- Warning: tests/neg/syntax-error-recovery.scala:61:2 -----------------------------------------------------------------
61 | println(bam)
| ^^^^^^^
| Alphanumeric method println is not declared infix; it should not be used as infix operator.
| Instead, use method syntax .println(...) or backticked identifier `println`.
| The latter can be rewritten automatically under -rewrite -source 3.4-migration.
3 changes: 3 additions & 0 deletions tests/pos/alphanumeric-infix-operator-compat/A_1_c3.0.0.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
class A:
def x(i: Int) = i
infix def y(i: Int) = i
3 changes: 3 additions & 0 deletions tests/pos/alphanumeric-infix-operator-compat/B_1_c3.1.0.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
class B:
def x(i: Int) = i
infix def y(i: Int) = i
3 changes: 3 additions & 0 deletions tests/pos/alphanumeric-infix-operator-compat/C_1_c3.2.0.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
class C:
def x(i: Int) = i
infix def y(i: Int) = i
3 changes: 3 additions & 0 deletions tests/pos/alphanumeric-infix-operator-compat/D_1_c3.3.0.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
class D:
def x(i: Int) = i
infix def y(i: Int) = i
15 changes: 15 additions & 0 deletions tests/pos/alphanumeric-infix-operator-compat/Test3.4_2.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//> using options -Werror

import language.`3.4`

def test1(a: A, b: B, c: C, d: D): Unit =
a x 1 // ok: was compiled with 3.0
b x 1 // ok: was compiled with 3.1
c x 1 // ok: was compiled with 3.2
d x 1 // ok: was compiled with 3.3

// ok: is marked as infix
a y 2
b y 2
c y 2
d y 2
13 changes: 13 additions & 0 deletions tests/pos/alphanumeric-infix-operator-compat/TestFuture_2.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import language.future

def test2(a: A, b: B, c: C, d: D): Unit =
a x 1 // ok: was compiled with 3.0
b x 1 // ok: was compiled with 3.1
c x 1 // ok: was compiled with 3.2
d x 1 // ok: was compiled with 3.3

// ok: is marked as infix
a y 2
b y 2
c y 2
d y 2
4 changes: 4 additions & 0 deletions tests/pos/i18933.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
//> using options -Werror

infix enum Extends[A, B]:
case Ev[B, A <: B]() extends (A Extends B)
2 changes: 1 addition & 1 deletion tests/pos/i7424c.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//> using options -Werror
object Main extends App:
enum Extends[A, B]:
infix enum Extends[A, B]:
case Ev[B, A <: B]() extends (A Extends B)

def cast(a: A): B = this match {
Expand Down
6 changes: 6 additions & 0 deletions tests/semanticdb/metac.expect
Original file line number Diff line number Diff line change
Expand Up @@ -3460,6 +3460,7 @@ Text => empty
Language => Scala
Symbols => 12 entries
Occurrences => 33 entries
Diagnostics => 1 entries
Synthetics => 4 entries

Symbols:
Expand Down Expand Up @@ -3511,6 +3512,11 @@ Occurrences:
[20:4..20:13): scalameta -> scala/reflect/Selectable#selectDynamic().
[21:4..21:19): StructuralTypes -> example/StructuralTypes.

Diagnostics:
[14:20..14:23): [warning] Alphanumeric method foo is not declared infix; it should not be used as infix operator.
Instead, use method syntax .foo(...) or backticked identifier `foo`.
The latter can be rewritten automatically under -rewrite -source 3.4-migration.

Synthetics:
[12:2..12:6):user => reflectiveSelectable(*)
[13:2..13:6):user => reflectiveSelectable(*)
Expand Down