summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2011-09-08 18:37:18 +0000
committerPaul Phillips <paulp@improving.org>2011-09-08 18:37:18 +0000
commitf32a32b1b33c9d7ccd62467e3e10cb69930023c8 (patch)
tree47ca34246fbdd255f2191ced68bd708e609d22d2 /test
parent52c1d019d63d2fffadc8f3f159d654187ac61ece (diff)
downloadscala-f32a32b1b33c9d7ccd62467e3e10cb69930023c8.tar.gz
scala-f32a32b1b33c9d7ccd62467e3e10cb69930023c8.tar.bz2
scala-f32a32b1b33c9d7ccd62467e3e10cb69930023c8.zip
Allow for the overriding of objects.
Various and sundry manipulations to allow for objects to be overridden when the mood is right. It is not enabled by default. The major contributor of change turned out to be the decoupling of the FINAL flag (and the "isFinal" test which examines only that flag) and the many semantics which were attributed to this interpretation of finality in different circumstances. Since objects no longer have the FINAL flag automatically applied (only top-level objects and those marked final in source code do) we need apply a more nuanced test. Fortunately there is such a nuanced test: isEffectivelyFinal, which is always true if the FINAL flag is set but also in various other circumstances. In almost every case, you should be testing "isEffectivelyFinal", not "isFinal". To enable overridable objects, use: -Yoverride-objects -Xexperimental // includes the above and others Remain to be done: working out transition logistics. Most likely this would involve bumping the scala signature version, and all objects in versions before that would be assumed final. Review by moors.
Diffstat (limited to 'test')
-rw-r--r--test/files/neg/override-object-flag.check5
-rw-r--r--test/files/neg/override-object-flag.scala3
-rw-r--r--test/files/neg/override-object-no.check23
-rw-r--r--test/files/neg/override-object-no.flags1
-rw-r--r--test/files/neg/override-object-no.scala45
-rw-r--r--test/files/neg/t276.check2
-rw-r--r--test/files/pos/override-object-yes.flags1
-rw-r--r--test/files/pos/override-object-yes.scala40
8 files changed, 119 insertions, 1 deletions
diff --git a/test/files/neg/override-object-flag.check b/test/files/neg/override-object-flag.check
new file mode 100644
index 0000000000..152d31ff8a
--- /dev/null
+++ b/test/files/neg/override-object-flag.check
@@ -0,0 +1,5 @@
+override-object-flag.scala:3: error: overriding object Foo in trait A of type object B.this.Foo;
+ object Foo cannot override final member
+trait B extends A { override object Foo }
+ ^
+one error found
diff --git a/test/files/neg/override-object-flag.scala b/test/files/neg/override-object-flag.scala
new file mode 100644
index 0000000000..74d00dd445
--- /dev/null
+++ b/test/files/neg/override-object-flag.scala
@@ -0,0 +1,3 @@
+// no flag enabling it, fail
+trait A { object Foo }
+trait B extends A { override object Foo }
diff --git a/test/files/neg/override-object-no.check b/test/files/neg/override-object-no.check
new file mode 100644
index 0000000000..c509634b3f
--- /dev/null
+++ b/test/files/neg/override-object-no.check
@@ -0,0 +1,23 @@
+override-object-no.scala:14: error: overriding object Bar in trait Foo with object Bar in trait Foo2:
+an overriding object must conform to the overridden object's class bound;
+ found : case1.Bippy with ScalaObject
+ required: case1.Bippy with case1.Bippo with ScalaObject
+ override object Bar extends Bippy { // err
+ ^
+override-object-no.scala:21: error: overriding object Bar in trait Quux1 with object Bar in trait Quux2:
+an overriding object must conform to the overridden object's class bound;
+ found : java.lang.Object with ScalaObject{def g: java.lang.String}
+ required: java.lang.Object with ScalaObject{def g: Int}
+ trait Quux2 extends Quux1 { override object Bar { def g = "abc" } } // err
+ ^
+override-object-no.scala:25: error: overriding object Bar in trait Quux3 of type object Quux4.this.Bar;
+ object Bar cannot override final member
+ trait Quux4 extends Quux3 { override object Bar } // err
+ ^
+override-object-no.scala:43: error: overriding object A in class Foo with object A in class P2:
+an overriding object must conform to the overridden object's class bound;
+ found : case2.Bar[List[String]] with ScalaObject
+ required: case2.Bar[Traversable[String]] with ScalaObject
+ override object A extends Bar[List[String]] // err
+ ^
+four errors found
diff --git a/test/files/neg/override-object-no.flags b/test/files/neg/override-object-no.flags
new file mode 100644
index 0000000000..22e9a95c4f
--- /dev/null
+++ b/test/files/neg/override-object-no.flags
@@ -0,0 +1 @@
+-Yoverride-objects \ No newline at end of file
diff --git a/test/files/neg/override-object-no.scala b/test/files/neg/override-object-no.scala
new file mode 100644
index 0000000000..745cdb2332
--- /dev/null
+++ b/test/files/neg/override-object-no.scala
@@ -0,0 +1,45 @@
+// See also pos/override-object-yes.scala
+
+package case1 {
+ // Missing interface in overriding object
+ class Bippy { def f = 1 }
+ trait Bippo
+
+ trait Foo {
+ object Bar extends Bippy with Bippo { override def f = 2 }
+ def f(x: Bippo)
+ def g = f(Bar)
+ }
+ trait Foo2 extends Foo {
+ override object Bar extends Bippy { // err
+ override def f = 3
+ }
+ }
+
+ // type mismatch in member
+ trait Quux1 { object Bar { def g = 55 } }
+ trait Quux2 extends Quux1 { override object Bar { def g = "abc" } } // err
+
+ // still can't override final objects!
+ trait Quux3 { final object Bar { } }
+ trait Quux4 extends Quux3 { override object Bar } // err
+}
+
+// type parameter as-seen-from business
+package case2 {
+ // invariance (see pos for the covariant case)
+ class Bar[T]
+
+ class Foo[T] {
+ object A extends Bar[T]
+ }
+
+ class Baz[S] extends Foo[S] {
+ override object A extends Bar[S]
+ }
+
+ class P1 extends Foo[Traversable[String]]
+ class P2 extends P1 {
+ override object A extends Bar[List[String]] // err
+ }
+}
diff --git a/test/files/neg/t276.check b/test/files/neg/t276.check
index 7d37f5cfa1..b241953a22 100644
--- a/test/files/neg/t276.check
+++ b/test/files/neg/t276.check
@@ -1,5 +1,5 @@
t276.scala:6: error: overriding type Bar in class Foo, which equals (Int, Int);
- class Bar cannot be used here - classes and objects can only override abstract types
+ class Bar cannot be used here - classes can only override abstract types
class Bar
^
one error found
diff --git a/test/files/pos/override-object-yes.flags b/test/files/pos/override-object-yes.flags
new file mode 100644
index 0000000000..22e9a95c4f
--- /dev/null
+++ b/test/files/pos/override-object-yes.flags
@@ -0,0 +1 @@
+-Yoverride-objects \ No newline at end of file
diff --git a/test/files/pos/override-object-yes.scala b/test/files/pos/override-object-yes.scala
new file mode 100644
index 0000000000..858f9b21fc
--- /dev/null
+++ b/test/files/pos/override-object-yes.scala
@@ -0,0 +1,40 @@
+package case1 {
+ class Bippy {
+ def f = 1
+ }
+
+ trait Foo {
+ object Bar extends Bippy {
+ override def f = 2
+ }
+ }
+
+ trait Foo2 extends Foo {
+ override object Bar extends Bippy {
+ override def f = 3
+ }
+ }
+
+ trait Foo3 {
+ object Bar {
+ def g: Traversable[Int] = Nil
+ }
+ }
+ trait Foo4 extends Foo3 {
+ override object Bar {
+ def g: List[Int] = Nil
+ }
+ }
+}
+
+package case2 {
+ class Bar[T]
+
+ class Foo[T] {
+ object A extends Bar[T]
+ }
+
+ class Baz[S] extends Foo[S] {
+ override object A extends Bar[S]
+ }
+}