Skip to content

Commit 29082f0

Browse files
committed
Drop extension keyword
1 parent 2110158 commit 29082f0

File tree

19 files changed

+61
-51
lines changed

19 files changed

+61
-51
lines changed

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

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3322,6 +3322,22 @@ object Parsers {
33223322
Template(constr, parents, Nil, EmptyValDef, Nil)
33233323
}
33243324

3325+
/** Are the next tokens a prefix of a DefParam? */
3326+
def isDefParam() =
3327+
val lookahead = in.LookaheadScanner()
3328+
if lookahead.token == LPAREN then
3329+
lookahead.nextToken()
3330+
if lookahead.token == AT then true
3331+
else if lookahead.token == IDENTIFIER then
3332+
if lookahead.name == nme.inline then
3333+
lookahead.nextToken()
3334+
if lookahead.token == IDENTIFIER then
3335+
lookahead.nextToken()
3336+
lookahead.token == COLON
3337+
else false
3338+
else false
3339+
else false
3340+
33253341
/** OLD:
33263342
* GivenDef ::= [id] [DefTypeParamClause] GivenBody
33273343
* GivenBody ::= [‘as ConstrApp {‘,’ ConstrApp }] {GivenParamClause} [TemplateBody]
@@ -3338,11 +3354,7 @@ object Parsers {
33383354
var mods1 = addMod(mods, instanceMod)
33393355
var isExtension = false
33403356
val name =
3341-
if isIdent(nme.extension) then
3342-
in.nextToken()
3343-
isExtension = true
3344-
EmptyTermName
3345-
else if newStyle && allowOldGiven && isIdent(nme.as) then EmptyTermName
3357+
if newStyle && allowOldGiven && isIdent(nme.as) then EmptyTermName
33463358
else if isIdent then ident()
33473359
else EmptyTermName
33483360
indentRegion(name) {
@@ -3359,12 +3371,13 @@ object Parsers {
33593371
tokenSeparated(COMMA, constrApp)
33603372
else if in.token == COLON then
33613373
in.nextToken()
3362-
if isIdent(nme.extension) then
3374+
if in.token == LBRACE
3375+
|| in.token == LBRACKET
3376+
|| in.token == LPAREN && isDefParam() then
33633377
if tparams.nonEmpty then
3364-
syntaxError(i"no type parameters allowed before `extension`", tparams.head.span)
3378+
syntaxError(i"no type parameters allowed for extension", tparams.head.span)
33653379
if leadingParamss.nonEmpty then
3366-
syntaxError(i"no parameters allowed before `extension`", leadingParamss.head.head.span)
3367-
in.nextToken()
3380+
syntaxError(i"no parameters allowed for extension", leadingParamss.head.head.span)
33683381
parseParams()
33693382
Nil
33703383
else tokenSeparated(COMMA, constrApp)

docs/docs/internals/syntax.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,7 @@ ObjectDef ::= id [Template]
389389
EnumDef ::= id ClassConstr InheritClauses EnumBody EnumDef(mods, name, tparams, template)
390390
GivenDef ::= [GivenSig (‘:’ | <:)] Type ‘=’ Expr
391391
| [GivenSig ‘:’] [ConstrApp {‘,’ ConstrApp }] [TemplateBody]
392-
| ‘extension’ [id ‘:’] [ExtParamClause] TemplateBody
392+
| [id ‘:’] [ExtParamClause] TemplateBody
393393
GivenSig ::= [id] [DefTypeParamClause] {GivenParamClause}
394394
ExtParamClause ::= [DefTypeParamClause] ‘(’ DefParam ‘)’ {GivenParamClause}
395395
Template ::= InheritClauses [TemplateBody] Template(constr, parents, self, stats)

docs/docs/reference/contextual/extension-methods.md

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -84,39 +84,36 @@ So `circle.circumference` translates to `CircleOps.circumference(circle)`, provi
8484

8585
### Given Instances Defining Only Extension Methods
8686

87-
Given instances that define extension methods can also be defined without a parent clause. In this case the `given` is followed by the special identifier
88-
`extension`. E.g.,
87+
Given instances that define extension methods can also be defined without a parent clause. E.g.,
8988

9089
```scala
91-
given stringOps: extension {
90+
given stringOps: {
9291
def (xs: Seq[String]) longestStrings: Seq[String] = {
9392
val maxLength = xs.map(_.length).max
9493
xs.filter(_.length == maxLength)
9594
}
9695
}
9796

98-
given extension {
97+
given {
9998
def (xs: List[T]) second[T] = xs.tail.head
10099
}
101100
```
102-
If given extensions are anonymous (as in the second clause), their name is synthesized from the name of the first defined extension method.
103-
104-
Note: `extension` is a soft keyword, it can be used elsewhere as a normal identifier.
101+
If an extensions is anonymous (as in the second clause), its name is synthesized from the name of the first defined extension method.
105102

106103
### Given Extensions with Collective Parameters
107104

108105
If a given extension defines several extension methods one can pull out the left parameter section
109106
as well as any type parameters of these extension methods into the given instance itself.
110107
For instance, here is a given instance with two extension methods.
111108
```scala
112-
given listOps: extension {
109+
given listOps: {
113110
def (xs: List[T]) second[T]: T = xs.tail.head
114111
def (xs: List[T]) third[T]: T = xs.tail.tail.head
115112
}
116113
```
117114
The repetition in the parameters can be avoided by moving the parameters in front of the opening brace. The following version is a shorthand for the code above.
118115
```scala
119-
given listOps: extension[T](xs: List[T]) {
116+
given listOps: [T](xs: List[T]) {
120117
def second: T = xs.tail.head
121118
def third: T = xs.tail.tail.head
122119
}
@@ -176,6 +173,6 @@ Here are the required syntax extensions compared to the
176173
DefSig ::= ...
177174
| ‘(’ DefParam ‘)’ [nl] id [DefTypeParamClause] DefParamClauses
178175
GivenDef ::= ...
179-
| [id ‘:’] ‘extension’ ExtParamClause TemplateBody
176+
| [id ‘:’] [ExtParamClause] TemplateBody
180177
ExtParamClause ::= [DefTypeParamClause] ‘(’ DefParam ‘)’ {GivenParamClause}
181178
```

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ Anonymous given instances that define extension methods without also implementin
6868
get their name from the name of the first extension method and the toplevel type
6969
constructor of its first parameter. For example, the given extension
7070
```scala
71-
given extension {
71+
given {
7272
def (xs: List[T]) second[T] = ...
7373
}
7474
```

docs/docs/reference/metaprogramming/macros.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ The `toExpr` extension method is defined in package `quoted`:
251251
```scala
252252
package quoted
253253

254-
given extension {
254+
given {
255255
def (x: T) toExpr[T: Liftable] given QuoteContext: Expr[T] = summon[Liftable[T]].toExpr(x)
256256
...
257257
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ object Logarithms {
2020
}
2121

2222
// Extension methods define opaque types' public APIs
23-
given logarithmOps: extension {
23+
given logarithmOps: {
2424
def (x: Logarithm) toDouble: Double = math.exp(x)
2525
def (x: Logarithm) + (y: Logarithm): Logarithm = Logarithm(math.exp(x) + math.exp(y))
2626
def (x: Logarithm) * (y: Logarithm): Logarithm = Logarithm(x + y)

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: extension {
11+
given arrayOps: {
1212

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

tests/neg/extmethod-overload.scala

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

tests/neg/i5455.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ object Library {
1111
def toInt(n: Nat): Int = n
1212

1313
}
14-
given extension {
14+
given {
1515
def (x: Nat) * (y: Nat): Nat = x * y
1616
def (x: Nat) toInt: Int = x
1717
}

tests/pos/i7084.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ object Test {
22

33
type Foo
44

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

tests/pos/i7087.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ type F[T] = T match {
66
case G[a] => String
77
}
88

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

tests/pos/implicit-scope.scala

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

12-
given extension {
12+
given {
1313
def (xs: FlagSet) bits: Long = opaques.toBits(xs)
1414
def (xs: FlagSet) | (ys: FlagSet): FlagSet = FlagSet(xs.bits | ys.bits)
1515
}

tests/pos/mirror-implicit-scope.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@ 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 extension {
6+
given {
77
inline def (gen: Generic[T]) toRepr[T <: Product](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 extension {
13+
given {
1414
inline def (gen: Generic[F]) toRepr[F[_] <: Product, T](t: F[T]): gen.MirroredElemTypes[T] = Tuple.fromProduct(t).asInstanceOf
1515
}
1616
}

tests/pos/reference/delegates.scala

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,14 @@ object Instances extends Common {
4848
}
4949
}
5050

51-
given stringOps: extension {
51+
given stringOps: {
5252
def (xs: Seq[String]) longestStrings: Seq[String] = {
5353
val maxLength = xs.map(_.length).max
5454
xs.filter(_.length == maxLength)
5555
}
5656
}
5757

58-
given extension {
58+
given {
5959
def (xs: List[T]) second[T] = xs.tail.head
6060
}
6161

@@ -152,14 +152,14 @@ object Instances extends Common {
152152
object PostConditions {
153153
opaque type WrappedResult[T] = T
154154

155-
private given WrappedResult: extension {
155+
private given WrappedResult: {
156156
def apply[T](x: T): WrappedResult[T] = x
157157
def (x: WrappedResult[T]) unwrap[T]: T = x
158158
}
159159

160160
def result[T] given (wrapped: WrappedResult[T]): T = wrapped.unwrap
161161

162-
given extension {
162+
given {
163163
def (x: T) ensuring[T] (condition: given WrappedResult[T] => Boolean): T = {
164164
assert(condition given WrappedResult(x))
165165
x
@@ -184,14 +184,14 @@ object AnonymousInstances extends Common {
184184
}
185185
}
186186

187-
given extension {
187+
given {
188188
def (xs: Seq[String]) longestStrings: Seq[String] = {
189189
val maxLength = xs.map(_.length).max
190190
xs.filter(_.length == maxLength)
191191
}
192192
}
193193

194-
given extension {
194+
given {
195195
def (xs: List[T]) second[T] = xs.tail.head
196196
}
197197

tests/pos/reference/opaque.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ object Logarithms {
1212
}
1313

1414
// Extension methods define opaque types' public APIs
15-
given extension {
15+
given {
1616
def (x: Logarithm) toDouble: Double = math.exp(x)
1717
def (x: Logarithm) + (y: Logarithm): Logarithm = Logarithm(math.exp(x) + math.exp(y))
1818
def (x: Logarithm) * (y: Logarithm): Logarithm = Logarithm(x + y)

tests/run/extmethod-overload.scala

Lines changed: 2 additions & 2 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: extension {
25+
given Foo: {
2626
def (x: Int) |+| (y: Int) = x + y
2727
def (x: Int) |+| (y: String) = x + y.length
2828

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

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

tests/run/i6902.scala

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

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

tests/run/instances-anonymous.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@ object Test extends App {
88

99
case class Circle(x: Double, y: Double, radius: Double)
1010

11-
given extension {
11+
given {
1212
def (c: Circle) circumference: Double = c.radius * math.Pi * 2
1313
}
1414

1515
val circle = new Circle(1, 1, 2.0)
1616

1717
println(circle.circumference)
1818

19-
given extension {
19+
given {
2020
def (xs: Seq[String]) longestStrings: Seq[String] = {
2121
val maxLength = xs.map(_.length).max
2222
xs.filter(_.length == maxLength)
@@ -25,13 +25,13 @@ object Test extends App {
2525
val names = List("hi", "hello", "world")
2626
assert(names.longestStrings == List("hello", "world"))
2727

28-
given extension {
28+
given {
2929
def (xs: Seq[T]) second[T] = xs.tail.head
3030
}
3131

3232
assert(names.longestStrings.second == "world")
3333

34-
given extension {
34+
given {
3535
def (xs: List[List[T]]) flattened[T] = xs.foldLeft[List[T]](Nil)(_ ++ _)
3636
}
3737

tests/run/instances.scala

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@ object Test extends App {
88

99
case class Circle(x: Double, y: Double, radius: Double)
1010

11-
given circleOps: extension {
11+
given circleOps: {
1212
def (c: Circle) circumference: Double = c.radius * math.Pi * 2
1313
}
1414

1515
val circle = new Circle(1, 1, 2.0)
1616

1717
assert(circle.circumference == circleOps.circumference(circle))
1818

19-
given stringOps: extension {
19+
given stringOps: {
2020
def (xs: Seq[String]) longestStrings: Seq[String] = {
2121
val maxLength = xs.map(_.length).max
2222
xs.filter(_.length == maxLength)
@@ -25,18 +25,18 @@ object Test extends App {
2525
val names = List("hi", "hello", "world")
2626
assert(names.longestStrings == List("hello", "world"))
2727

28-
given seqOps: extension {
28+
given seqOps: {
2929
def (xs: Seq[T]) second[T] = xs.tail.head
3030
}
3131

3232
assert(names.longestStrings.second == "world")
3333

34-
given listListOps: extension {
34+
given listListOps: {
3535
def (xs: List[List[T]]) flattened[T] = xs.foldLeft[List[T]](Nil)(_ ++ _)
3636
}
3737

3838
// A right associative op
39-
given prepend: extension {
39+
given prepend: {
4040
def (x: T) ::[T] (xs: Seq[T]) = x +: xs
4141
}
4242
val ss: Seq[Int] = List(1, 2, 3)

0 commit comments

Comments
 (0)