Skip to content

Commit bc0670a

Browse files
committed
Avoid parameter name clashes in export forwarders
1 parent 98f0a63 commit bc0670a

File tree

4 files changed

+31
-7
lines changed

4 files changed

+31
-7
lines changed

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

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1179,11 +1179,28 @@ class Namer { typer: Typer =>
11791179
then
11801180
(StableRealizable, ExprType(pathType.select(sym)))
11811181
else
1182-
def addPathMethodParams(pt: Type, info: Type): Type = pt match
1183-
case pt: MethodOrPoly =>
1184-
pt.derivedLambdaType(resType = addPathMethodParams(pt.resType, info))
1185-
case _ =>
1186-
info
1182+
def addPathMethodParams(pathType: Type, info: Type): Type =
1183+
def defines(pt: Type, pname: Name): Boolean = pt match
1184+
case pt: MethodOrPoly =>
1185+
pt.paramNames.contains(pname) || defines(pt.resType, pname)
1186+
case _ =>
1187+
false
1188+
def avoidNameClashes(info: Type): Type = info match
1189+
case info: MethodOrPoly =>
1190+
info.derivedLambdaType(
1191+
paramNames = info.paramNames.mapConserve {
1192+
pname => if defines(pathType, pname) then pname.freshened else pname
1193+
},
1194+
resType = avoidNameClashes(info.resType))
1195+
case info =>
1196+
info
1197+
def wrap(pt: Type, info: Type): Type = pt match
1198+
case pt: MethodOrPoly =>
1199+
pt.derivedLambdaType(resType = wrap(pt.resType, info))
1200+
case _ =>
1201+
info
1202+
wrap(pathType, avoidNameClashes(info))
1203+
11871204
val mbrInfo =
11881205
if pathMethod.exists
11891206
then addPathMethodParams(pathMethod.info, mbr.info.widenExpr)

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2590,7 +2590,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
25902590
val selectors1 = typedSelectors(exp.selectors)
25912591
assignType(cpy.Export(exp)(expr1, selectors1))
25922592
case _ =>
2593-
errorTree(exp, em"exports are only allowed from objects and classes")
2593+
errorTree(exp, em"exports are only allowed from objects and classes, they can not belong to local blocks")
25942594

25952595
def typedPackageDef(tree: untpd.PackageDef)(using Context): Tree =
25962596
val pid1 = withMode(Mode.InPackageClauseName)(typedExpr(tree.pid, AnySelectionProto))

tests/neg/export-in-extension.check

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,4 @@
2626
-- Error: tests/neg/export-in-extension.scala:38:13 --------------------------------------------------------------------
2727
38 | export cm.* // error
2828
| ^^^^^^^^^^^
29-
| exports are only allowed from objects and classes
29+
| exports are only allowed from objects and classes, they can not belong to local blocks
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
class Ops[A](xs: List[A]):
2+
def map[B](x: A => B): List[B] = ???
3+
4+
extension [B](x: List[B])
5+
private def ops = new Ops[B](x)
6+
export ops.map // `x` and `B` should not appear twice as a parameter
7+

0 commit comments

Comments
 (0)