@@ -302,21 +302,45 @@ class Namer { typer: Typer =>
302302
303303 typr.println(i " creating symbol for $tree in ${ctx.mode}" )
304304
305- def checkNoConflict (name : Name ): Name = {
306- def errorName (msg : => String ) = {
307- ctx.error(msg, tree.sourcePos)
308- name.freshened
309- }
305+ def checkNoConflict (name : Name , isPrivate : Boolean ): Name =
306+ val owner = ctx.owner
307+ var conflictsDetected = false
308+
309+ def conflict (conflicting : Symbol ) =
310+ val where : String =
311+ if conflicting.owner == owner then " "
312+ else if conflicting.owner.isPackageObject then i " in ${conflicting.associatedFile}"
313+ else i " in ${conflicting.owner}"
314+ ctx.error(i " $name is already defined as $conflicting$where" , tree.sourcePos)
315+ conflictsDetected = true
316+
317+ def checkNoConflictWith (preExisting : Symbol ) =
318+ if (preExisting.isDefinedInCurrentRun || preExisting.is(Package ))
319+ && (! preExisting.is(Private ) || preExisting.owner.is(Package ))
320+ then conflict(preExisting)
321+
322+ def checkNoConflictIn (owner : Symbol ) =
323+ checkNoConflictWith( owner.unforcedDecls.lookup(name))
324+
325+ def pkgObjs (pkg : Symbol ) =
326+ pkg.denot.asInstanceOf [PackageClassDenotation ].packageObjs.map(_.symbol)
327+
310328 def preExisting = ctx.effectiveScope.lookup(name)
311- if (ctx.owner.is(PackageClass ))
312- if (preExisting.isDefinedInCurrentRun)
313- errorName(s " ${preExisting.showLocated} has already been compiled once during this run " )
314- else name
329+ if owner.is(PackageClass ) then
330+ checkNoConflictWith(preExisting)
331+ return name
332+ for pkgObj <- pkgObjs(owner) do
333+ checkNoConflictIn(pkgObj)
315334 else
316- if ((! ctx.owner.isClass || name.isTypeName) && preExisting.exists)
317- errorName(i " $name is already defined as $preExisting" )
318- else name
319- }
335+ if (! owner.isClass || name.isTypeName) && preExisting.exists then
336+ conflict(preExisting)
337+ else if owner.isPackageObject && ! isPrivate && name != nme.CONSTRUCTOR then
338+ checkNoConflictIn(owner.owner)
339+ for pkgObj <- pkgObjs(owner.owner) if pkgObj != owner do
340+ checkNoConflictIn(pkgObj)
341+
342+ if conflictsDetected then name.freshened else name
343+ end checkNoConflict
320344
321345 /** Create new symbol or redefine existing symbol under lateCompile. */
322346 def createOrRefine [S <: Symbol ](
@@ -348,17 +372,17 @@ class Namer { typer: Typer =>
348372
349373 tree match {
350374 case tree : TypeDef if tree.isClassDef =>
351- val name = checkNoConflict(tree.name).asTypeName
352375 val flags = checkFlags(tree.mods.flags &~ GivenOrImplicit )
376+ val name = checkNoConflict(tree.name, flags.is(Private )).asTypeName
353377 val cls =
354378 createOrRefine[ClassSymbol ](tree, name, flags, ctx.owner,
355379 cls => adjustIfModule(new ClassCompleter (cls, tree)(ctx), tree),
356380 ctx.newClassSymbol(ctx.owner, name, _, _, _, tree.nameSpan, ctx.source.file))
357381 cls.completer.asInstanceOf [ClassCompleter ].init()
358382 cls
359383 case tree : MemberDef =>
360- val name = checkNoConflict(tree.name)
361384 var flags = checkFlags(tree.mods.flags)
385+ val name = checkNoConflict(tree.name, flags.is(Private ))
362386 tree match
363387 case tree : ValOrDefDef =>
364388 if tree.unforcedRhs == EmptyTree
0 commit comments