diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2013-01-20 12:31:22 +0100 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2013-01-20 17:02:11 +0100 |
commit | 1a7de4314ac72bca81e31ad3ac0af7bee7eed26b (patch) | |
tree | 45bf4f3f2e81dc32256da07b2225aa99e0cd4f82 /test/files/neg/t6666.scala | |
parent | 6f72ed85c3882d2a8c824a41e6e42d7f33b8d1d6 (diff) | |
download | scala-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.scala | 132 |
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 |