Skip to content

Commit 7a2cff6

Browse files
committed
Use new extension method syntax
1 parent 7475bcf commit 7a2cff6

File tree

17 files changed

+103
-74
lines changed

17 files changed

+103
-74
lines changed

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

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,16 @@ object Flags {
2222

2323
type Flag = opaques.Flag
2424

25-
given /*FlagOps*/ {
25+
given extension (x: FlagSet) with
2626

27-
def (x: FlagSet) bits: Long = opaques.toBits(x)
27+
def bits: Long = opaques.toBits(x)
2828

2929
/** The union of the given flag sets.
3030
* Combining two FlagSets with `|` will give a FlagSet
3131
* that has the intersection of the applicability to terms/types
3232
* of the two flag sets. It is checked that the intersection is not empty.
3333
*/
34-
def (x: FlagSet) | (y: FlagSet): FlagSet =
34+
def | (y: FlagSet): FlagSet =
3535
if (x.bits == 0) y
3636
else if (y.bits == 0) x
3737
else {
@@ -42,48 +42,48 @@ object Flags {
4242
}
4343

4444
/** The intersection of the given flag sets */
45-
def (x: FlagSet) & (y: FlagSet): FlagSet = FlagSet(x.bits & y.bits)
45+
def & (y: FlagSet): FlagSet = FlagSet(x.bits & y.bits)
4646

4747
/** The intersection of a flag set with the complement of another flag set */
48-
def (x: FlagSet) &~ (y: FlagSet): FlagSet = {
48+
def &~ (y: FlagSet): FlagSet = {
4949
val tbits = x.bits & KINDFLAGS
5050
if ((tbits & y.bits) == 0) x
5151
else FlagSet(tbits | ((x.bits & ~y.bits) & ~KINDFLAGS))
5252
}
5353

54-
def (x: FlagSet) ^ (y: FlagSet) =
54+
def ^ (y: FlagSet) =
5555
FlagSet((x.bits | y.bits) & KINDFLAGS | (x.bits ^ y.bits) & ~KINDFLAGS)
5656

5757
/** Does the given flag set contain the given flag?
5858
* This means that both the kind flags and the carrier bits have non-empty intersection.
5959
*/
60-
def (x: FlagSet) is (flag: Flag): Boolean = {
60+
def is (flag: Flag): Boolean = {
6161
val fs = x.bits & flag.bits
6262
(fs & KINDFLAGS) != 0 && (fs & ~KINDFLAGS) != 0
6363
}
6464

6565
/** Does the given flag set contain the given flag
6666
* and at the same time contain none of the flags in the `butNot` set?
6767
*/
68-
def (x: FlagSet) is (flag: Flag, butNot: FlagSet): Boolean = x.is(flag) && !x.isOneOf(butNot)
68+
def is (flag: Flag, butNot: FlagSet): Boolean = x.is(flag) && !x.isOneOf(butNot)
6969

7070
/** Does the given flag set have a non-empty intersection with another flag set?
7171
* This means that both the kind flags and the carrier bits have non-empty intersection.
7272
*/
73-
def (x: FlagSet) isOneOf (flags: FlagSet): Boolean = {
73+
def isOneOf (flags: FlagSet): Boolean = {
7474
val fs = x.bits & flags.bits
7575
(fs & KINDFLAGS) != 0 && (fs & ~KINDFLAGS) != 0
7676
}
7777

7878
/** Does the given flag set have a non-empty intersection with another flag set,
7979
* and at the same time contain none of the flags in the `butNot` set?
8080
*/
81-
def (x: FlagSet) isOneOf (flags: FlagSet, butNot: FlagSet): Boolean = x.isOneOf(flags) && !x.isOneOf(butNot)
81+
def isOneOf (flags: FlagSet, butNot: FlagSet): Boolean = x.isOneOf(flags) && !x.isOneOf(butNot)
8282

8383
/** Does a given flag set have all of the flags of another flag set?
8484
* Pre: The intersection of the term/type flags of both sets must be non-empty.
8585
*/
86-
def (x: FlagSet) isAllOf (flags: FlagSet): Boolean = {
86+
def isAllOf (flags: FlagSet): Boolean = {
8787
val fs = x.bits & flags.bits
8888
((fs & KINDFLAGS) != 0 || flags.bits == 0) &&
8989
(fs >>> TYPESHIFT) == (flags.bits >>> TYPESHIFT)
@@ -93,36 +93,36 @@ object Flags {
9393
* and at the same time contain none of the flags in the `butNot` set?
9494
* Pre: The intersection of the term/type flags of both sets must be non-empty.
9595
*/
96-
def (x: FlagSet) isAllOf (flags: FlagSet, butNot: FlagSet): Boolean = x.isAllOf(flags) && !x.isOneOf(butNot)
96+
def isAllOf (flags: FlagSet, butNot: FlagSet): Boolean = x.isAllOf(flags) && !x.isOneOf(butNot)
9797

98-
def (x: FlagSet) isEmpty: Boolean = (x.bits & ~KINDFLAGS) == 0
98+
def isEmpty: Boolean = (x.bits & ~KINDFLAGS) == 0
9999

100100
/** Is a given flag set a subset of another flag set? */
101-
def (x: FlagSet) <= (y: FlagSet): Boolean = (x.bits & y.bits) == x.bits
101+
def <= (y: FlagSet): Boolean = (x.bits & y.bits) == x.bits
102102

103103
/** Does the given flag set apply to terms? */
104-
def (x: FlagSet) isTermFlags: Boolean = (x.bits & TERMS) != 0
104+
def isTermFlags: Boolean = (x.bits & TERMS) != 0
105105

106106
/** Does the given flag set apply to terms? */
107-
def (x: FlagSet) isTypeFlags: Boolean = (x.bits & TYPES) != 0
107+
def isTypeFlags: Boolean = (x.bits & TYPES) != 0
108108

109109
/** The given flag set with all flags transposed to be type flags */
110-
def (x: FlagSet) toTypeFlags: FlagSet = if (x.bits == 0) x else FlagSet(x.bits & ~KINDFLAGS | TYPES)
110+
def toTypeFlags: FlagSet = if (x.bits == 0) x else FlagSet(x.bits & ~KINDFLAGS | TYPES)
111111

112112
/** The given flag set with all flags transposed to be term flags */
113-
def (x: FlagSet) toTermFlags: FlagSet = if (x.bits == 0) x else FlagSet(x.bits & ~KINDFLAGS | TERMS)
113+
def toTermFlags: FlagSet = if (x.bits == 0) x else FlagSet(x.bits & ~KINDFLAGS | TERMS)
114114

115115
/** The given flag set with all flags transposed to be common flags */
116-
def (x: FlagSet) toCommonFlags: FlagSet = if (x.bits == 0) x else FlagSet(x.bits | KINDFLAGS)
116+
def toCommonFlags: FlagSet = if (x.bits == 0) x else FlagSet(x.bits | KINDFLAGS)
117117

118118
/** The number of non-kind flags in the given flag set */
119-
def (x: FlagSet) numFlags: Int = java.lang.Long.bitCount(x.bits & ~KINDFLAGS)
119+
def numFlags: Int = java.lang.Long.bitCount(x.bits & ~KINDFLAGS)
120120

121121
/** The lowest non-kind bit set in the given flag set */
122-
def (x: FlagSet) firstBit: Int = java.lang.Long.numberOfTrailingZeros(x.bits & ~KINDFLAGS)
122+
def firstBit: Int = java.lang.Long.numberOfTrailingZeros(x.bits & ~KINDFLAGS)
123123

124124
/** The list of non-empty names of flags with given index idx that are set in the given flag set */
125-
private def (x: FlagSet) flagString(idx: Int): List[String] =
125+
private def flagString(idx: Int): List[String] =
126126
if ((x.bits & (1L << idx)) == 0) Nil
127127
else {
128128
def halfString(kind: Int) =
@@ -134,7 +134,7 @@ object Flags {
134134
}
135135

136136
/** The list of non-empty names of flags that are set in teh given flag set */
137-
def (x: FlagSet) flagStrings(privateWithin: String): Seq[String] = {
137+
def flagStrings(privateWithin: String): Seq[String] = {
138138
var rawStrings = (2 to MaxFlag).flatMap(x.flagString(_)) // DOTTY problem: cannot drop with (_)
139139
if (!privateWithin.isEmpty && !x.is(Protected))
140140
rawStrings = rawStrings :+ "private"
@@ -149,8 +149,8 @@ object Flags {
149149
}
150150

151151
/** The string representation of the given flag set */
152-
def (x: FlagSet) flagsString: String = x.flagStrings("").mkString(" ")
153-
}
152+
def flagsString: String = x.flagStrings("").mkString(" ")
153+
end given
154154

155155
def termFlagSet(x: Long) = FlagSet(TERMS | x)
156156

docs/docs/reference/contextual/relationship-implicits.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,12 @@ The synthesized type names are formed from
6161
Tuples are treated as transparent, i.e. a type `F[(X, Y)]` would get the synthesized name
6262
`F_X_Y`. Directly implemented function types `A => B` are represented as `A_to_B`. Function types used as arguments to other type constructors are represented as `Function`.
6363

64-
Anonymous given instances that define extension methods without also implementing a type
64+
Anonymous given instances that define extension methods
6565
get their name from the name of the first extension method and the toplevel type
6666
constructor of its first parameter. For example, the given instance
6767
```scala
68-
given {
69-
def (xs: List[T]) second[T] = ...
68+
given extension [T] (xs: List[T]) {
69+
def second = ...
7070
}
7171
```
7272
gets the synthesized name `given_second_of_List_T`.

docs/docs/reference/other-new-features/opaques.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@ object Logarithms {
2020
}
2121

2222
// Extension methods define opaque types' public APIs
23-
given logarithmOps: {
24-
def (x: Logarithm) toDouble: Double = math.exp(x)
25-
def (x: Logarithm) + (y: Logarithm): Logarithm = Logarithm(math.exp(x) + math.exp(y))
26-
def (x: Logarithm) * (y: Logarithm): Logarithm = Logarithm(x + y)
23+
given logarithmOps: extension (x: Logarithm) {
24+
def toDouble: Double = math.exp(x)
25+
def + (y: Logarithm): Logarithm = Logarithm(math.exp(x) + math.exp(y))
26+
def * (y: Logarithm): Logarithm = Logarithm(x + y)
2727
}
2828
}
2929
```

library/src-bootstrapped/scala/IArray.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ object opaques {
88
opaque type IArray[+T] = Array[_ <: T]
99

1010
/** Defines extension methods for immutable arrays */
11-
given arrayOps: {
11+
given arrayOps: AnyRef {
1212

1313
/** The selection operation on an immutable array.
1414
*

tests/neg/extmethod-overload.scala

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
object Test {
2-
given A: {
3-
def (x: Int) |+| (y: Int) = x + y
4-
}
5-
given B: {
6-
def (x: Int) |+| (y: String) = x + y.length
2+
given a: extension (x: Int)
3+
def |+| (y: Int) = x + y
4+
5+
given b: extension (x: Int) {
6+
def |+| (y: String) = x + y.length
77
}
88
assert((1 |+| 2) == 3) // error ambiguous
99

1010
locally {
11-
import B.|+|
11+
import b.|+|
1212
assert((1 |+| "2") == 2) // OK
1313
}
1414
}

tests/neg/i6801.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
given MyNumericOps[T]: {
2-
def (x: T) +(y: T)(given n: Numeric[T]): T = n.plus(x,y)
1+
given MyNumericOps: extension [T](x: T) {
2+
def + (y: T)(given n: Numeric[T]): T = n.plus(x,y)
33
}
44
def foo[T: Numeric](x: T) = 1f + x // error: no implicit argument of type Numeric[Any]
55
def bar[T: Numeric](x: T) = x + 1f // error: no implicit argument of type Numeric[Any]

tests/pos/i6900.scala

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,35 @@
1-
object Test {
2-
given bla[A]: { def [C](a: A) foo: C => A = _ => a }
1+
object Test1 {
2+
trait Foo[A] with
3+
def foo[C]: C => A
4+
5+
// Works with old-style conversion
6+
implicit def i2f[A](a: A): Foo[A] = new Foo[A] with
7+
def foo[C]: C => A = _ => a
8+
9+
// But not with newstyle
10+
/*
11+
given [A]: Conversion[A, Foo[A]] with
12+
def apply(a: A) = new Foo[A] with
13+
def foo[C]: C => A = _ => a
14+
*/
315

416
1.foo.foo
517
1.foo.foo[String]
618
1.foo[String].foo
719
1.foo[String].foo[String]
820
}
21+
object Test2 {
22+
23+
// Works with extension method
24+
given extension [A, C](a: A) with
25+
def foo: C => A = _ => a
26+
27+
1.foo.foo
28+
29+
// ... but have to pass 2 parameters
30+
1.foo.foo[Any => Int, String]
31+
1.foo[Int, String].foo
32+
1.foo[Int, String].foo[String => Int, String]
33+
34+
}
35+

tests/pos/i7084.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ object Test {
22

33
type Foo
44

5-
given {
6-
def (y: Any) g(given Foo): Any = ???
5+
given extension (y: Any) {
6+
def g(given Foo): Any = ???
77
}
88

99
def f(x: Any)(given Foo): Any = {

tests/pos/i7087.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ type F[T] = T match {
66
case G[a] => String
77
}
88

9-
given {
10-
def [T](tup: T) g (given Foo: F[T]) = ???
9+
given extension [T](tup: T) {
10+
def g(given Foo: F[T]) = ???
1111
}
1212

1313
def f(x: G[Int])(given Foo: String) = x.g

tests/pos/implicit-scope.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ object A {
99
type FlagSet = opaques.FlagSet
1010
def FlagSet(bits: Long): FlagSet = opaques.FlagSet(bits)
1111

12-
given {
13-
def (xs: FlagSet) bits: Long = opaques.toBits(xs)
14-
def (xs: FlagSet) | (ys: FlagSet): FlagSet = FlagSet(xs.bits | ys.bits)
12+
given extension (xs: FlagSet) {
13+
def bits: Long = opaques.toBits(xs)
14+
def | (ys: FlagSet): FlagSet = FlagSet(xs.bits | ys.bits)
1515
}
1616
}
1717

tests/pos/mirror-implicit-scope.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@ import scala.deriving._
33
object Test {
44
object K0 {
55
type Generic[T] = Mirror { type Scope = K0.type ; type MirroredType = T ; type MirroredElemTypes }
6-
given {
7-
inline def [T <: Product](gen: Generic[T]) toRepr (t: T): gen.MirroredElemTypes = Tuple.fromProduct(t).asInstanceOf
6+
given extension [T <: Product](gen: Generic[T]) {
7+
inline def toRepr (t: T): gen.MirroredElemTypes = Tuple.fromProduct(t).asInstanceOf
88
}
99
}
1010

1111
object K1 {
1212
type Generic[F[_]] = Mirror { type Scope = K1.type ; type MirroredType = F ; type MirroredElemTypes[_] }
13-
given {
14-
inline def [F[_] <: Product, T](gen: Generic[F]) toRepr (t: F[T]): gen.MirroredElemTypes[T] = Tuple.fromProduct(t).asInstanceOf
13+
given extension [F[_] <: Product, T](gen: Generic[F]) {
14+
inline def toRepr (t: F[T]): gen.MirroredElemTypes[T] = Tuple.fromProduct(t).asInstanceOf
1515
}
1616
}
1717

tests/pos/reference/opaque.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ object Logarithms {
1212
}
1313

1414
// Extension methods define opaque types' public APIs
15-
given {
16-
def (x: Logarithm) toDouble: Double = math.exp(x)
17-
def (x: Logarithm) + (y: Logarithm): Logarithm = Logarithm(math.exp(x) + math.exp(y))
18-
def (x: Logarithm) * (y: Logarithm): Logarithm = Logarithm(x + y)
15+
given extension (x: Logarithm) {
16+
def toDouble: Double = math.exp(x)
17+
def + (y: Logarithm): Logarithm = Logarithm(math.exp(x) + math.exp(y))
18+
def * (y: Logarithm): Logarithm = Logarithm(x + y)
1919
}
2020
}
2121

tests/run/extmethod-overload.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ object Test extends App {
2222
// Test with extension methods in given object
2323
object test1 {
2424

25-
given Foo: {
25+
given Foo: AnyRef {
2626
def (x: Int) |+| (y: Int) = x + y
2727
def (x: Int) |+| (y: String) = x + y.length
2828

@@ -97,8 +97,8 @@ object Test extends App {
9797
def (x: Int) yy (y: Int) = x + y
9898
}
9999

100-
given {
101-
def (x: Int) yy (y: Int) = x - y
100+
given extension (x: Int) {
101+
def yy (y: Int) = x - y
102102
}
103103

104104
import D._

tests/run/extmethods2.scala

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ object Test extends App {
22

33
class TC
44

5-
given stringListOps(given TC): {
5+
given stringListOps(given TC): Object {
66
type T = List[String]
77
def (x: T) foo (y: T) = (x ++ y, summon[TC])
88
def (x: T) bar (y: Int) = (x(0)(y), summon[TC])
@@ -16,11 +16,13 @@ object Test extends App {
1616
test(given TC())
1717

1818
object A {
19-
given listOps: [T](xs: List[T]) {
19+
given listOps: extension [T](xs: List[T]) {
2020
def second: T = xs.tail.head
2121
def third: T = xs.tail.tail.head
2222
def concat(ys: List[T]) = xs ++ ys
23-
def zipp[U](ys: List[U]): List[(T, U)] = xs.zip(ys)
23+
}
24+
given polyListOps: extension [T, U](xs: List[T]) {
25+
def zipp(ys: List[U]): List[(T, U)] = xs.zip(ys)
2426
}
2527
given extension (xs: List[Int]) {
2628
def prod = (1 /: xs)(_ * _)

tests/run/i6902.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
object Test {
2-
given [A]: { def (a: A) <<< : A = a }
3-
given { def (b: Int) <<<< : Int = b }
2+
given extension[A](a: A) { def <<< : A = a }
3+
given extension (b: Int) { def <<<< : Int = b }
44

55
def main(args: Array[String]): Unit = {
66
1.<<<

0 commit comments

Comments
 (0)