From e3e1e30c08d8bb532ac1d36d191fc8d4dbab0eb9 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Tue, 13 Sep 2016 13:43:43 +1000 Subject: 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 ($outer: C): T.this.D = { D.super.(); () }; 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 ($outer: C, O$module$1: runtime.VolatileObjectRef): C#D$1 = { D$1.super.(); () }; 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 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 ($outer: C0, Local$module$1: runtime.VolatileObjectRef): T#C1$1 = { C1$1.super.(); () }; - C1$1.this.$outer.Local$1(Local$module$1); + C1$1.this.$outer.$asInstanceOf[T]().Local$1(Local$module$1); private[this] val $outer: C0 = _; def $outer(): C0 = C1$1.this.$outer } ``` --- test/files/pos/t9920.scala | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 test/files/pos/t9920.scala (limited to 'test/files/pos') diff --git a/test/files/pos/t9920.scala b/test/files/pos/t9920.scala new file mode 100644 index 0000000000..8612618cc4 --- /dev/null +++ b/test/files/pos/t9920.scala @@ -0,0 +1,6 @@ +object Test { + def o = { + def i: Int = { i; 0 } + i + } +} -- cgit v1.2.3