Skip to content

Commit 8d57aec

Browse files
committed
Refine & document clash detection scheme
1 parent 4d6f215 commit 8d57aec

File tree

3 files changed

+22
-5
lines changed

3 files changed

+22
-5
lines changed

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

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1072,9 +1072,14 @@ class Namer { typer: Typer =>
10721072
val renamed = mutable.Set[Name]()
10731073
val selectors = selectors0 map {
10741074
case sel @ ImportSelector(imported, id @ Ident(alias), bound) if alias != nme.WILDCARD =>
1075+
def noAliasSelector =
1076+
cpy.ImportSelector(sel)(imported, EmptyTree, bound).asInstanceOf[ImportSelector]
10751077
if renamed.contains(alias) then
10761078
report.error(i"duplicate rename target", id.srcPos)
1077-
cpy.ImportSelector(sel)(imported, EmptyTree, bound).asInstanceOf[ImportSelector]
1079+
noAliasSelector
1080+
else if alias == imported.name then
1081+
report.warning(i"redundant rename in export", id.srcPos)
1082+
noAliasSelector
10781083
else
10791084
renamed += alias
10801085
sel
@@ -1086,7 +1091,7 @@ class Namer { typer: Typer =>
10861091
lazy val wildcardBound = importBound(selectors, isGiven = false)
10871092
lazy val givenBound = importBound(selectors, isGiven = true)
10881093

1089-
def canForward(mbr: SingleDenotation): CanForward = {
1094+
def canForward(mbr: SingleDenotation, alias: TermName): CanForward = {
10901095
import CanForward.*
10911096
val sym = mbr.symbol
10921097
if !sym.isAccessibleFrom(path.tpe) then
@@ -1095,7 +1100,7 @@ class Namer { typer: Typer =>
10951100
Skip
10961101
else if cls.derivesFrom(sym.owner) && (sym.owner == cls || !sym.is(Deferred)) then
10971102
No(i"is already a member of $cls")
1098-
else if renamed.contains(sym.name.toTermName) then
1103+
else if alias == mbr.name.toTermName && renamed.contains(alias) then
10991104
No(i"clashes with a renamed export")
11001105
else if sym.is(Override) then
11011106
sym.allOverriddenSymbols.find(
@@ -1139,7 +1144,7 @@ class Namer { typer: Typer =>
11391144
case _ =>
11401145
acc.reverse ::: prefss
11411146

1142-
if canForward(mbr) == CanForward.Yes then
1147+
if canForward(mbr, alias) == CanForward.Yes then
11431148
val sym = mbr.symbol
11441149
val hasDefaults = sym.hasDefaultParams // compute here to ensure HasDefaultParams and NoDefaultParams flags are set
11451150
val forwarder =
@@ -1196,7 +1201,7 @@ class Namer { typer: Typer =>
11961201
val mbrs = List(name, name.toTypeName).flatMap(path.tpe.member(_).alternatives)
11971202
mbrs.foreach(addForwarder(alias, _, span))
11981203
if buf.size == size then
1199-
val reason = mbrs.map(canForward).collect {
1204+
val reason = mbrs.map(canForward(_, alias)).collect {
12001205
case CanForward.No(whyNot) => i"\n$path.$name cannot be exported because it $whyNot"
12011206
}.headOption.getOrElse("")
12021207
report.error(i"""no eligible member $name at $path$reason""", ctx.source.atSpan(span))

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,15 @@ def f: c.T = ...
100100

101101
1. Export clauses can appear in classes or they can appear at the top-level. An export clause cannot appear as a statement in a block.
102102
1. If an export clause contains a wildcard or given selector, it is forbidden for its qualifier path to refer to a package. This is because it is not yet known how to safely track wildcard dependencies to a package for the purposes of incremental compilation.
103+
1. An export renaming hides un-renamed exports matching the target name. For instance, the following
104+
clause would be invalid since `B` is hidden by the renaming `A as B`.
105+
```scala
106+
export {A as B, B} // error: B is hidden
107+
```
108+
109+
1. Renamings in an export clause must have pairwise different target names. For instance, the following clause would be invalid:
110+
```scala
111+
export {A as C, B as C} // error: duplicate renaming
103112

104113
1. Simple renaming exports like
105114
```scala

tests/neg/i14818.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,6 @@ object T3:
1818
object T4:
1919
export M.{A as C, B as C} // error
2020

21+
object T5:
22+
export M.{A as B, B as A} // OK
23+

0 commit comments

Comments
 (0)