Skip to content

ExplicitOuter doesn't match Scala 2.12's outer types #4342

@gsps

Description

@gsps

Scala 2.12 appears to use the declared self type of the enclosing class as the outer type when transforming inner classes. Dotty doesn't match this behavior and uses the enclosing class itself, leading to NoSuchMethodErrors wrt. Scala 2.12 classes upon executing the Dotty-compiled code. Here's a minimal example:

Consider the following code, compiled with 2.12:

package foo

class A extends B

trait B { this: A =>
  class C
}

object a extends A

and the following code, compiled with Dotty:

object Scala2_12FromDotty {
  new foo.a.C  // runtime error: trying to call constructor of C with a B instead of an A
}

We can see the discrepancy in the generated code. That is, javap -p 'target/scala-2.12/classes/foo/B$C.class' yields:

Compiled from "Foo.scala"
public class foo.B$C {
  public final foo.A $outer;
  public foo.A foo$B$C$$$outer();
  public foo.B$C(foo.A);
}

whereas javap -c Scala2_12FromDotty$.class yields

Compiled from "Scala2_12FromDotty.scala"
public final class Scala2_12FromDotty$ {
  (...)
  public Scala2_12FromDotty$();
    Code:
      (...)
      12: getstatic     #25                 // Field foo/a$.MODULE$:Lfoo/a$;
      15: invokespecial #28                 // Method foo/B$C."<init>":(Lfoo/B;)V
      (...)
}

I tried to look into the related phases a bit, but I'm not sure whether this should be fixed in ExplicitOuter or by transforming infos, applications and defdefs later, for instance, as an extension of LinkScala2Impls.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions