aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-11-14 16:11:31 +0100
committerMartin Odersky <odersky@gmail.com>2014-11-14 16:11:31 +0100
commit4d5a901d10a28c286f8754134f5030daae0d239b (patch)
tree41936bfc93fb242db330aeac3627038e9c1ef142
parent9dae49b8994f72f2b4b83665c53a63b49896c5de (diff)
downloaddotty-4d5a901d10a28c286f8754134f5030daae0d239b.tar.gz
dotty-4d5a901d10a28c286f8754134f5030daae0d239b.tar.bz2
dotty-4d5a901d10a28c286f8754134f5030daae0d239b.zip
Fix OverridingPairs
OverridingPairs had several bugs which caused pairs to be lost, which caused missing overrides checks. Fixing OverridingPairs revealed several test failures (and a problem in Synthetics generation which was fixed in the last commit). Tests that became negative are all moved into neg/overrides.scala, and the original versions in pos were fixed.
-rw-r--r--src/dotty/tools/dotc/transform/OverridingPairs.scala30
-rw-r--r--src/dotty/tools/dotc/typer/RefChecks.scala2
-rw-r--r--test/dotc/tests.scala2
-rw-r--r--tests/neg/over.scala10
-rw-r--r--tests/neg/overrides.scala59
-rw-r--r--tests/pos/overrides.scala2
-rw-r--r--tests/pos/synthetics.scala8
-rw-r--r--tests/pos/t0599.scala4
-rw-r--r--tests/pos/t2809.scala2
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()
}
}