Skip to content

Method calls can produce signatures referencing unaccessible methods in Dotty when Scalac doesn't #4430

@Blaisorblade

Description

@Blaisorblade

On Gitter, @jiminhsieh reports that Dotty doesn't run on Eclipse OpenJ9 (because of its version of the standard library doesn't match in some internals ABI details), because Dotty outputs (for https://github.com/lampepfl/dotty/blob/0.7.0/compiler/src/dotty/tools/dotc/util/NameTransformer.scala#L98) a call to java/lang/StringBuilder.append([CII)Ljava/lang/AbstractStringBuilder; rather than java/lang/StringBuilder.append:([CII)Ljava/lang/StringBuilder;, which is what Scalac 2.12.5 produces.

AbstractStringBuilder is a package-accessible class that isn't part of the specified Java standard library, and StringBuilder.append is declared to return StringBuilder not AbstractStringBuilder; the signature that Scalac uses exists on the reference implementation, but just because that implementation also defines public AbstractStringBuilder.append(...): AbstractStringBuilder which is inherited by StringBuffer.

Minimization

That can be verified by compiling this code on a standard JDK (I'm using Oracle JDK 1.8.0_162) and calling javap -c *.class on the result:

object Foo {
  def main() = {
    (new java.lang.StringBuilder()).append(Array[Char](), 0, 0)
  }
}

Analysis and blame

Is Dotty or OpenJ9's library at fault?

Scalac's result would work here, and JLS overload resolution would forbid emitting that call from Java, because §15.12.2 says

This step uses the name of the method and the argument expressions to locate methods that are both accessible and applicable, that is, declarations that can be correctly invoked on the given arguments.

and accessibility of a method is defined in §6.6.1 and requires the defining class to be accessible too:

A member (class, interface, field, or method) of a reference type, or a constructor of a class type, is accessible only if the type is accessible and the member or constructor is declared to permit access:

OTOH, it's not clear from the JLS binary compatibility spec that the OpenJ9 definition of AbstractStringBuilder is binary compatible with the original one, but I think that might be because the definition isn't specific enough.

EDIT: I meant *StringBuilder throughout.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions