summaryrefslogtreecommitdiff
path: root/test/files/neg/t6666.scala
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2013-01-20 12:31:22 +0100
committerJason Zaugg <jzaugg@gmail.com>2013-01-20 17:02:11 +0100
commit1a7de4314ac72bca81e31ad3ac0af7bee7eed26b (patch)
tree45bf4f3f2e81dc32256da07b2225aa99e0cd4f82 /test/files/neg/t6666.scala
parent6f72ed85c3882d2a8c824a41e6e42d7f33b8d1d6 (diff)
downloadscala-1a7de4314ac72bca81e31ad3ac0af7bee7eed26b.tar.gz
scala-1a7de4314ac72bca81e31ad3ac0af7bee7eed26b.tar.bz2
scala-1a7de4314ac72bca81e31ad3ac0af7bee7eed26b.zip
SI-6666 Restrict hidden `this` access in self/super calls.
Detect when classes (user authored or compiler generated) local to a self or super constructor argument would require premature access to the in-construction instance. The same restriction applies for classes and objects; for objects, the premature access would result in a null via MODULE$ field. A residual error has been lodged as SI-6997. I'd like to remove calls to `Symbol#outerClass` (which relies on the flaky flag INCONSTRUCTOR, see my comments in the JIRA issue for more discussion) from `LambdaLift` and `ExplicitOuter`, and instead use the stack of active self/super calls to know when to skip an enclosing class. That will obviate that flag.
Diffstat (limited to 'test/files/neg/t6666.scala')
-rw-r--r--test/files/neg/t6666.scala132
1 files changed, 132 insertions, 0 deletions
diff --git a/test/files/neg/t6666.scala b/test/files/neg/t6666.scala
new file mode 100644
index 0000000000..d37ffaf141
--- /dev/null
+++ b/test/files/neg/t6666.scala
@@ -0,0 +1,132 @@
+class C(a: Any)
+object F {
+ def byname(a: => Any) = println(a)
+ def hof(a: () => Any) = println(a())
+}
+
+class COkay extends C(0) {
+ def this(a: Any) {
+ this()
+ def x = "".toString
+ F.byname(x)
+ }
+}
+
+//
+// The thunk's apply method accesses the MODULE$
+// field before it is set.
+//
+// 0: getstatic #23; //Field O1$.MODULE$:LO1$;
+// 3: invokevirtual #26; //Method O1$.O1$$x$1:()Ljava/lang/String;
+object O1 extends C({
+ def x = "".toString
+ F.byname(x)
+})
+
+// java.lang.NullPointerException
+// at O2$$anonfun$$init$$1.apply(<console>:11)
+object O2 extends C({
+ lazy val x = "".toString
+ F.byname(x)
+})
+
+// java.lang.NullPointerException
+// at O3$$anonfun$$init$$1.apply(<console>:11)
+object O3 extends C({
+ def x = "".toString
+ F.hof(() => x)
+})
+
+// Okay, the nested classes don't get an outer pointer passed,
+// just an extra param for `x: String`.
+object O6 extends C({
+ val x = "".toString
+ F.byname(x); F.hof(() => x); (new { val xx = x }.xx)
+})
+
+
+class C1 extends C({
+ def x = "".toString
+ F.byname(x)
+})
+class C2 extends C({
+ lazy val x = "".toString
+ F.byname(x)
+})
+class C3 extends C({
+ def x = "".toString
+ F.hof(() => x)
+})
+class C4 extends C({
+ def x = "".toString
+ object Nested { def xx = x}
+ Nested.xx
+})
+class C5 extends C({
+ def x = "".toString
+ val y = {
+ object Nested { def xx = x}
+ Nested.xx
+ }
+})
+
+// okay, for same reason as O6
+class C6 extends C({
+ val x = "".toString
+ F.byname(x); F.hof(() => x); (new { val xx = x }.xx)
+})
+
+class C11(a: Any) {
+ def this() = {
+ this({
+ def x = "".toString
+ F.byname(x)
+ })
+ }
+}
+
+// Crashes earlier in lazyVals.
+// class C12(a: Any) {
+// def this() = {
+// this({
+// lazy val x = "".toString
+// F.byname(x)
+// })
+// }
+// }
+
+class C13(a: Any) {
+ def this() = {
+ this({
+ def x = "".toString
+ F.hof(() => x)
+ })
+ }
+}
+
+class C14(a: Any) {
+ def this() = {
+ this({
+ def x = "".toString
+ object Nested { def xx = x}
+ Nested.xx
+ })
+ }
+}
+
+class C15(a: Any) {
+ def this() = {
+ this({
+ def x = "".toString
+ val y = {
+ object Nested { def xx = x}
+ Nested.xx
+ }
+ })
+ }
+}
+
+class COuter extends C({
+ def foo = 0
+ class CInner extends C({foo})
+}) \ No newline at end of file