Skip to content

Commit e1ce523

Browse files
Merge pull request #14879 from dotty-staging/fix-14875
Simplify and harden duplicates checking in exports
2 parents 2ec9c52 + 7b6e38a commit e1ce523

File tree

3 files changed

+18
-27
lines changed

3 files changed

+18
-27
lines changed

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

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1072,33 +1072,17 @@ class Namer { typer: Typer =>
10721072
/** The forwarders defined by export `exp` */
10731073
private def exportForwarders(exp: Export)(using Context): List[tpd.MemberDef] =
10741074
val buf = new mutable.ListBuffer[tpd.MemberDef]
1075-
val Export(expr, selectors0) = exp
1075+
val Export(expr, selectors) = exp
10761076
if expr.isEmpty then
10771077
report.error(em"Export selector must have prefix and `.`", exp.srcPos)
10781078
return Nil
10791079

1080-
val renamed = mutable.Set[Name]()
1081-
val selectors = selectors0 map {
1082-
case sel @ ImportSelector(imported, id @ Ident(alias), bound) if alias != nme.WILDCARD =>
1083-
def noAliasSelector =
1084-
cpy.ImportSelector(sel)(imported, EmptyTree, bound).asInstanceOf[ImportSelector]
1085-
if renamed.contains(alias) then
1086-
report.error(i"duplicate rename target", id.srcPos)
1087-
noAliasSelector
1088-
else if alias == imported.name then
1089-
report.warning(i"redundant rename in export", id.srcPos)
1090-
noAliasSelector
1091-
else
1092-
renamed += alias
1093-
sel
1094-
case sel => sel
1095-
}
1096-
10971080
val path = typedAheadExpr(expr, AnySelectionProto)
10981081
checkLegalExportPath(path, selectors)
10991082
lazy val wildcardBound = importBound(selectors, isGiven = false)
11001083
lazy val givenBound = importBound(selectors, isGiven = true)
11011084

1085+
val targets = mutable.Set[Name]()
11021086
def canForward(mbr: SingleDenotation, alias: TermName): CanForward = {
11031087
import CanForward.*
11041088
val sym = mbr.symbol
@@ -1108,8 +1092,8 @@ class Namer { typer: Typer =>
11081092
Skip
11091093
else if cls.derivesFrom(sym.owner) && (sym.owner == cls || !sym.is(Deferred)) then
11101094
No(i"is already a member of $cls")
1111-
else if alias == mbr.name.toTermName && renamed.contains(alias) then
1112-
No(i"clashes with a renamed export")
1095+
else if targets.contains(alias) then
1096+
No(i"clashes with another export in the same export clause")
11131097
else if sym.is(Override) then
11141098
sym.allOverriddenSymbols.find(
11151099
other => cls.derivesFrom(other.owner) && !other.is(Deferred)
@@ -1208,6 +1192,7 @@ class Namer { typer: Typer =>
12081192
val size = buf.size
12091193
val mbrs = List(name, name.toTypeName).flatMap(path.tpe.member(_).alternatives)
12101194
mbrs.foreach(addForwarder(alias, _, span))
1195+
targets += alias
12111196
if buf.size == size then
12121197
val reason = mbrs.map(canForward(_, alias)).collect {
12131198
case CanForward.No(whyNot) => i"\n$path.$name cannot be exported because it $whyNot"

tests/neg/i14818.check

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
1-
-- Error: tests/neg/i14818.scala:9:12 ----------------------------------------------------------------------------------
1+
-- Error: tests/neg/i14818.scala:9:17 ----------------------------------------------------------------------------------
22
9 | export M.{A, B as A} // error
3-
| ^
4-
| no eligible member A at M
5-
| M.A cannot be exported because it clashes with a renamed export
3+
| ^^^^^^
4+
| no eligible member B at M
5+
| M.B cannot be exported because it clashes with another export in the same export clause
66
-- [E050] Type Error: tests/neg/i14818.scala:16:10 ---------------------------------------------------------------------
77
16 | val x = b(1) // error
88
| ^
99
| method b in object T3 does not take parameters
1010
|
1111
| longer explanation available when compiling with `-explain`
12-
-- Error: tests/neg/i14818.scala:19:25 ---------------------------------------------------------------------------------
12+
-- Error: tests/neg/i14818.scala:19:22 ---------------------------------------------------------------------------------
1313
19 | export M.{A as C, B as C} // error
14-
| ^
15-
| duplicate rename target
14+
| ^^^^^^
15+
| no eligible member B at M
16+
| M.B cannot be exported because it clashes with another export in the same export clause

tests/neg/i14875.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
object M {
2+
type B
3+
}
4+
5+
export M.{B, B} // error

0 commit comments

Comments
 (0)