@@ -292,24 +292,41 @@ object Denotations {
292
292
val sym1 = denot1.symbol
293
293
val sym2 = denot2.symbol
294
294
295
- if (isDoubleDef(sym1, sym2)) doubleDefError(denot1, denot2, pre)
296
-
297
295
val sym2Accessible = sym2.isAccessibleFrom(pre)
296
+
298
297
/** Does `sym1` come before `sym2` in the linearization of `pre`? */
299
298
def precedes (sym1 : Symbol , sym2 : Symbol ) = {
300
299
def precedesIn (bcs : List [ClassSymbol ]): Boolean = bcs match {
301
300
case bc :: bcs1 => (sym1 eq bc) || ! (sym2 eq bc) && precedesIn(bcs1)
302
301
case Nil => true
303
302
}
304
- sym1.derivesFrom(sym2) ||
305
- ! sym2.derivesFrom(sym1) && precedesIn(pre.baseClasses)
303
+ (sym1 ne sym2) &&
304
+ (sym1.derivesFrom(sym2) ||
305
+ ! sym2.derivesFrom(sym1) && precedesIn(pre.baseClasses))
306
306
}
307
307
308
- /** Preference according to partial pre-order (isConcrete, precedes) */
308
+ /** Establish a partial order "preference" order between symbols.
309
+ * Give preference to `sym1` over `sym2` if one of the following
310
+ * conditions holds, in decreasing order of weight:
311
+ * 1. sym1 is concrete and sym2 is abstract
312
+ * 2. The owner of sym1 comes before the owner of sym2 in the linearization
313
+ * of the type of the prefix `pre`.
314
+ * 3. The access boundary of sym2 is properly contained in the access
315
+ * boundary of sym1. For protected access, we count the enclosing
316
+ * package as access boundary.
317
+ * 4. sym1 a method but sym2 is not.
318
+ * The aim of these criteria is to give some disambiguation on access which
319
+ * - does not depend on textual order or other arbitrary choices
320
+ * - minimizes raising of doubleDef errors
321
+ */
309
322
def preferSym (sym1 : Symbol , sym2 : Symbol ) =
310
323
sym1.eq(sym2) ||
311
324
sym1.isAsConcrete(sym2) &&
312
- (! sym2.isAsConcrete(sym1) || precedes(sym1.owner, sym2.owner))
325
+ (! sym2.isAsConcrete(sym1) ||
326
+ precedes(sym1.owner, sym2.owner) ||
327
+ sym2.accessBoundary(sym2.enclosingPackageClass)
328
+ .isProperlyContainedIn(sym1.accessBoundary(sym1.enclosingPackageClass)) ||
329
+ sym1.is(Method ) && ! sym2.is(Method ))
313
330
314
331
/** Sym preference provided types also override */
315
332
def prefer (sym1 : Symbol , sym2 : Symbol , info1 : Type , info2 : Type ) =
@@ -321,6 +338,7 @@ object Denotations {
321
338
if (sym1Accessible && prefer(sym1, sym2, info1, info2)) denot1
322
339
else if (sym1Accessible && sym2.exists && ! sym2Accessible) denot1
323
340
else if (sym2Accessible && sym1.exists && ! sym1Accessible) denot2
341
+ else if (isDoubleDef(sym1, sym2)) doubleDefError(denot1, denot2, pre)
324
342
else {
325
343
val sym =
326
344
if (! sym1.exists) sym2
0 commit comments