Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Private constructors and methods are compiled to public visibility when accessed from a companion object #6882

Open
scabug opened this issue Dec 27, 2012 · 6 comments

Comments

@scabug
Copy link

scabug commented Dec 27, 2012

Private constructors and methods are compiled to public visibility when a companion object access them. This should arguably be the "most private" possible. While the Scala compiler should (and likely does, I didn't test it) enforce the visibility restrictions, when interoperating with Java, it would be preferable to have something other than public visibility here.

Per Simon Ochsenreither, the issue could be solvable by emitting an appropriate static forwarder in the class.

Example with expected results (no companion object):

class Private private(x: Int) {
  private[this] val y = x
  private def yValue = y
}

javap -p output with private constructor and method:

public class Private implements scala.ScalaObject {
  private final int y;
  private int yValue();
  private Private(int);
}

This is expected.

However, adding the companion object as follows results in the private constructor and method being generated as public.

object Private {
  def main(args: Array[String]) {
    val p = new Private(7)
    p.yValue
  }
}

javap -p output with public constructor and method:

public class Private implements scala.ScalaObject {
  private final int y;
  public static final void main(java.lang.String[]);
  public final int Private$$yValue();
  public Private(int);
}
@scabug
Copy link
Author

scabug commented Dec 27, 2012

Imported From: https://issues.scala-lang.org/browse/SI-6882?orig=1
Reporter: Eric Fredericks (eric.fredericks)
Affected Versions: 2.9.2

@scabug
Copy link
Author

scabug commented Apr 17, 2015

Paul Lysak (paul.lysak) said:
There's a similar issue when private methods used in closures. For example if you look at "javap -p Enumeration" output for scala.Enumeration you may notice public methods
public scala.collection.mutable.Map<java.lang.Object, java.lang.String> scala$Enumeration$$nmap();
public void scala$Enumeration$$populateNameMap();
despite the fact that nmap field and populateNameMap method are private in Scala code and aren't used anywhere beyond Enumeration class, but inside that class there are few closures that operate with private fields.

@scabug
Copy link
Author

scabug commented Apr 18, 2015

@SethTisue said:
Can you explain how adding a static forwarder would help?

@scabug
Copy link
Author

scabug commented Jul 20, 2015

@SethTisue said:
Closing as "Incomplete" for now. Feel free to reopen if you can supply more detail justifying the proposed fix.

@dwijnand
Copy link
Member

See #7085 for more details on the idea of adding a synthetic static accessor. Which I think should work for a private constructor.

@dwijnand dwijnand reopened this Nov 19, 2018
@dwijnand
Copy link
Member

Oh see also #7085 (comment):

Another tricky aspect of Java's approach to access is constructors. It creates 'access constructors' with an extra dummy parameter. The type of the parameter was used to uniquely distinguish the constructors, and was chosen to be the type of the inner class that needed to access the constructor.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants