diff options
Diffstat (limited to 'test/pending/run')
-rw-r--r-- | test/pending/run/instanceOfAndTypeMatching.scala | 193 |
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 + } +} |