Skip to content

Commit e83d59c

Browse files
committed
Avoid parameter name clashes in export forwarders
1 parent db1d862 commit e83d59c

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
@@ -1180,11 +1180,28 @@ class Namer { typer: Typer =>
11801180
then
11811181
(StableRealizable, ExprType(pathType.select(sym)))
11821182
else
1183-
def addPathMethodParams(pt: Type, info: Type): Type = pt match
1184-
case pt: MethodOrPoly =>
1185-
pt.derivedLambdaType(resType = addPathMethodParams(pt.resType, info))
1186-
case _ =>
1187-
info
1183+
def addPathMethodParams(pathType: Type, info: Type): Type =
1184+
def defines(pt: Type, pname: Name): Boolean = pt match
1185+
case pt: MethodOrPoly =>
1186+
pt.paramNames.contains(pname) || defines(pt.resType, pname)
1187+
case _ =>
1188+
false
1189+
def avoidNameClashes(info: Type): Type = info match
1190+
case info: MethodOrPoly =>
1191+
info.derivedLambdaType(
1192+
paramNames = info.paramNames.mapConserve {
1193+
pname => if defines(pathType, pname) then pname.freshened else pname
1194+
},
1195+
resType = avoidNameClashes(info.resType))
1196+
case info =>
1197+
info
1198+
def wrap(pt: Type, info: Type): Type = pt match
1199+
case pt: MethodOrPoly =>
1200+
pt.derivedLambdaType(resType = wrap(pt.resType, info))
1201+
case _ =>
1202+
info
1203+
wrap(pathType, avoidNameClashes(info))
1204+
11881205
val mbrInfo =
11891206
if pathMethod.exists
11901207
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
@@ -2622,7 +2622,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
26222622
val selectors1 = typedSelectors(exp.selectors)
26232623
assignType(cpy.Export(exp)(expr1, selectors1))
26242624
case _ =>
2625-
errorTree(exp, em"exports are only allowed from objects and classes")
2625+
errorTree(exp, em"exports are only allowed from objects and classes, they can not belong to local blocks")
26262626

26272627
def typedPackageDef(tree: untpd.PackageDef)(using Context): Tree =
26282628
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)