Skip to content

Commit f122b34

Browse files
jchybtgodzik
authored andcommitted
Fail compilation if multiple conflicting top-level private defs/vals are in the same package (scala#22759)
Now the private top level definitions act basically the same as package private (which is the same behavior as private objects/classes), as that is what the reference implies, and it helps us avoid ambiguous method/value selections.
1 parent 2b2895a commit f122b34

File tree

5 files changed

+21
-7
lines changed

5 files changed

+21
-7
lines changed

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

+6-6
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ class Namer { typer: Typer =>
131131
* The logic here is very subtle and fragile due to the fact that
132132
* we are not allowed to force anything.
133133
*/
134-
def checkNoConflict(name: Name, isPrivate: Boolean, span: Span)(using Context): Name =
134+
def checkNoConflict(name: Name, span: Span)(using Context): Name =
135135
val owner = ctx.owner
136136
var conflictsDetected = false
137137

@@ -166,7 +166,7 @@ class Namer { typer: Typer =>
166166
def preExisting = ctx.effectiveScope.lookup(name)
167167
if (!owner.isClass || name.isTypeName) && preExisting.exists then
168168
conflict(preExisting)
169-
else if owner.isPackageObject && !isPrivate && name != nme.CONSTRUCTOR then
169+
else if owner.isPackageObject && name != nme.CONSTRUCTOR then
170170
checkNoConflictIn(owner.owner)
171171
for pkgObj <- pkgObjs(owner.owner) if pkgObj != owner do
172172
checkNoConflictIn(pkgObj)
@@ -242,7 +242,7 @@ class Namer { typer: Typer =>
242242
tree match {
243243
case tree: TypeDef if tree.isClassDef =>
244244
val flags = checkFlags(tree.mods.flags)
245-
val name = checkNoConflict(tree.name, flags.is(Private), tree.span).asTypeName
245+
val name = checkNoConflict(tree.name, tree.span).asTypeName
246246
val cls =
247247
createOrRefine[ClassSymbol](tree, name, flags, ctx.owner,
248248
cls => adjustIfModule(new ClassCompleter(cls, tree)(ctx), tree),
@@ -251,7 +251,7 @@ class Namer { typer: Typer =>
251251
cls
252252
case tree: MemberDef =>
253253
var flags = checkFlags(tree.mods.flags)
254-
val name = checkNoConflict(tree.name, flags.is(Private), tree.span)
254+
val name = checkNoConflict(tree.name, tree.span)
255255
tree match
256256
case tree: ValOrDefDef =>
257257
if tree.isInstanceOf[ValDef] && !flags.is(Param) && name.endsWith("_=") then
@@ -1217,7 +1217,7 @@ class Namer { typer: Typer =>
12171217
val hasDefaults = sym.hasDefaultParams // compute here to ensure HasDefaultParams and NoDefaultParams flags are set
12181218
val forwarder =
12191219
if mbr.isType then
1220-
val forwarderName = checkNoConflict(alias.toTypeName, isPrivate = false, span)
1220+
val forwarderName = checkNoConflict(alias.toTypeName, span)
12211221
var target = pathType.select(sym)
12221222
if target.typeParams.nonEmpty then
12231223
target = target.EtaExpand(target.typeParams)
@@ -1271,7 +1271,7 @@ class Namer { typer: Typer =>
12711271
(EmptyFlags, mbrInfo)
12721272
var mbrFlags = MandatoryExportTermFlags | maybeStable | (sym.flags & RetainedExportTermFlags)
12731273
if pathMethod.exists then mbrFlags |= ExtensionMethod
1274-
val forwarderName = checkNoConflict(alias, isPrivate = false, span)
1274+
val forwarderName = checkNoConflict(alias, span)
12751275
newSymbol(cls, forwarderName, mbrFlags, mbrInfo, coord = span)
12761276

12771277
forwarder.info = avoidPrivateLeaks(forwarder)

tests/neg/i22721.check

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
-- [E161] Naming Error: tests/neg/i22721/test2.scala:3:12 --------------------------------------------------------------
2+
3 |private def foobar: Int = 0 // error
3+
|^^^^^^^^^^^^^^^^^^^^^^^^^^^
4+
|foobar is already defined as method foobar in tests/neg/i22721/test1.scala
5+
|
6+
|Note that overloaded methods must all be defined in the same group of toplevel definitions

tests/neg/i22721/test1.scala

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package example
2+
3+
private def foobar: String = "foo"
4+
object test1 { def x = foobar }

tests/neg/i22721/test2.scala

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package example
2+
3+
private def foobar: Int = 0 // error
4+
object test2 { def x = foobar }

tests/neg/toplevel-overload/moredefs_1.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ trait B
22

33
def f(x: B) = s"B" // error: has already been compiled
44

5-
private def g(): Unit = () // OK, since it is private
5+
private def g(): Unit = () // error: has already been compiled (def is visible in package)

0 commit comments

Comments
 (0)