Skip to content

Nested generic class requires explicit outer parameter when used from Java #10889

@lrytz

Description

@lrytz
➜  o cat Test.scala
package p
abstract class O {
  class I[T](s: String)
}
➜  o scalac Test.scala
➜  o cat Test.java
public class Test {
  public void foo() {
    p.O l = null;
    p.O.I<Object> s = l.new I<Object>(/*l,*/ "foo");
  }
}
➜  o javac Test.java
Test.java:4: error: constructor I in class O.I<T> cannot be applied to given types;
    p.O.I<Object> s = l.new I<Object>(/*l,*/ "foo");
                        ^
  required: O,String
  found: String
  reason: actual and formal argument lists differ in length
  where T is a type-variable:
    T extends Object declared in class O.I
1 error

It compiles when un-commenting the l constructor argument.

If we define O in Java:

➜  o cat O.java
package p;
public abstract class O {
  public class I<T> {
    public I(String s) { }
  }
}
➜  o javac -d . O.java
➜  o javac Test.java

It seems the fact that we emit a generic signature is tripping up javac.

Classfile from Scala

// class version 52.0 (52)
// access flags 0x21
// signature <T:Ljava/lang/Object;>Ljava/lang/Object;
// declaration: p/O$I<T>
public class p/O$I {

  // compiled from: Test.scala

  ATTRIBUTE Scala : unknown

  ATTRIBUTE ScalaInlineInfo : unknown
  // access flags 0x1
  public INNERCLASS p/O$I p/O I

  // access flags 0x1011
  public final synthetic Lp/O; $outer

  // access flags 0x1001
  public synthetic p$O$I$$$outer()Lp/O;

  // access flags 0x1
  // signature (Lp/O;Ljava/lang/String;)V
  // declaration: void <init>(p.O, java.lang.String)
  public <init>(Lp/O;Ljava/lang/String;)V
    // parameter final  $outer
    // parameter final  s
}

Classfile from Java

// class version 52.0 (52)
// access flags 0x21
// signature <T:Ljava/lang/Object;>Ljava/lang/Object;
// declaration: p/O$I<T>
public class p/O$I {

  // compiled from: O.java
  // access flags 0x1
  public INNERCLASS p/O$I p/O I

  // access flags 0x1010
  final synthetic Lp/O; this$0

  // access flags 0x1
  public <init>(Lp/O;Ljava/lang/String;)V
}

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions