Skip to content

Commit c259790

Browse files
committed
Drop extension keyword
1 parent 09e7268 commit c259790

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
@@ -80,39 +80,36 @@ So `circle.circumference` translates to `CircleOps.circumference(circle)`, provi
8080

8181
### Given Instances Defining Only Extension Methods
8282

83-
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
84-
`extension`. E.g.,
83+
Given instances that define extension methods can also be defined without a parent clause. E.g.,
8584

8685
```scala
87-
given stringOps: extension {
86+
given stringOps: {
8887
def (xs: Seq[String]) longestStrings: Seq[String] = {
8988
val maxLength = xs.map(_.length).max
9089
xs.filter(_.length == maxLength)
9190
}
9291
}
9392

94-
given extension {
93+
given {
9594
def (xs: List[T]) second[T] = xs.tail.head
9695
}
9796
```
98-
If given extensions are anonymous (as in the second clause), their name is synthesized from the name of the first defined extension method.
99-
100-
Note: `extension` is a soft keyword, it can be used elsewhere as a normal identifier.
97+
If an extensions is anonymous (as in the second clause), its name is synthesized from the name of the first defined extension method.
10198

10299
### Given Extensions with Collective Parameters
103100

104101
If a given extension defines several extension methods one can pull out the left parameter section
105102
as well as any type parameters of these extension methods into the given instance itself.
106103
For instance, here is a given instance with two extension methods.
107104
```scala
108-
given listOps: extension {
105+
given listOps: {
109106
def (xs: List[T]) second[T]: T = xs.tail.head
110107
def (xs: List[T]) third[T]: T = xs.tail.tail.head
111108
}
112109
```
113110
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.
114111
```scala
115-
given listOps: extension[T](xs: List[T]) {
112+
given listOps: [T](xs: List[T]) {
116113
def second: T = xs.tail.head
117114
def third: T = xs.tail.tail.head
118115
}
@@ -172,6 +169,6 @@ Here are the required syntax extensions compared to the
172169
DefSig ::= ...
173170
| ‘(’ DefParam ‘)’ [nl] id [DefTypeParamClause] DefParamClauses
174171
GivenDef ::= ...
175-
| [id ‘:’] ‘extension’ ExtParamClause TemplateBody
172+
| [id ‘:’] [ExtParamClause] TemplateBody
176173
ExtParamClause ::= [DefTypeParamClause] ‘(’ DefParam ‘)’ {GivenParamClause}
177174
```

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

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

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)