diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2016-09-13 13:43:43 +1000 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2016-09-27 10:21:38 +1000 |
commit | e3e1e30c08d8bb532ac1d36d191fc8d4dbab0eb9 (patch) | |
tree | 5d175eb2155a16c96bc77c39ac74340bca16042e /build.sbt | |
parent | de7cddd1905c730685f5ef2b74a6c0c1f30f2dd2 (diff) | |
download | scala-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 'build.sbt')
0 files changed, 0 insertions, 0 deletions