Skip to content

Commit c933e0d

Browse files
authored
Merge pull request #2861 from dotty-staging/fix-intersection
Fix #2858: Handle intersection selection when symbol only exists on one side
2 parents 707ff86 + ad1e2e8 commit c933e0d

File tree

3 files changed

+24
-15
lines changed

3 files changed

+24
-15
lines changed

compiler/src/dotty/tools/dotc/core/Denotations.scala

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -386,25 +386,28 @@ object Denotations {
386386
/** Establish a partial order "preference" order between symbols.
387387
* Give preference to `sym1` over `sym2` if one of the following
388388
* conditions holds, in decreasing order of weight:
389-
* 1. sym1 is concrete and sym2 is abstract
390-
* 2. The owner of sym1 comes before the owner of sym2 in the linearization
389+
* 1. sym2 doesn't exist
390+
* 2. sym1 is concrete and sym2 is abstract
391+
* 3. The owner of sym1 comes before the owner of sym2 in the linearization
391392
* of the type of the prefix `pre`.
392-
* 3. The access boundary of sym2 is properly contained in the access
393+
* 4. The access boundary of sym2 is properly contained in the access
393394
* boundary of sym1. For protected access, we count the enclosing
394395
* package as access boundary.
395-
* 4. sym1 a method but sym2 is not.
396+
* 5. sym1 a method but sym2 is not.
396397
* The aim of these criteria is to give some disambiguation on access which
397398
* - does not depend on textual order or other arbitrary choices
398399
* - minimizes raising of doubleDef errors
399400
*/
400401
def preferSym(sym1: Symbol, sym2: Symbol) =
401402
sym1.eq(sym2) ||
402-
sym1.isAsConcrete(sym2) &&
403-
(!sym2.isAsConcrete(sym1) ||
404-
precedes(sym1.owner, sym2.owner) ||
405-
accessBoundary(sym2).isProperlyContainedIn(accessBoundary(sym1)) ||
406-
sym1.is(Method) && !sym2.is(Method)) ||
407-
sym1.info.isErroneous
403+
sym1.exists &&
404+
(!sym2.exists ||
405+
sym1.isAsConcrete(sym2) &&
406+
(!sym2.isAsConcrete(sym1) ||
407+
precedes(sym1.owner, sym2.owner) ||
408+
accessBoundary(sym2).isProperlyContainedIn(accessBoundary(sym1)) ||
409+
sym1.is(Method) && !sym2.is(Method)) ||
410+
sym1.info.isErroneous)
408411

409412
/** Sym preference provided types also override */
410413
def prefer(sym1: Symbol, sym2: Symbol, info1: Type, info2: Type) =
@@ -425,9 +428,7 @@ object Denotations {
425428
else if (isDoubleDef(sym1, sym2)) handleDoubleDef
426429
else {
427430
val sym =
428-
if (!sym1.exists) sym2
429-
else if (!sym2.exists) sym1
430-
else if (preferSym(sym2, sym1)) sym2
431+
if (preferSym(sym2, sym1)) sym2
431432
else sym1
432433
val jointInfo =
433434
try infoMeet(info1, info2)
@@ -1243,4 +1244,4 @@ object Denotations {
12431244
util.Stats.record("stale symbol")
12441245
override def getMessage() = msg
12451246
}
1246-
}
1247+
}

compiler/src/dotty/tools/dotc/core/SymDenotations.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -781,7 +781,7 @@ object SymDenotations {
781781
sym.owner == defn.AnyClass ||
782782
sym == defn.Object_clone ||
783783
sym.owner.is(Scala2x)
784-
test(symbol) || allOverriddenSymbols.exists(test)
784+
this.exists && (test(symbol) || allOverriddenSymbols.exists(test))
785785
}
786786

787787
// ------ access to related symbols ---------------------------------

tests/pos/i2858.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
class Cont[A0](x0: A0) { type A = A0; val x: A = x0 }
2+
3+
object Test {
4+
def test: Unit = {
5+
val c: Cont[_] & { type A = Int } = new Cont(1)
6+
c.x
7+
}
8+
}

0 commit comments

Comments
 (0)