Skip to content

Commit

Permalink
fix scala#9704: take renaming into account with exports
Browse files Browse the repository at this point in the history
  • Loading branch information
bishabosha committed Oct 30, 2020
1 parent 9ec34f8 commit e2e169c
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 28 deletions.
35 changes: 19 additions & 16 deletions compiler/src/dotty/tools/dotc/typer/Namer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -949,26 +949,28 @@ class Namer { typer: Typer =>
lazy val wildcardBound = importBound(selectors, isGiven = false)
lazy val givenBound = importBound(selectors, isGiven = true)

def whyNoForwarder(mbr: SingleDenotation): String = {
def whyNoForwarder(mbr: SingleDenotation, isSameName: Boolean): String = {
val sym = mbr.symbol
if (!sym.isAccessibleFrom(path.tpe)) "is not accessible"
else if (sym.isConstructor || sym.is(ModuleClass) || sym.is(Bridge)) SKIP
else if (cls.derivesFrom(sym.owner) &&
(sym.owner == cls || !sym.is(Deferred))) i"is already a member of $cls"
else if (sym.is(Override))
sym.allOverriddenSymbols.find(
other => cls.derivesFrom(other.owner) && !other.is(Deferred)) match {
case Some(other) => i"overrides ${other.showLocated}, which is already a member of $cls"
case None => ""
}
if !sym.isAccessibleFrom(path.tpe) then "is not accessible"
else if sym.isConstructor || sym.is(ModuleClass) || sym.is(Bridge) then SKIP
else if isSameName then
if cls.derivesFrom(sym.owner) && (sym.owner == cls || !sym.is(Deferred)) then
i"is already a member of $cls"
else if sym.is(Override) then
sym.allOverriddenSymbols.find(
other => cls.derivesFrom(other.owner) && !other.is(Deferred)) match {
case Some(other) => i"overrides ${other.showLocated}, which is already a member of $cls"
case None => ""
}
else ""
else ""
}

/** Add a forwarder with name `alias` or its type name equivalent to `mbr`,
* provided `mbr` is accessible and of the right implicit/non-implicit kind.
*/
def addForwarder(alias: TermName, mbr: SingleDenotation, span: Span): Unit =
if (whyNoForwarder(mbr) == "") {
def addForwarder(alias: TermName, isSameName: Boolean, mbr: SingleDenotation, span: Span): Unit =
if (whyNoForwarder(mbr, isSameName) == "") {
val sym = mbr.symbol
val forwarder =
if mbr.isType then
Expand Down Expand Up @@ -1017,9 +1019,10 @@ class Namer { typer: Typer =>
def addForwardersNamed(name: TermName, alias: TermName, span: Span): Unit = {
val size = buf.size
val mbrs = List(name, name.toTypeName, name.toExtensionName).flatMap(path.tpe.member(_).alternatives)
mbrs.foreach(addForwarder(alias, _, span))
val isSameName = name == alias
mbrs.foreach(addForwarder(alias, isSameName, _, span))
if (buf.size == size) {
val reason = mbrs.map(whyNoForwarder).dropWhile(_ == SKIP) match {
val reason = mbrs.map(whyNoForwarder(_, isSameName)).dropWhile(_ == SKIP) match {
case Nil => ""
case why :: _ => i"\n$path.$name cannot be exported because it $why"
}
Expand All @@ -1035,7 +1038,7 @@ class Namer { typer: Typer =>
val alias = mbr.name.toTermName
if !seen.contains(alias)
&& mbr.matchesImportBound(if mbr.symbol.is(Given) then givenBound else wildcardBound)
then addForwarder(alias, mbr, span)
then addForwarder(alias, isSameName = true, mbr, span)

def addForwarders(sels: List[untpd.ImportSelector], seen: List[TermName]): Unit = sels match
case sel :: sels1 =>
Expand Down
24 changes: 13 additions & 11 deletions tests/neg/exports.check
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,21 @@
| final def status: => List[String] in class Copier at line 24 and
| final def status: => List[String] in class Copier at line 26
| have the same type after erasure.
-- Error: tests/neg/exports.scala:35:24 --------------------------------------------------------------------------------
35 | export this.{concat => ++} // error: no eligible member
| ^^^^^^^^^^^^
| no eligible member concat at this
| this.concat cannot be exported because it is already a member of trait IterableOps
-- Error: tests/neg/exports.scala:41:15 --------------------------------------------------------------------------------
41 | export foo.foo // error: no eligible member
-- [E120] Naming Error: tests/neg/exports.scala:42:24 ------------------------------------------------------------------
42 | export this.{addAll => alias} // error: double definition
| ^
| Double definition:
| def alias(ints: Int*): (Buf.this : Buf) in class Buf at line 41 and
| final def alias(ints: Int*): (Buf.this : Buf) in class Buf at line 42
| have the same type after erasure.
-- Error: tests/neg/exports.scala:47:15 --------------------------------------------------------------------------------
47 | export foo.foo // error: no eligible member
| ^^^
| no eligible member foo at this.foo
| this.foo.foo cannot be exported because it is already a member of class Foo
-- [E120] Naming Error: tests/neg/exports.scala:46:15 ------------------------------------------------------------------
46 | export bar._ // error: double definition
-- [E120] Naming Error: tests/neg/exports.scala:52:15 ------------------------------------------------------------------
52 | export bar._ // error: double definition
| ^
| Double definition:
| val bar: Bar in class Baz at line 45 and
| final def bar: => (Baz.this.bar.bar : => (Baz.this.bar.baz.bar : Bar)) in class Baz at line 46
| val bar: Bar in class Baz at line 51 and
| final def bar: => (Baz.this.bar.bar : => (Baz.this.bar.baz.bar : Bar)) in class Baz at line 52
12 changes: 11 additions & 1 deletion tests/neg/exports.scala
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,16 @@

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

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

}

class Buf {
def addAll(ints: Int*): this.type = this
def alias(ints: Int*): this.type = this
export this.{addAll => alias} // error: double definition
}

class Foo {
val foo : Foo = new Foo
export foo.foo // error: no eligible member
Expand All @@ -49,3 +55,7 @@
val baz: Baz = new Baz
export baz._
}
class Qux {
val qux: Qux = new Qux
export qux.{qux => innerQux}
}
4 changes: 4 additions & 0 deletions tests/neg/exports1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,7 @@ object D1 extends B:
object D2 extends B:
object b2 extends B2
export b2.f // error

object D3 extends B:
object b2 extends B2
export b2.{f => g} // ok
16 changes: 16 additions & 0 deletions tests/pos/i9704.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
abstract class WordSpec {
export this.{extension_in => extension_should}

extension(s: String) def in(f: => Any): Unit = {
println(s)
f
}
}

object test extends WordSpec {
"X" should {
"add numbers" in {
assert(1 + 1 == 2)
}
}
}

0 comments on commit e2e169c

Please sign in to comment.