Skip to content

Commit 6c380b2

Browse files
committed
Make with optional in extension methods
1 parent 6dd4a99 commit 6c380b2

19 files changed

+32
-31
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3544,7 +3544,7 @@ object Parsers {
35443544
val tparams = typeParamClauseOpt(ParamOwner.Def)
35453545
val extParams = paramClause(0, prefix = true)
35463546
val givenParamss = paramClauses(givenOnly = true)
3547-
accept(WITH)
3547+
possibleTemplateStart()
35483548
if !in.isNestedStart then syntaxError("Extension without extension methods")
35493549
val templ = templateBodyOpt(makeConstructor(tparams, extParams :: givenParamss), Nil, Nil)
35503550
templ.body.foreach(checkExtensionMethod(tparams, _))

docs/docs/internals/syntax.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -389,9 +389,8 @@ GivenDef ::= [GivenSig (‘:’ | <:)] {FunArgTypes ‘=>’}
389389
| [GivenSig ‘:’] {FunArgTypes ‘=>’}
390390
ConstrApps [[‘with’] TemplateBody]
391391
GivenSig ::= [id] [DefTypeParamClause] {GivenParamClause}
392-
ExtensionDef ::= [id] ‘of’ ExtParamClause {GivenParamClause}
393-
‘with’ ExtMethods
394-
ExtMethods ::= ‘{’ ‘def’ DefDef {semi ‘def’ DefDef} ‘}’
392+
ExtensionDef ::= [id] ‘of’ ExtParamClause {GivenParamClause} ExtMethods
393+
ExtMethods ::= [nl] ‘{’ ‘def’ DefDef {semi ‘def’ DefDef} ‘}’
395394
ExtParamClause ::= [DefTypeParamClause] ‘(’ DefParam ‘)’
396395
Template ::= InheritClauses [[‘with’] TemplateBody] Template(constr, parents, self, stats)
397396
InheritClauses ::= [‘extends’ ConstrApps] [‘derives’ QualId {‘,’ QualId}]

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -128,19 +128,19 @@ A collective extension defines one or more concrete methods that have the same t
128128
and prefix parameter. Examples:
129129

130130
```scala
131-
extension stringOps of (xs: Seq[String]) with {
131+
extension stringOps of (xs: Seq[String]) {
132132
def longestStrings: Seq[String] = {
133133
val maxLength = xs.map(_.length).max
134134
xs.filter(_.length == maxLength)
135135
}
136136
}
137137

138-
extension listOps of [T](xs: List[T]) with {
138+
extension listOps of [T](xs: List[T]) {
139139
def second = xs.tail.head
140140
def third: T = xs.tail.tail.head
141141
}
142142

143-
extension of [T](xs: List[T])(given Ordering[T]) with {
143+
extension of [T](xs: List[T])(given Ordering[T]) {
144144
def largest(n: Int) = xs.sorted.takeRight(n)
145145
}
146146
```
@@ -176,6 +176,6 @@ DefSig ::= ...
176176
ExtParamClause ::= [DefTypeParamClause] ‘(’ DefParam ‘)’
177177
TmplDef ::= ...
178178
| ‘extension’ ExtensionDef
179-
ExtensionDef ::= [id] ‘of’ ExtParamClause {GivenParamClause} ‘with’ ExtMethods
179+
ExtensionDef ::= [id] ‘of’ ExtParamClause {GivenParamClause} ExtMethods
180180
ExtMethods ::= ‘{’ ‘def’ DefDef {semi ‘def’ DefDef} ‘}’
181181
```

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ Anonymous collective extensions also get compiler synthesized names, which are f
7272

7373
For example, the extension
7474
```scala
75-
extension of [T] (xs: List[T]) with {
75+
extension of [T] (xs: List[T]) {
7676
def second = ...
7777
}
7878
```

tests/neg/extension-methods.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ object Test {
1010
"".l2 // error
1111
1.l1 // error
1212

13-
extension of [T](xs: List[T]) with {
13+
extension of [T](xs: List[T]) {
1414
def (x: Int).f1: T = ??? // error: No extension method allowed here, since collective parameters are given
1515
def f2[T]: T = ??? // error: T is already defined as type T
1616
def f3(xs: List[T]) = ??? // error: xs is already defined as value xs

tests/neg/extmethod-overload.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
object Test {
2-
extension a of (x: Int) with
2+
extension a of (x: Int) {
33
def |+| (y: Int) = x + y
4+
}
45

5-
extension b of (x: Int) with {
6+
extension b of (x: Int) {
67
def |+| (y: String) = x + y.length
78
}
89
assert((1 |+| 2) == 3) // error ambiguous

tests/neg/i5455.scala

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

1313
}
14-
extension of (x: Nat) with
14+
extension of (x: Nat) {
1515
def * (y: Nat): Nat = x * y
1616
def toInt: Int = x
17+
}
1718
}
1819

1920
object User extends App {

tests/neg/i6801.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
extension myNumericOps of [T](x: T) with {
1+
extension myNumericOps of [T](x: T) {
22
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]

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-
extension of (y: Any) with {
5+
extension of (y: Any) {
66
def 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-
extension of [T](tup: T) with {
9+
extension of [T](tup: T) {
1010
def g(given Foo: F[T]) = ???
1111
}
1212

0 commit comments

Comments
 (0)