Skip to content

Commit ba2be40

Browse files
authored
Skip ambiguous reference error when symbols are aliases (#16401)
Follow-up for #8622, which introduced a new lookup ambiguity if a name is inherited from a parent and also found in an outer scope. The error is avoided if the two symbols are aliases.
2 parents 81235b7 + 5b8cebf commit ba2be40

File tree

2 files changed

+28
-1
lines changed

2 files changed

+28
-1
lines changed

compiler/src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,17 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
376376
case denot => !denot.hasAltWith(isCurrent)
377377

378378
def checkNoOuterDefs(denot: Denotation, last: Context, prevCtx: Context): Unit =
379+
def sameTermOrType(d1: SingleDenotation, d2: Denotation) =
380+
d2.containsSym(d1.symbol) || d2.hasUniqueSym && {
381+
val sym1 = d1.symbol
382+
val sym2 = d2.symbol
383+
if sym1.isTerm then
384+
sym1.isStableMember &&
385+
sym2.isStableMember &&
386+
sym1.owner.thisType.select(name, sym1) =:= sym2.owner.thisType.select(name, sym2)
387+
else
388+
(sym1.isAliasType || sym2.isAliasType) && d1.info =:= d2.info
389+
}
379390
val outer = last.outer
380391
val owner = outer.owner
381392
if (owner eq last.owner) && (outer.scope eq last.scope) then
@@ -385,7 +396,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
385396
val competing = scope.denotsNamed(name).filterWithFlags(required, excluded)
386397
if competing.exists then
387398
val symsMatch = competing
388-
.filterWithPredicate(sd => denot.containsSym(sd.symbol))
399+
.filterWithPredicate(sd => sameTermOrType(sd, denot))
389400
.exists
390401
if !symsMatch && !suppressErrors then
391402
report.errorOrMigrationWarning(

tests/pos/t11921.scala

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
object t1:
2+
class C
3+
class A:
4+
val c: B.c.type = B.c
5+
object B:
6+
val c = new C
7+
val a = new A:
8+
def m = c // not ambiguous, `this.c` and `B.c` are compatible paths
9+
10+
object t2:
11+
class C[T]:
12+
type TT = T
13+
object O:
14+
type TT = String
15+
class D extends C[TT]:
16+
def n(x: TT) = x // `TT` is not ambiguous, `this.TT` and `O.TT` are aliases

0 commit comments

Comments
 (0)