summaryrefslogtreecommitdiff
path: root/test/pending/run/instanceOfAndTypeMatching.scala
diff options
context:
space:
mode:
Diffstat (limited to 'test/pending/run/instanceOfAndTypeMatching.scala')
-rw-r--r--test/pending/run/instanceOfAndTypeMatching.scala193
1 files changed, 193 insertions, 0 deletions
diff --git a/test/pending/run/instanceOfAndTypeMatching.scala b/test/pending/run/instanceOfAndTypeMatching.scala
new file mode 100644
index 0000000000..9ab2d6c3c4
--- /dev/null
+++ b/test/pending/run/instanceOfAndTypeMatching.scala
@@ -0,0 +1,193 @@
+// Summary of incorrect or questionable behavior.
+// Full code and successful parts follow.
+
+object Summary {
+ class Outer {
+ class Inner { }
+ def f() = { class MethodInner ; new MethodInner }
+ }
+
+ // 1 static issue:
+ //
+ // Given method in MethodInner: def g(other: MethodInner) = ()
+ // method1.g(method1) fails to compile with type error.
+ //
+ // Note that this cannot be worked around by widening the return type
+ // of f() because MethodInner is declared inside of f. So there is no way
+ // I see for a class declared inside a method to receive members of its
+ // own declared type -- not only the narrow type of those from this
+ // instance, but ANY members, because there is no Foo#Bar syntax which will
+ // traverse a method.
+ //
+ // 4 runtime issues:
+ //
+ // From the outside: inner1.isInstanceOf[outer2.Inner] is true, should (maybe) be false
+ // From inside inner1: inner2.isInstanceOf[Outer.this.Inner] is true, should (maybe) be false
+ // From the outside: inner1 match { case _: outer2.Inner => true ... } is true, should definitely be false
+ // From inside method1: method2 match { case _: MethodInner => true ... } is true, should definitely be false
+ //
+ // Note that the fact that every test returns true on instances of MethodInner means
+ // that it is impossible to draw any type distinction between instances. As far as one
+ // can tell, they are all of the same type regardless not only of whether they were
+ // created on the same method invocation but whether they are contained in the same
+ // instance of Outer.
+ //
+ // WRT "same method invocation", see Iterator.duplicate for an example of this.
+}
+
+// Tests
+
+class Outer {
+ class Inner {
+ def passOuter(other: Outer) = () // pass any Outer
+ def passThisType(other: Outer.this.type) = () // pass only this Outer instance
+ def passInner(other: Inner) = () // pass only Inners from this Outer instance
+ def passInner2(other: Outer.this.Inner) = () // same as above
+ def passInnerSharp(other: Outer#Inner) = () // pass any Inner
+
+ def compareSimpleWithTypeMatch(other: Any) = other match {
+ case _: Inner => true
+ case _ => false
+ }
+ def compareSimpleWithInstanceOf(other: Any) = other.isInstanceOf[Inner]
+
+ def compareSharpWithTypeMatch(other: Any) = {
+ other match {
+ case _: Outer#Inner => true
+ case _ => false
+ }
+ }
+ def compareSharpWithInstanceOf(other: Any) = other.isInstanceOf[Outer#Inner]
+
+ def comparePathWithTypeMatch(other: Any) = other match {
+ case _: Outer.this.Inner => true
+ case _ => false
+ }
+ def comparePathWithInstanceOf(other: Any) = other.isInstanceOf[Outer.this.Inner]
+ }
+
+ def f() = {
+ class MethodInner {
+ def passOuter(other: Outer) = () // pass any Outer
+ def passThisType(other: Outer.this.type) = () // pass only this Outer instance
+ def passInner(other: Inner) = () // pass only Inners from this Outer instance
+ def passInner2(other: Outer.this.Inner) = () // same as above
+ def passInnerSharp(other: Outer#Inner) = () // pass any Inner
+ def passMethodInner(other: MethodInner) = () // pass only MethodInners from this Outer instance
+ // is there any way to refer to Outer#MethodInner? Not that there should be.
+
+ def compareWithInstanceOf(other: Any) = other.isInstanceOf[MethodInner]
+ def compareWithTypeMatch(other: Any) = other match {
+ case _: MethodInner => true
+ case _ => false
+ }
+ }
+
+ new MethodInner
+ }
+}
+
+object Test
+{
+ val outer1 = new Outer
+ val outer2 = new Outer
+ val inner1 = new outer1.Inner
+ val inner2 = new outer2.Inner
+ val method1 = outer1.f()
+ val method2 = outer2.f()
+
+ def testInnerStatic = {
+ // these should all work
+ inner1.passOuter(outer1)
+ inner1.passOuter(outer2)
+ inner1.passThisType(outer1)
+ inner1.passInner(inner1)
+ inner1.passInner2(inner1)
+ inner1.passInnerSharp(inner1)
+ inner1.passInnerSharp(inner2)
+
+ // these should all fail to compile, and do
+ //
+ // inner1.passThisType(outer2)
+ // inner1.passInner(inner2)
+ // inner1.passInner2(inner2)
+ }
+ def testInnerRuntime = {
+ println("testInnerRuntime\n")
+
+ List("These should be true under any scenario: ",
+ inner1.isInstanceOf[outer1.Inner] ,
+ inner1.isInstanceOf[Outer#Inner] ,
+ inner1 match { case _: Outer#Inner => true ; case _ => false } ,
+ inner1 match { case _: outer1.Inner => true ; case _ => false } ,
+ inner1.compareSharpWithTypeMatch(inner2) ,
+ inner1.compareSharpWithInstanceOf(inner2)
+ ) foreach println
+
+ List("These should be true under current proposal: ",
+ inner1.compareSimpleWithInstanceOf(inner2)
+ ) foreach println
+
+ List("These should be false under current proposal: ",
+ inner1.compareSimpleWithTypeMatch(inner2) ,
+ inner1.comparePathWithTypeMatch(inner2)
+ ) foreach println
+
+ List("These return true but I think should return false: ",
+ inner1.isInstanceOf[outer2.Inner] , // true
+ inner1.comparePathWithInstanceOf(inner2) // true
+ ) foreach println
+
+ List("These are doing the wrong thing under current proposal",
+ inner1 match { case _: outer2.Inner => true ; case _ => false } // should be false
+ ) foreach println
+ }
+
+ def testMethodInnerStatic = {
+ // these should all work
+ method1.passOuter(outer1)
+ method1.passOuter(outer2)
+ method1.passThisType(outer1)
+ method1.passInner(inner1)
+ method1.passInner2(inner1)
+ method1.passInnerSharp(inner1)
+ method1.passInnerSharp(inner2)
+ // This fails with:
+ //
+ // a.scala:114: error: type mismatch;
+ // found : Test.method1.type (with underlying type MethodInner forSome { type MethodInner <: java.lang.Object with ScalaObject{def passOuter(other: Outer): Unit; def passThisType(other: Test.outer1.type): Unit; def passInner(other: Test.outer1.Inner): Unit; def passInner2(other: Test.outer1.Inner): Unit; def passInnerSharp(other: Outer#Inner): Unit; def passMethodInner(other: MethodInner): Unit} })
+ // required: MethodInner where type MethodInner <: java.lang.Object with ScalaObject{def passOuter(other: Outer): Unit; def passThisType(other: Test.outer1.type): Unit; def passInner(other: Test.outer1.Inner): Unit; def passInner2(other: Test.outer1.Inner): Unit; def passInnerSharp(other: Outer#Inner): Unit; def passMethodInner(other: MethodInner): Unit}
+ // method1.passMethodInner(method1)
+ // ^
+ // method1.passMethodInner(method1)
+
+ // these should all fail to compile, and do
+ //
+ // method1.passThisType(outer2)
+ // method1.passInner(inner2)
+ // method1.passInner2(inner2)
+ // method1.passMethodInner(method2)
+ }
+
+ def testMethodInnerRuntime = {
+ println("\ntestMethodInnerRuntime\n")
+
+ List("These should be true under any scenario: ",
+ method1.compareWithInstanceOf(method1) ,
+ method1.compareWithTypeMatch(method1)
+ ) foreach println
+
+ List("These should be true under current proposal: ",
+ method1.compareWithInstanceOf(method2)
+ ) foreach println
+
+ List("These are doing the wrong thing under current proposal",
+ method1.compareWithTypeMatch(method2) // should be false
+ ) foreach println
+ }
+
+ def main(args: Array[String]): Unit = {
+ testInnerRuntime
+ testMethodInnerRuntime
+ }
+}