summaryrefslogtreecommitdiff
path: root/test/files/run/t9920b.scala
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2016-09-13 13:43:43 +1000
committerJason Zaugg <jzaugg@gmail.com>2016-09-27 10:21:38 +1000
commite3e1e30c08d8bb532ac1d36d191fc8d4dbab0eb9 (patch)
tree5d175eb2155a16c96bc77c39ac74340bca16042e /test/files/run/t9920b.scala
parentde7cddd1905c730685f5ef2b74a6c0c1f30f2dd2 (diff)
downloadscala-e3e1e30c08d8bb532ac1d36d191fc8d4dbab0eb9.tar.gz
scala-e3e1e30c08d8bb532ac1d36d191fc8d4dbab0eb9.tar.bz2
scala-e3e1e30c08d8bb532ac1d36d191fc8d4dbab0eb9.zip
SI-9920 Avoid linkage errors with captured local objects + self types
An outer parameter of a nested class is typed with the self type of the enclosing class: ``` class C; trait T { _: C => def x = 42; class D { x } } ``` leads to: ``` class D extends Object { def <init>($outer: C): T.this.D = { D.super.<init>(); () }; D.this.$outer().$asInstanceOf[T]().x(); ``` Note that a cast is inserted before the call to `x`. If we modify that a little, to instead capture a local module: ``` class C; trait T { _: C => def y { object O; class D { O } } } ``` Scala 2.11 used to generate (after lambdalift): ``` class D$1 extends Object { def <init>($outer: C, O$module$1: runtime.VolatileObjectRef): C#D$1 = { D$1.super.<init>(); () }; D$1.this.$outer().O$1(O$module$1); ``` That isn't type correct, `D$1.this.$outer() : C` does not have a member `O$1`. However, the old trait encoding would rewrite this in mixin to: ``` T$class.O$1($outer, O$module$1); ``` Trait implementation methods also used to accept the self type: ``` trait T$class { final <stable> def O$1($this: C, O$module$1: runtime.VolatileObjectRef): T$O$2.type } ``` So the problem was hidden. This commit changes replaces manual typecheckin of the selection in LambdaLift with a use of the local (erasure) typer, which will add casts as needed. For `run/t9220.scala`, this changes the post LambdaLift AST as follows: ``` class C1$1 extends Object { def <init>($outer: C0, Local$module$1: runtime.VolatileObjectRef): T#C1$1 = { C1$1.super.<init>(); () }; - C1$1.this.$outer.Local$1(Local$module$1); + C1$1.this.$outer.$asInstanceOf[T]().Local$1(Local$module$1); <synthetic> <paramaccessor> <artifact> private[this] val $outer: C0 = _; <synthetic> <stable> <artifact> def $outer(): C0 = C1$1.this.$outer } ```
Diffstat (limited to 'test/files/run/t9920b.scala')
-rw-r--r--test/files/run/t9920b.scala17
1 files changed, 17 insertions, 0 deletions
diff --git a/test/files/run/t9920b.scala b/test/files/run/t9920b.scala
new file mode 100644
index 0000000000..fab196b669
--- /dev/null
+++ b/test/files/run/t9920b.scala
@@ -0,0 +1,17 @@
+class C0
+trait T {
+ def test = {
+ object Local
+
+ class C1 {
+ Local
+ }
+ new C1()
+ }
+}
+
+object Test extends C0 with T {
+ def main(args: Array[String]): Unit = {
+ test
+ }
+}