Skip to content

Commit b6ff321

Browse files
committed
Introduce infix flag
Make infix a flag instead of an annotation.
1 parent 7c5770b commit b6ff321

File tree

16 files changed

+52
-41
lines changed

16 files changed

+52
-41
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,8 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
213213
case class Inline()(implicit @constructorOnly src: SourceFile) extends Mod(Flags.Inline)
214214

215215
case class Transparent()(implicit @constructorOnly src: SourceFile) extends Mod(Flags.Transparent)
216+
217+
case class Infix()(implicit @constructorOnly src: SourceFile) extends Mod(Flags.Infix)
216218
}
217219

218220
/** Modifiers and annotations for definitions

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -357,14 +357,16 @@ object Flags {
357357
/** An opaque type alias or a class containing one */
358358
val (Opaque @ _, _, _) = newFlags(43, "opaque")
359359

360+
/** An infix method or type */
361+
val (Infix @ _, _, _) = newFlags(44, "infix")
360362

361363
// ------------ Flags following this one are not pickled ----------------------------------
362364

363365
/** Symbol is not a member of its owner */
364-
val (NonMember @ _, _, _) = newFlags(45, "<non-member>")
366+
val (NonMember @ _, _, _) = newFlags(49, "<non-member>")
365367

366368
/** Denotation is in train of being loaded and completed, used to catch cyclic dependencies */
367-
val (Touched @ _, _, _) = newFlags(48, "<touched>")
369+
val (Touched @ _, _, _) = newFlags(50, "<touched>")
368370

369371
/** Class has been lifted out to package level, local value has been lifted out to class level */
370372
val (Lifted @ _, _, _) = newFlags(51, "<lifted>")

compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -713,6 +713,7 @@ class TreePickler(pickler: TastyPickler) {
713713
if (flags.is(Synthetic)) writeModTag(SYNTHETIC)
714714
if (flags.is(Artifact)) writeModTag(ARTIFACT)
715715
if flags.is(Transparent) then writeModTag(TRANSPARENT)
716+
if flags.is(Infix) then writeModTag(INFIX)
716717
if (isTerm) {
717718
if (flags.is(Implicit)) writeModTag(IMPLICIT)
718719
if (flags.is(Given)) writeModTag(GIVEN)

compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -668,6 +668,7 @@ class TreeUnpickler(reader: TastyReader,
668668
case EXPORTED => addFlag(Exported)
669669
case OPEN => addFlag(Open)
670670
case TRANSPARENT => addFlag(Transparent)
671+
case INFIX => addFlag(Infix)
671672
case PRIVATEqualified =>
672673
readByte()
673674
privateWithin = readWithin

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2732,6 +2732,7 @@ object Parsers {
27322732
case nme.opaque => Mod.Opaque()
27332733
case nme.open => Mod.Open()
27342734
case nme.transparent => Mod.Transparent()
2735+
case nme.infix => Mod.Infix()
27352736
}
27362737
}
27372738

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,5 +288,5 @@ object Tokens extends TokensCommon {
288288

289289
final val endMarkerTokens = identifierTokens | BitSet(IF, WHILE, FOR, MATCH, TRY, NEW, GIVEN, VAL, THIS)
290290

291-
final val softModifierNames = Set(nme.inline, nme.opaque, nme.open, nme.transparent)
291+
final val softModifierNames = Set(nme.inline, nme.opaque, nme.open, nme.transparent, nme.infix)
292292
}

compiler/src/dotty/tools/dotc/transform/SymUtils.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,8 @@ object SymUtils:
241241

242242
/** Is symbol assumed or declared as an infix symbol? */
243243
def isDeclaredInfix(using Context): Boolean =
244-
self.hasAnnotation(defn.InfixAnnot)
244+
self.is(Infix)
245+
|| self.hasAnnotation(defn.InfixAnnot)
245246
|| defn.isInfix(self)
246247
|| self.name.isUnapplyName
247248
&& self.owner.is(Module)

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -786,7 +786,7 @@ trait Checking {
786786
}
787787

788788
/** Check that `tree` is a valid infix operation. That is, if the
789-
* operator is alphanumeric, it must be declared `@infix`.
789+
* operator is alphanumeric, it must be declared `infix`.
790790
*/
791791
def checkValidInfix(tree: untpd.InfixOp, meth: Symbol)(using Context): Unit = {
792792
tree.op match {
@@ -807,7 +807,7 @@ trait Checking {
807807
else
808808
("method", (n: Name) => s"method syntax .$n(...)")
809809
report.deprecationWarning(
810-
i"""Alphanumeric $kind $name is not declared @infix; it should not be used as infix operator.
810+
i"""Alphanumeric $kind $name is not declared `infix`; it should not be used as infix operator.
811811
|The operation can be rewritten automatically to `$name` under -deprecation -rewrite.
812812
|Or rewrite to ${alternative(name)} manually.""",
813813
tree.op.srcPos)

library/src/scala/compiletime/ops/package.scala

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ package object ops {
1111
* val eq3: "1" == "1" = true
1212
* ```
1313
*/
14-
@infix type ==[X, Y] <: Boolean
14+
type ==[X, Y] <: Boolean
1515

1616
/** Inequality comparison of two singleton types.
1717
* ```scala
@@ -20,7 +20,7 @@ package object ops {
2020
* val eq3: "1" != "1" = false
2121
* ```
2222
*/
23-
@infix type !=[X, Y] <: Boolean
23+
type !=[X, Y] <: Boolean
2424
}
2525

2626
object string {
@@ -29,7 +29,7 @@ package object ops {
2929
* val hello: "hello " + "world" = "hello world"
3030
* ```
3131
*/
32-
@infix type +[X <: String, Y <: String] <: String
32+
type +[X <: String, Y <: String] <: String
3333
}
3434

3535
object int {
@@ -38,95 +38,95 @@ package object ops {
3838
* val sum: 2 + 2 = 4
3939
* ```
4040
*/
41-
@infix type +[X <: Int, Y <: Int] <: Int
41+
type +[X <: Int, Y <: Int] <: Int
4242

4343
/** Subtraction of two `Int` singleton types.
4444
* ```scala
4545
* val sub: 4 - 2 = 2
4646
* ```
4747
*/
48-
@infix type -[X <: Int, Y <: Int] <: Int
48+
type -[X <: Int, Y <: Int] <: Int
4949

5050
/** Multiplication of two `Int` singleton types.
5151
* ```scala
5252
* val mul: 4 * 2 = 8
5353
* ```
5454
*/
55-
@infix type *[X <: Int, Y <: Int] <: Int
55+
type *[X <: Int, Y <: Int] <: Int
5656

5757
/** Integer division of two `Int` singleton types.
5858
* ```scala
5959
* val div: 5 / 2 = 2
6060
* ```
6161
*/
62-
@infix type /[X <: Int, Y <: Int] <: Int
62+
type /[X <: Int, Y <: Int] <: Int
6363

6464
/** Remainder of the division of `X` by `Y`.
6565
* ```scala
6666
* val mod: 5 % 2 = 1
6767
* ```
6868
*/
69-
@infix type %[X <: Int, Y <: Int] <: Int
69+
type %[X <: Int, Y <: Int] <: Int
7070

7171
/** Binary left shift of `X` by `Y`.
7272
* ```scala
7373
* val lshift: 1 << 2 = 4
7474
* ```
7575
*/
76-
@infix type <<[X <: Int, Y <: Int] <: Int
76+
type <<[X <: Int, Y <: Int] <: Int
7777

7878
/** Binary right shift of `X` by `Y`.
7979
* ```scala
8080
* val rshift: 10 >> 1 = 5
8181
* ```
8282
*/
83-
@infix type >>[X <: Int, Y <: Int] <: Int
83+
type >>[X <: Int, Y <: Int] <: Int
8484

8585
/** Binary right shift of `X` by `Y`, filling the left with zeros.
8686
* ```scala
8787
* val rshiftzero: 10 >>> 1 = 5
8888
* ```
8989
*/
90-
@infix type >>>[X <: Int, Y <: Int] <: Int
90+
type >>>[X <: Int, Y <: Int] <: Int
9191

9292
/** Bitwise xor of `X` and `Y`.
9393
* ```scala
9494
* val xor: 10 ^ 30 = 20
9595
* ```
9696
*/
97-
@infix type ^[X <: Int, Y <: Int] <: Int
97+
type ^[X <: Int, Y <: Int] <: Int
9898

9999
/** Less-than comparison of two `Int` singleton types.
100100
* ```scala
101101
* val lt1: 4 < 2 = false
102102
* val lt2: 2 < 4 = true
103103
* ```
104104
*/
105-
@infix type <[X <: Int, Y <: Int] <: Boolean
105+
type <[X <: Int, Y <: Int] <: Boolean
106106

107107
/** Greater-than comparison of two `Int` singleton types.
108108
* ```scala
109109
* val gt1: 4 > 2 = true
110110
* val gt2: 2 > 2 = false
111111
* ```
112112
*/
113-
@infix type >[X <: Int, Y <: Int] <: Boolean
113+
type >[X <: Int, Y <: Int] <: Boolean
114114

115115
/** Greater-or-equal comparison of two `Int` singleton types.
116116
* ```scala
117117
* val ge1: 4 >= 2 = true
118118
* val ge2: 2 >= 3 = false
119119
* ```
120120
*/
121-
@infix type >=[X <: Int, Y <: Int] <: Boolean
121+
type >=[X <: Int, Y <: Int] <: Boolean
122122

123123
/** Less-or-equal comparison of two `Int` singleton types.
124124
* ```scala
125125
* val lt1: 4 <= 2 = false
126126
* val lt2: 2 <= 2 = true
127127
* ```
128128
*/
129-
@infix type <=[X <: Int, Y <: Int] <: Boolean
129+
type <=[X <: Int, Y <: Int] <: Boolean
130130

131131
/** Bitwise and of `X` and `Y`.
132132
* ```scala
@@ -196,22 +196,22 @@ package object ops {
196196
* val b: false ^ true = true
197197
* ```
198198
*/
199-
@infix type ^[X <: Boolean, Y <: Boolean] <: Boolean
199+
type ^[X <: Boolean, Y <: Boolean] <: Boolean
200200

201201
/** Conjunction of two `Boolean` singleton types.
202202
* ```scala
203203
* val a: true && true = true
204204
* val b: false && true = false
205205
* ```
206206
*/
207-
@infix type &&[X <: Boolean, Y <: Boolean] <: Boolean
207+
type &&[X <: Boolean, Y <: Boolean] <: Boolean
208208

209209
/** Disjunction of two `Boolean` singleton types.
210210
* ```scala
211211
* val a: true || false = true
212212
* val b: false || false = false
213213
* ```
214214
*/
215-
@infix type ||[X <: Boolean, Y <: Boolean] <: Boolean
215+
type ||[X <: Boolean, Y <: Boolean] <: Boolean
216216
}
217217
}

scala3doc-testcases/src/tests/typesSignatures.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ class Operators
4343

4444
// Infix annotation is not well supported in Dotty
4545
// import scala.annotation.infix
46-
// @infix type op[A, B] = Int
46+
// infix type op[A, B] = Int
4747
// type Binary2 = String op Int
4848

4949
import scala.compiletime.ops.boolean._

tasty/src/dotty/tools/tasty/TastyFormat.scala

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ object TastyFormat {
255255

256256
final val header: Array[Int] = Array(0x5C, 0xA1, 0xAB, 0x1F)
257257
val MajorVersion: Int = 25
258-
val MinorVersion: Int = 0
258+
val MinorVersion: Int = 1
259259

260260
final val ASTsSection = "ASTs"
261261
final val PositionsSection = "Positions"
@@ -371,6 +371,7 @@ object TastyFormat {
371371
final val PARAMEND = 41
372372
final val PARAMalias = 42
373373
final val TRANSPARENT = 43
374+
final val INFIX = 44
374375

375376
// Cat. 2: tag Nat
376377

@@ -485,7 +486,7 @@ object TastyFormat {
485486

486487
/** Useful for debugging */
487488
def isLegalTag(tag: Int): Boolean =
488-
firstSimpleTreeTag <= tag && tag <= TRANSPARENT ||
489+
firstSimpleTreeTag <= tag && tag <= INFIX ||
489490
firstNatTreeTag <= tag && tag <= RENAMED ||
490491
firstASTTreeTag <= tag && tag <= BOUNDED ||
491492
firstNatASTTreeTag <= tag && tag <= NAMEDARG ||
@@ -515,6 +516,7 @@ object TastyFormat {
515516
| OBJECT
516517
| TRAIT
517518
| TRANSPARENT
519+
| INFIX
518520
| ENUM
519521
| LOCAL
520522
| SYNTHETIC
@@ -576,6 +578,7 @@ object TastyFormat {
576578
case OBJECT => "OBJECT"
577579
case TRAIT => "TRAIT"
578580
case TRANSPARENT => "TRANSPARENT"
581+
case INFIX => "INFIX"
579582
case ENUM => "ENUM"
580583
case LOCAL => "LOCAL"
581584
case SYNTHETIC => "SYNTHETIC"

tests/neg-custom-args/infix.scala

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
// Compile with -strict -Xfatal-warnings -deprecation
22
import scala.annotation.infix
33
class C:
4-
@infix def op(x: Int): Int = ???
4+
infix def op(x: Int): Int = ???
55
def meth(x: Int): Int = ???
66
def matching(x: Int => Int) = ???
77
def +(x: Int): Int = ???
88

99
object C:
1010
given AnyRef:
1111
extension (x: C)
12-
@infix def iop (y: Int) = ???
12+
infix def iop (y: Int) = ???
1313
def mop (y: Int) = ???
1414
def ++ (y: Int) = ???
1515

@@ -34,25 +34,25 @@ def test() = {
3434
case x => x
3535
}
3636

37-
@infix class Or[X, Y]
37+
infix class Or[X, Y]
3838
class AndC[X, Y]
39-
@infix type And[X, Y] = AndC[X, Y]
40-
@infix type &&[X, Y] = AndC[X, Y]
39+
infix type And[X, Y] = AndC[X, Y]
40+
infix type &&[X, Y] = AndC[X, Y]
4141

4242
class Map[X, Y]
4343

4444
val x1: Int Map String = ??? // error
45-
val x2: Int Or String = ??? // OK since Or is declared `@infix`
45+
val x2: Int Or String = ??? // OK since Or is declared `infix`
4646
val x3: Int AndC String = ??? // error
4747
val x4: Int `AndC` String = ??? // OK
4848
val x5: Int And String = ??? // OK
4949
val x6: Int && String = ???
5050

5151
case class Pair[T](x: T, y: T)
52-
@infix case class Q[T](x: T, y: T)
52+
infix case class Q[T](x: T, y: T)
5353

5454
object PP {
55-
@infix def unapply[T](x: Pair[T]): Option[(T, T)] = Some((x.x, x.y))
55+
infix def unapply[T](x: Pair[T]): Option[(T, T)] = Some((x.x, x.y))
5656
}
5757

5858
val p = Pair(1, 2)

tests/pos/reference/extension-methods.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ object ExtMethods:
1313

1414
extension (x: String) def < (y: String) = x.compareTo(y) < 0
1515
extension [Elem](x: Elem) def #: (xs: Seq[Elem]) = x +: xs
16-
extension (x: Number) @infix def min (y: Number) = x
16+
extension (x: Number) infix def min (y: Number) = x
1717

1818
assert("a" < "bb")
1919
val xs = 1 #: Vector(2, 3)

tests/pos/singleton-ops-dispatch.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import scala.compiletime.ops._
22
import scala.annotation.infix
33

44
object Test {
5-
@infix type +[X <: Int | String, Y <: Int | String] = (X, Y) match {
5+
infix type +[X <: Int | String, Y <: Int | String] = (X, Y) match {
66
case (Int, Int) => int.+[X, Y]
77
case (String, String) => string.+[X, Y]
88
case (String, Int) => string.+[X, int.ToString[Y]]

tests/pos/singleton-ops-test-issue-8287.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import scala.annotation.infix
33

44
object Test {
55
class Vec[S <: Int] {
6-
@infix def concat [RS <: Int](that : Vec[RS]) : Vec[S + RS] = new Vec[S + RS]
6+
infix def concat [RS <: Int](that : Vec[RS]) : Vec[S + RS] = new Vec[S + RS]
77
}
88

99
val v1 = new Vec[1]

tests/run/infix.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ import annotation.{infix, targetName}
22
object Test extends App {
33

44
case class Rational(n: Int, d: Int) {
5-
@infix def + (that: Rational) =
5+
infix def + (that: Rational) =
66
Rational(this.n * that.d + that.n * this.d, this.d * that.d)
7-
@infix @targetName("multiply") def * (that: Rational) =
7+
@targetName("multiply") infix def * (that: Rational) =
88
Rational(this.n * that.n, this.d * that.d)
99
}
1010

0 commit comments

Comments
 (0)