Skip to content

Commit

Permalink
Package object members are not conflicting with inherited
Browse files Browse the repository at this point in the history
  • Loading branch information
lrytz committed Jul 5, 2023
1 parent 062d9ca commit 181c1aa
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 13 deletions.
30 changes: 17 additions & 13 deletions compiler/src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
* the inherited member (has an overloaded alternative that) coincides with
* (an overloaded alternative of) the definition x.
*/
def checkNoOuterDefs(denot: Denotation, last: Context, prevCtx: Context): Unit =
def checkNoOuterDefs(denot: Denotation, ctx: Context, origCtx: Context): Unit =
def sameTermOrType(d1: SingleDenotation, d2: Denotation) =
d2.containsSym(d1.symbol) || d2.hasUniqueSym && {
val sym1 = d1.symbol
Expand All @@ -430,19 +430,23 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
else
(sym1.isAliasType || sym2.isAliasType) && d1.info =:= d2.info
}
val outer = last.outer
val owner = outer.owner
if (owner eq last.owner) && (outer.scope eq last.scope) then
checkNoOuterDefs(denot, outer, prevCtx)
else if !owner.isRoot then
val outerCtx = ctx.outer
val outerOwner = outerCtx.owner
if (outerOwner eq ctx.owner) && (outerCtx.scope eq ctx.scope) then
checkNoOuterDefs(denot, outerCtx, origCtx)
else if !outerOwner.isRoot then
val found =
if owner.is(Package) then
owner.denot.asClass.membersNamed(name)
if outerOwner.is(Package) then
def notInPackageObject(sym: Symbol) =
sym.owner == outerOwner || // sym.owner.isPackageObject is false if sym is defined in a parent of the package object
sym.owner.isPackageObject && sym.owner.name.endsWith(str.TOPLEVEL_SUFFIX) // top-level definitions
outerOwner.denot.asClass.membersNamed(name)
.filterWithPredicate(d => !d.symbol.is(Package)
&& notInPackageObject(d.symbol)
&& d.symbol.source.exists
&& isDefinedInCurrentUnit(d))
else
val scope = if owner.isClass then owner.info.decls else outer.scope
val scope = if outerOwner.isClass then outerOwner.info.decls else outerCtx.scope
scope.denotsNamed(name)
val competing = found.filterWithFlags(required, excluded | Synthetic)
if competing.exists then
Expand All @@ -451,14 +455,14 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
.exists
if !symsMatch && !suppressErrors then
report.errorOrMigrationWarning(
AmbiguousReference(name, Definition, Inheritance, prevCtx)(using outer),
AmbiguousReference(name, Definition, Inheritance, origCtx)(using outerCtx),
pos, from = `3.0`)
if migrateTo3 then
patch(Span(pos.span.start),
if prevCtx.owner == refctx.owner.enclosingClass then "this."
else s"${prevCtx.owner.name}.this.")
if origCtx.owner == refctx.owner.enclosingClass then "this."
else s"${origCtx.owner.name}.this.")
else
checkNoOuterDefs(denot, outer, prevCtx)
checkNoOuterDefs(denot, outerCtx, origCtx)

if isNewDefScope then
val defDenot = ctx.denotNamed(name, required, excluded)
Expand Down
36 changes: 36 additions & 0 deletions tests/neg/t12186.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package object p extends p.U {
def b: Int = 0
trait Y
}

package p {
trait U {
def a: Int = 0
trait X
}

object c
def c1 = 0 // top-level def
trait Z
trait T {
def a = 1
def b = 1
def c = 1
def c1 = 1

trait X
trait Y
trait Z
}

trait RR extends T {
def m1 = a // ok
def m2 = b // ok
def m3 = c // error
def m4 = c1 // error

def n1: X // ok
def n2: Y // ok
def n3: Z // error
}
}
4 changes: 4 additions & 0 deletions tests/neg/t12186b/A.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package object p extends p.U {
def b: Int = 0
trait Y
}
31 changes: 31 additions & 0 deletions tests/neg/t12186b/B.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package p {
trait U {
def a: Int = 0
trait X
}

object c
def c1 = 0 // top-level def
trait Z
trait T {
def a = 1
def b = 1
def c = 1
def c1 = 1

trait X
trait Y
trait Z
}

trait RR extends T {
def m1 = a // ok
def m2 = b // ok
def m3 = c // error
def m4 = c1 // error

def n1: X // ok
def n2: Y // ok
def n3: Z // error
}
}

0 comments on commit 181c1aa

Please sign in to comment.