|
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
}
```
|