Skip to content

Commit c55f2cd

Browse files
committed
Disallow exports of extension methods in extension methods
Revert "Add note on export of extensions" This reverts commit 77447c8.
1 parent 2afffcc commit c55f2cd

File tree

3 files changed

+21
-37
lines changed

3 files changed

+21
-37
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1114,6 +1114,8 @@ class Namer { typer: Typer =>
11141114
Skip
11151115
else if pathMethod.exists && mbr.isType then
11161116
No("is a type, so it cannot be exported as extension method")
1117+
else if pathMethod.exists && sym.is(ExtensionMethod) then
1118+
No("is already an extension method, cannot be exported into another one")
11171119
else
11181120
Yes
11191121
}

docs/_docs/reference/other-new-features/export.md

Lines changed: 3 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -162,11 +162,9 @@ extension (x: String)
162162
private def moreOps = new StringOps(x)
163163
export moreOps.*
164164
```
165-
In this case the qualifier expression must be an identifier that refers to a unique parameterless extension method in the same extension clause.
166-
167-
An export will then create extension methods for all accessible term members,
168-
matching the selectors, in the result of the qualifier path.
169-
For instance, the extension above would be expanded to
165+
In this case the qualifier expression must be an identifier that refers to a unique parameterless extension method in the same extension clause. The export will create
166+
extension methods for all accessible term members
167+
in the result of the qualifier path. For instance, the extension above would be expanded to
170168
```scala
171169
extension (x: String)
172170
def take(n: Int): String = x.substring(0, n)
@@ -176,38 +174,6 @@ extension (x: String)
176174
def capitalize: String = moreOps.capitalize
177175
```
178176

179-
### A Note on Exporting Extension Methods
180-
**Note:** extension methods can have surprising results if exported from within an extension (i.e. they
181-
are exported as-if they were an ordinary method). Observe the following example:
182-
```scala
183-
class StringOps:
184-
extension (x: String) def capitalize: String = ...
185-
def zero: String = ""
186-
187-
extension (s: String)
188-
private def moreOps = new StringOps()
189-
export moreOps.*
190-
```
191-
this would be expanded to
192-
```scala
193-
extension (s: String)
194-
private def moreOps = new StringOps()
195-
def capitalize(x: String): String = moreOps.capitalize(x)
196-
...
197-
```
198-
observe the extra String parameter on `capitalize`.
199-
It is instead recommended to export extension methods from
200-
outside of an extension, and to use a renaming selector to avoid them, e.g.:
201-
```scala
202-
private val myStringOps = new StringOps()
203-
204-
extension (s: String)
205-
private def moreOps = myStringOps
206-
export moreOps.{capitalize as _, *}
207-
208-
export myStringOps.capitalize
209-
```
210-
211177
## Syntax changes:
212178

213179
```
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
class StringOps:
2+
extension (x: String)
3+
def capitalize: String = ???
4+
def foo: String = ???
5+
6+
def foo: String = ???
7+
8+
9+
extension (s: String)
10+
private def moreOps = new StringOps()
11+
export moreOps.capitalize // error: no eligible member capitalize at moreOps
12+
13+
extension (s: String)
14+
private def moreOps2= new StringOps()
15+
export moreOps2.foo // OK
16+

0 commit comments

Comments
 (0)