@@ -56,6 +56,8 @@ trait Contexts { self: Analyzer =>
56
56
LookupAmbiguous (s " it is imported twice in the same scope by \n $imp1\n and $imp2" )
57
57
def ambiguousDefnAndImport (owner : Symbol , imp : ImportInfo ) =
58
58
LookupAmbiguous (s " it is both defined in $owner and imported subsequently by \n $imp" )
59
+ def ambiguousDefinitions (owner : Symbol , other : Symbol ) =
60
+ LookupAmbiguous (s " it is both defined in $owner and available as ${other.fullLocationString}" )
59
61
60
62
private lazy val startContext = NoContext .make(
61
63
Template (List (), noSelfType, List ()) setSymbol global.NoSymbol setType global.NoType ,
@@ -1410,15 +1412,17 @@ trait Contexts { self: Analyzer =>
1410
1412
}
1411
1413
1412
1414
// cx.scope eq null arises during FixInvalidSyms in Duplicators
1413
- while (defSym == NoSymbol && (cx ne NoContext ) && (cx.scope ne null )) {
1414
- pre = cx.enclClass.prefix
1415
- defSym = lookupInScope(cx.owner, cx.enclClass.prefix, cx.scope) match {
1416
- case NoSymbol => searchPrefix
1417
- case found => found
1415
+ def nextDefinition (): Unit =
1416
+ while (defSym == NoSymbol && (cx ne NoContext ) && (cx.scope ne null )) {
1417
+ pre = cx.enclClass.prefix
1418
+ defSym = lookupInScope(cx.owner, cx.enclClass.prefix, cx.scope) match {
1419
+ case NoSymbol => searchPrefix
1420
+ case found => found
1421
+ }
1422
+ if (! defSym.exists) cx = cx.outer // push further outward
1418
1423
}
1419
- if (! defSym.exists)
1420
- cx = cx.outer // push further outward
1421
- }
1424
+ nextDefinition()
1425
+
1422
1426
if (symbolDepth < 0 )
1423
1427
symbolDepth = cx.depth
1424
1428
@@ -1458,24 +1462,50 @@ trait Contexts { self: Analyzer =>
1458
1462
importCursor.advanceImp1Imp2()
1459
1463
}
1460
1464
1461
- if ( defSym.exists && impSym.exists) {
1465
+ val preferDef : Boolean = defSym.exists && ( ! impSym.exists || {
1462
1466
// 4) root imported symbols have same (lowest) precedence as package-owned symbols in different compilation units.
1463
1467
if (imp1.depth < symbolDepth && imp1.isRootImport && foreignDefined)
1464
- impSym = NoSymbol
1468
+ true
1465
1469
// 4) imported symbols have higher precedence than package-owned symbols in different compilation units.
1466
1470
else if (imp1.depth >= symbolDepth && foreignDefined)
1467
- defSym = NoSymbol
1471
+ false
1468
1472
// Defined symbols take precedence over erroneous imports.
1469
1473
else if (impSym.isError || impSym.name == nme.CONSTRUCTOR )
1470
- impSym = NoSymbol
1474
+ true
1471
1475
// Try to reconcile them before giving up, at least if the def is not visible
1472
1476
else if (foreignDefined && thisContext.reconcileAmbiguousImportAndDef(name, impSym, defSym))
1473
- impSym = NoSymbol
1477
+ true
1474
1478
// Otherwise they are irreconcilably ambiguous
1475
1479
else
1476
1480
return ambiguousDefnAndImport(defSym.alternatives.head.owner, imp1)
1481
+ })
1482
+
1483
+ // If the defSym is at 4, and there is a def at 1 in scope, then the reference is ambiguous.
1484
+ if (foreignDefined && ! defSym.isPackage) {
1485
+ val defSym0 = defSym
1486
+ val pre0 = pre
1487
+ val cx0 = cx
1488
+ while ((cx ne NoContext ) && cx.depth >= symbolDepth) cx = cx.outer
1489
+ var done = false
1490
+ while (! done) {
1491
+ defSym = NoSymbol
1492
+ nextDefinition()
1493
+ done = (cx eq NoContext ) || defSym.exists && ! foreignDefined
1494
+ if (! done && (cx ne NoContext )) cx = cx.outer
1495
+ }
1496
+ if (defSym.exists && (defSym ne defSym0)) {
1497
+ val ambiguity =
1498
+ if (preferDef) ambiguousDefinitions(owner = defSym.owner, defSym0)
1499
+ else ambiguousDefnAndImport(owner = defSym.owner, imp1)
1500
+ return ambiguity
1501
+ }
1502
+ defSym = defSym0
1503
+ pre = pre0
1504
+ cx = cx0
1477
1505
}
1478
1506
1507
+ if (preferDef) impSym = NoSymbol else defSym = NoSymbol
1508
+
1479
1509
// At this point only one or the other of defSym and impSym might be set.
1480
1510
if (defSym.exists) finishDefSym(defSym, pre)
1481
1511
else if (impSym.exists) {
0 commit comments