diff options
-rw-r--r-- | src/dotty/tools/dotc/transform/OverridingPairs.scala | 30 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/RefChecks.scala | 2 | ||||
-rw-r--r-- | test/dotc/tests.scala | 2 | ||||
-rw-r--r-- | tests/neg/over.scala | 10 | ||||
-rw-r--r-- | tests/neg/overrides.scala | 59 | ||||
-rw-r--r-- | tests/pos/overrides.scala | 2 | ||||
-rw-r--r-- | tests/pos/synthetics.scala | 8 | ||||
-rw-r--r-- | tests/pos/t0599.scala | 4 | ||||
-rw-r--r-- | tests/pos/t2809.scala | 2 |
9 files changed, 99 insertions, 20 deletions
diff --git a/src/dotty/tools/dotc/transform/OverridingPairs.scala b/src/dotty/tools/dotc/transform/OverridingPairs.scala index d0bc90389..76d5d3613 100644 --- a/src/dotty/tools/dotc/transform/OverridingPairs.scala +++ b/src/dotty/tools/dotc/transform/OverridingPairs.scala @@ -2,7 +2,7 @@ package dotty.tools.dotc package transform import core._ -import Flags._, Symbols._, Contexts._, Types._, Scopes._ +import Flags._, Symbols._, Contexts._, Types._, Scopes._, Decorators._ import util.HashSet import collection.mutable.HashMap import collection.immutable.BitSet @@ -18,6 +18,8 @@ import scala.annotation.tailrec */ object OverridingPairs { + private val ExcludedType = ExpandedName.toTypeFlags | TypeArgument + /** The cursor class * @param base the base class that contains the overriding pairs */ @@ -29,7 +31,10 @@ object OverridingPairs { * But it may be refined in subclasses. */ protected def exclude(sym: Symbol): Boolean = - sym.isConstructor || sym.is(PrivateLocal) + sym.isConstructor || + sym.is(Private) || + sym.is(Module) && sym.is(Synthetic) || + sym.is(ExcludedType) /** The parents of base (may also be refined). */ @@ -77,7 +82,7 @@ object OverridingPairs { } private def hasCommonParentAsSubclass(cls1: Symbol, cls2: Symbol): Boolean = - (subParents(cls1) intersect subParents(cls2)).isEmpty + (subParents(cls1) intersect subParents(cls2)).nonEmpty /** The scope entries that have already been visited as overridden * (maybe excluded because of hasCommonParentAsSubclass). @@ -107,21 +112,16 @@ object OverridingPairs { overriding = curEntry.sym if (nextEntry ne null) { val overridingOwner = overriding.owner + def qualifies(candidate: Symbol) = + candidate.canMatchInheritedSymbols && + overriding.owner != candidate.owner && + matches(overriding, candidate) && + !exclude(candidate) && + !exclude(overriding) do { do { nextEntry = decls.lookupNextEntry(nextEntry); - /* DEBUG - if ((nextEntry ne null) && - !(nextEntry.sym hasFlag PRIVATE) && - !(overriding.owner == nextEntry.sym.owner) && - !matches(overriding, nextEntry.sym)) - println("skipping "+overriding+":"+self.memberType(overriding)+overriding.locationString+" to "+nextEntry.sym+":"+self.memberType(nextEntry.sym)+nextEntry.sym.locationString) - */ - } while ((nextEntry ne null) && - (//!!!!nextEntry.sym.canMatchInheritedSymbols || - (overriding.owner == nextEntry.sym.owner) || - (!matches(overriding, nextEntry.sym)) || - (exclude(overriding)))) + } while ((nextEntry ne null) && !qualifies(nextEntry.sym)) if (nextEntry ne null) visited.addEntry(nextEntry) // skip nextEntry if a class in `parents` is a subclass of the owners of both // overriding and nextEntry.sym diff --git a/src/dotty/tools/dotc/typer/RefChecks.scala b/src/dotty/tools/dotc/typer/RefChecks.scala index f45966741..2ae9a5b97 100644 --- a/src/dotty/tools/dotc/typer/RefChecks.scala +++ b/src/dotty/tools/dotc/typer/RefChecks.scala @@ -246,7 +246,7 @@ object RefChecks { } else if (!other.is(Deferred) && member.isClass) { overrideError("cannot be used here - classes can only override abstract types") } else if (other.isEffectivelyFinal) { // (1.2) - overrideError("cannot override final member") + overrideError(i"cannot override final member ${other.showLocated}") } else if (!other.is(Deferred) && !isDefaultGetter(other.name) && !member.is(AnyOverrideOrSynthetic)) { // (*) Synthetic exclusion for (at least) default getters, fixes SI-5178. We cannot assign the OVERRIDE flag to // the default getter: one default getter might sometimes override, sometimes not. Example in comment on ticket. diff --git a/test/dotc/tests.scala b/test/dotc/tests.scala index 966c231e4..fb2b747a6 100644 --- a/test/dotc/tests.scala +++ b/test/dotc/tests.scala @@ -72,6 +72,8 @@ class tests extends CompilerTest { @Test def neg_autoTupling = compileFile(posDir, "autoTuplingTest", "-language:noAutoTupling" :: Nil, xerrors = 4) @Test def neg_autoTupling2 = compileFile(negDir, "autoTuplingTest", xerrors = 4) @Test def neg_companions = compileFile(negDir, "companions", xerrors = 1) + @Test def neg_over = compileFile(negDir, "over", xerrors = 1) + @Test def neg_overrides = compileFile(negDir, "overrides", xerrors = 4) @Test def neg_projections = compileFile(negDir, "projections", xerrors = 1) @Test def neg_i39 = compileFile(negDir, "i39", xerrors = 1) @Test def neg_i50_volatile = compileFile(negDir, "i50-volatile", xerrors = 4) diff --git a/tests/neg/over.scala b/tests/neg/over.scala new file mode 100644 index 000000000..488d71614 --- /dev/null +++ b/tests/neg/over.scala @@ -0,0 +1,10 @@ +trait T { + def x = 1 +} + +class C extends T { + + val x = 2 + override val y = 2 + +} diff --git a/tests/neg/overrides.scala b/tests/neg/overrides.scala new file mode 100644 index 000000000..4befe1623 --- /dev/null +++ b/tests/neg/overrides.scala @@ -0,0 +1,59 @@ + abstract class FooA { + type A <: Ax; + abstract class Ax; + abstract class InnerA { + type B <: A; + def doB : B; + } + } + trait FooB extends FooA { + type A <: Ax; + trait Ax extends super.Ax { def xxx : Int; } + abstract class InnerB extends InnerA { + // type B <: A; + val a : A = doB; + a.xxx; + doB.xxx; + } + } + +package p1 { + abstract class T1 { + protected def bug(p: Int = 1): Int // without 'protected' compiles fine + } +} +package p2 { // all being in the same package compiles fine + import p1._ + abstract class T2 extends T1 { + class A { + bug() + } + } + + abstract class T3 extends T2 { + class A { + bug() + } + } +} + +class A[T] { + + def f(x: T)(y: T = x) = y + +} + +class B extends A[Int] { + + def f(x: Int)(y: Int) = y + + f(2)() + +} + +class X { + def f: A[Int] = ??? +} +class Y extends X { + def f: A[Int] = ??? +} diff --git a/tests/pos/overrides.scala b/tests/pos/overrides.scala index 3d254ea70..97402f773 100644 --- a/tests/pos/overrides.scala +++ b/tests/pos/overrides.scala @@ -6,7 +6,7 @@ class A[T] { class B extends A[Int] { - def f(x: Int)(y: Int) = y + override def f(x: Int)(y: Int) = y f(2)() diff --git a/tests/pos/synthetics.scala b/tests/pos/synthetics.scala index c7d49df70..c870cb1a4 100644 --- a/tests/pos/synthetics.scala +++ b/tests/pos/synthetics.scala @@ -2,3 +2,11 @@ case class C(x: Int, var y: String) { } + +class Top { + + final override def hashCode: Int = 2 + +} + +case class Sub() extends Top diff --git a/tests/pos/t0599.scala b/tests/pos/t0599.scala index 885159af6..6445fa9fb 100644 --- a/tests/pos/t0599.scala +++ b/tests/pos/t0599.scala @@ -7,8 +7,8 @@ abstract class FooA { } } trait FooB extends FooA { - type A <: Ax; - trait Ax extends super.Ax { def xxx : Int; } + type A <: Axx; + trait Axx extends super.Ax { def xxx : Int; } abstract class InnerB extends InnerA { // type B <: A; val a : A = doB; diff --git a/tests/pos/t2809.scala b/tests/pos/t2809.scala index 1f68b0b07..1e9ec60d2 100644 --- a/tests/pos/t2809.scala +++ b/tests/pos/t2809.scala @@ -12,7 +12,7 @@ package p2 { // all being in the same package compiles fine } abstract class T3 extends T2 { - class A { + class A2 { bug() } } |