@@ -302,21 +302,45 @@ class Namer { typer: Typer =>
302
302
303
303
typr.println(i " creating symbol for $tree in ${ctx.mode}" )
304
304
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
+
310
328
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)
315
334
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
320
344
321
345
/** Create new symbol or redefine existing symbol under lateCompile. */
322
346
def createOrRefine [S <: Symbol ](
@@ -348,17 +372,17 @@ class Namer { typer: Typer =>
348
372
349
373
tree match {
350
374
case tree : TypeDef if tree.isClassDef =>
351
- val name = checkNoConflict(tree.name).asTypeName
352
375
val flags = checkFlags(tree.mods.flags &~ GivenOrImplicit )
376
+ val name = checkNoConflict(tree.name, flags.is(Private )).asTypeName
353
377
val cls =
354
378
createOrRefine[ClassSymbol ](tree, name, flags, ctx.owner,
355
379
cls => adjustIfModule(new ClassCompleter (cls, tree)(ctx), tree),
356
380
ctx.newClassSymbol(ctx.owner, name, _, _, _, tree.nameSpan, ctx.source.file))
357
381
cls.completer.asInstanceOf [ClassCompleter ].init()
358
382
cls
359
383
case tree : MemberDef =>
360
- val name = checkNoConflict(tree.name)
361
384
var flags = checkFlags(tree.mods.flags)
385
+ val name = checkNoConflict(tree.name, flags.is(Private ))
362
386
tree match
363
387
case tree : ValOrDefDef =>
364
388
if tree.unforcedRhs == EmptyTree
0 commit comments