From 3fcb75c763b3274d68e8d3d76a0f69e4cc93f81b Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Thu, 2 Mar 2023 11:47:27 +0100 Subject: [PATCH] Include top-level symbols from same file in outer ambiguity error When checking if an inherited definition is ambiguous with an outer definition, include top-level outer definitions defined in the same compilation unit. --- .../src/dotty/tools/dotc/typer/Typer.scala | 14 ++++++++---- tests/neg/ambiref.check | 16 ++++++++++++++ tests/neg/ambiref.scala | 22 ++++++++++++++++++- tests/pos-special/fatal-warnings/i9260.scala | 2 +- tests/run/protectedacc.scala | 2 +- 5 files changed, 49 insertions(+), 7 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 9d8fdcc006c9..2338c2cde9d2 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -366,7 +366,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer // Does reference `tp` refer only to inherited symbols? def isInherited(denot: Denotation) = def isCurrent(mbr: SingleDenotation): Boolean = - !mbr.symbol.exists || mbr.symbol.owner == ctx.owner + !mbr.symbol.exists || mbr.symbol.owner == ctx.owner || ctx.owner.is(Package) denot match case denot: SingleDenotation => !isCurrent(denot) case denot => !denot.hasAltWith(isCurrent) @@ -387,9 +387,15 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer val owner = outer.owner if (owner eq last.owner) && (outer.scope eq last.scope) then checkNoOuterDefs(denot, outer, prevCtx) - else if !owner.is(Package) then - val scope = if owner.isClass then owner.info.decls else outer.scope - val competing = scope.denotsNamed(name).filterWithFlags(required, excluded) + else if !last.owner.isRoot then + val found = + if owner.is(Package) then + owner.denot.asClass.membersNamed(name) + .filterWithPredicate(d => !d.symbol.is(Package) && d.symbol.source == denot.symbol.source) + else + val scope = if owner.isClass then owner.info.decls else outer.scope + scope.denotsNamed(name) + val competing = found.filterWithFlags(required, excluded | Synthetic) if competing.exists then val symsMatch = competing .filterWithPredicate(sd => sameTermOrType(sd, denot)) diff --git a/tests/neg/ambiref.check b/tests/neg/ambiref.check index 5d701b3b3b71..32b4078f1346 100644 --- a/tests/neg/ambiref.check +++ b/tests/neg/ambiref.check @@ -30,3 +30,19 @@ | and inherited subsequently in class E | | longer explanation available when compiling with `-explain` +-- [E049] Reference Error: tests/neg/ambiref.scala:43:10 --------------------------------------------------------------- +43 | println(global) // error + | ^^^^^^ + | Reference to global is ambiguous. + | It is both defined in package + | and inherited subsequently in object D + | + | longer explanation available when compiling with `-explain` +-- [E049] Reference Error: tests/neg/ambiref.scala:49:16 --------------------------------------------------------------- +49 | def t = new T { } // error + | ^ + | Reference to T is ambiguous. + | It is both defined in package p + | and inherited subsequently in class C + | + | longer explanation available when compiling with `-explain` diff --git a/tests/neg/ambiref.scala b/tests/neg/ambiref.scala index e7a5d5efbd7e..bb48997cd465 100644 --- a/tests/neg/ambiref.scala +++ b/tests/neg/ambiref.scala @@ -40,4 +40,24 @@ val global = 0 class C: val global = 1 object D extends C: - println(global) // OK, since global is defined in package \ No newline at end of file + println(global) // error + +package p: + class T + trait P { trait T } + class C extends P: + def t = new T { } // error + +package scala: + trait P { trait Option[+A] } + class C extends P: + def t = new Option[String] { } // OK, competing scala.Option is not defined in the same compilation unit + +object test5: + class Mu // generates a synthetic companion object with an apply method + trait A { + val Mu = 1 + } + trait B extends A { + def t = Mu // don't warn about synthetic companion + } diff --git a/tests/pos-special/fatal-warnings/i9260.scala b/tests/pos-special/fatal-warnings/i9260.scala index df548f393eea..0392c1c96fa8 100644 --- a/tests/pos-special/fatal-warnings/i9260.scala +++ b/tests/pos-special/fatal-warnings/i9260.scala @@ -10,7 +10,7 @@ end AstImpl object untpd extends AstImpl[Null]: - def DefDef(ast: Ast): DefDef = ast match + def DefDef(ast: this.Ast): DefDef = ast match case ast: DefDef => ast end untpd diff --git a/tests/run/protectedacc.scala b/tests/run/protectedacc.scala index a08e7201fd15..85aa3438faa3 100644 --- a/tests/run/protectedacc.scala +++ b/tests/run/protectedacc.scala @@ -134,7 +134,7 @@ package p { abstract class X[T] extends PolyA[T] { - trait Inner extends B { + trait Inner extends this.B { def self: T; def self2: Node; def getB: Inner;