Skip to content

Commit e2e169c

Browse files
committed
fix scala#9704: take renaming into account with exports
1 parent 9ec34f8 commit e2e169c

File tree

5 files changed

+63
-28
lines changed

5 files changed

+63
-28
lines changed

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

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -949,26 +949,28 @@ class Namer { typer: Typer =>
949949
lazy val wildcardBound = importBound(selectors, isGiven = false)
950950
lazy val givenBound = importBound(selectors, isGiven = true)
951951

952-
def whyNoForwarder(mbr: SingleDenotation): String = {
952+
def whyNoForwarder(mbr: SingleDenotation, isSameName: Boolean): String = {
953953
val sym = mbr.symbol
954-
if (!sym.isAccessibleFrom(path.tpe)) "is not accessible"
955-
else if (sym.isConstructor || sym.is(ModuleClass) || sym.is(Bridge)) SKIP
956-
else if (cls.derivesFrom(sym.owner) &&
957-
(sym.owner == cls || !sym.is(Deferred))) i"is already a member of $cls"
958-
else if (sym.is(Override))
959-
sym.allOverriddenSymbols.find(
960-
other => cls.derivesFrom(other.owner) && !other.is(Deferred)) match {
961-
case Some(other) => i"overrides ${other.showLocated}, which is already a member of $cls"
962-
case None => ""
963-
}
954+
if !sym.isAccessibleFrom(path.tpe) then "is not accessible"
955+
else if sym.isConstructor || sym.is(ModuleClass) || sym.is(Bridge) then SKIP
956+
else if isSameName then
957+
if cls.derivesFrom(sym.owner) && (sym.owner == cls || !sym.is(Deferred)) then
958+
i"is already a member of $cls"
959+
else if sym.is(Override) then
960+
sym.allOverriddenSymbols.find(
961+
other => cls.derivesFrom(other.owner) && !other.is(Deferred)) match {
962+
case Some(other) => i"overrides ${other.showLocated}, which is already a member of $cls"
963+
case None => ""
964+
}
965+
else ""
964966
else ""
965967
}
966968

967969
/** Add a forwarder with name `alias` or its type name equivalent to `mbr`,
968970
* provided `mbr` is accessible and of the right implicit/non-implicit kind.
969971
*/
970-
def addForwarder(alias: TermName, mbr: SingleDenotation, span: Span): Unit =
971-
if (whyNoForwarder(mbr) == "") {
972+
def addForwarder(alias: TermName, isSameName: Boolean, mbr: SingleDenotation, span: Span): Unit =
973+
if (whyNoForwarder(mbr, isSameName) == "") {
972974
val sym = mbr.symbol
973975
val forwarder =
974976
if mbr.isType then
@@ -1017,9 +1019,10 @@ class Namer { typer: Typer =>
10171019
def addForwardersNamed(name: TermName, alias: TermName, span: Span): Unit = {
10181020
val size = buf.size
10191021
val mbrs = List(name, name.toTypeName, name.toExtensionName).flatMap(path.tpe.member(_).alternatives)
1020-
mbrs.foreach(addForwarder(alias, _, span))
1022+
val isSameName = name == alias
1023+
mbrs.foreach(addForwarder(alias, isSameName, _, span))
10211024
if (buf.size == size) {
1022-
val reason = mbrs.map(whyNoForwarder).dropWhile(_ == SKIP) match {
1025+
val reason = mbrs.map(whyNoForwarder(_, isSameName)).dropWhile(_ == SKIP) match {
10231026
case Nil => ""
10241027
case why :: _ => i"\n$path.$name cannot be exported because it $why"
10251028
}
@@ -1035,7 +1038,7 @@ class Namer { typer: Typer =>
10351038
val alias = mbr.name.toTermName
10361039
if !seen.contains(alias)
10371040
&& mbr.matchesImportBound(if mbr.symbol.is(Given) then givenBound else wildcardBound)
1038-
then addForwarder(alias, mbr, span)
1041+
then addForwarder(alias, isSameName = true, mbr, span)
10391042

10401043
def addForwarders(sels: List[untpd.ImportSelector], seen: List[TermName]): Unit = sels match
10411044
case sel :: sels1 =>

tests/neg/exports.check

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,19 +33,21 @@
3333
| final def status: => List[String] in class Copier at line 24 and
3434
| final def status: => List[String] in class Copier at line 26
3535
| have the same type after erasure.
36-
-- Error: tests/neg/exports.scala:35:24 --------------------------------------------------------------------------------
37-
35 | export this.{concat => ++} // error: no eligible member
38-
| ^^^^^^^^^^^^
39-
| no eligible member concat at this
40-
| this.concat cannot be exported because it is already a member of trait IterableOps
41-
-- Error: tests/neg/exports.scala:41:15 --------------------------------------------------------------------------------
42-
41 | export foo.foo // error: no eligible member
36+
-- [E120] Naming Error: tests/neg/exports.scala:42:24 ------------------------------------------------------------------
37+
42 | export this.{addAll => alias} // error: double definition
38+
| ^
39+
| Double definition:
40+
| def alias(ints: Int*): (Buf.this : Buf) in class Buf at line 41 and
41+
| final def alias(ints: Int*): (Buf.this : Buf) in class Buf at line 42
42+
| have the same type after erasure.
43+
-- Error: tests/neg/exports.scala:47:15 --------------------------------------------------------------------------------
44+
47 | export foo.foo // error: no eligible member
4345
| ^^^
4446
| no eligible member foo at this.foo
4547
| this.foo.foo cannot be exported because it is already a member of class Foo
46-
-- [E120] Naming Error: tests/neg/exports.scala:46:15 ------------------------------------------------------------------
47-
46 | export bar._ // error: double definition
48+
-- [E120] Naming Error: tests/neg/exports.scala:52:15 ------------------------------------------------------------------
49+
52 | export bar._ // error: double definition
4850
| ^
4951
| Double definition:
50-
| val bar: Bar in class Baz at line 45 and
51-
| final def bar: => (Baz.this.bar.bar : => (Baz.this.bar.baz.bar : Bar)) in class Baz at line 46
52+
| val bar: Bar in class Baz at line 51 and
53+
| final def bar: => (Baz.this.bar.bar : => (Baz.this.bar.baz.bar : Bar)) in class Baz at line 52

tests/neg/exports.scala

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,16 @@
3232

3333
def concat[B >: A](other: List[B]): CC[B]
3434

35-
export this.{concat => ++} // error: no eligible member
35+
export this.{concat => ++}
3636

3737
}
3838

39+
class Buf {
40+
def addAll(ints: Int*): this.type = this
41+
def alias(ints: Int*): this.type = this
42+
export this.{addAll => alias} // error: double definition
43+
}
44+
3945
class Foo {
4046
val foo : Foo = new Foo
4147
export foo.foo // error: no eligible member
@@ -49,3 +55,7 @@
4955
val baz: Baz = new Baz
5056
export baz._
5157
}
58+
class Qux {
59+
val qux: Qux = new Qux
60+
export qux.{qux => innerQux}
61+
}

tests/neg/exports1.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,7 @@ object D1 extends B:
1818
object D2 extends B:
1919
object b2 extends B2
2020
export b2.f // error
21+
22+
object D3 extends B:
23+
object b2 extends B2
24+
export b2.{f => g} // ok

tests/pos/i9704.scala

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
abstract class WordSpec {
2+
export this.{extension_in => extension_should}
3+
4+
extension(s: String) def in(f: => Any): Unit = {
5+
println(s)
6+
f
7+
}
8+
}
9+
10+
object test extends WordSpec {
11+
"X" should {
12+
"add numbers" in {
13+
assert(1 + 1 == 2)
14+
}
15+
}
16+
}

0 commit comments

Comments
 (0)