Skip to content

Anonymous classes methods becoming private when compiled. #9487

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

Closed
scabug opened this issue Sep 24, 2015 · 6 comments
Closed

Anonymous classes methods becoming private when compiled. #9487

scabug opened this issue Sep 24, 2015 · 6 comments

Comments

@scabug
Copy link

scabug commented Sep 24, 2015

When a type of an anonymous class is less specific that the definition of the class (AnyRef for example) the anonymous class methods become private. This happens with val, def and var definition inside the class.

  type T = {val x: String; def y: String; var z: String}

  // This one generates to compile the anonymous class properly.
  // It marks all methods and field accessors as private
  // If the return type is T then it compiles correctly
  def get(): AnyRef = new { val x = "x"; def y = "y"; var z = "z"}

  val obj = get()
  // Prints: Failure(java.lang.NoSuchMethodException: A$$anon$2.x())
  println(Try(obj.asInstanceOf[T].x))

  // Prints: Failure(java.lang.NoSuchMethodException: A$$anon$2.y())
  println(Try(obj.asInstanceOf[T].y))

  // Prints: Failure(java.lang.NoSuchMethodException: A$$anon$2.z())
  println(Try(obj.asInstanceOf[T].z))
  // Failure(java.lang.NoSuchMethodException: A$$anon$1.z_$eq(java.lang.String))
  println(Try(obj.asInstanceOf[T].z = "zz"))
  // Prints: Failure(java.lang.NoSuchMethodException: A$$anon$2.z())
  println(Try(obj.asInstanceOf[T].z))

  println
  println("Fields:")
  // Lists x and z fields as expected
  obj.getClass.getDeclaredFields.foreach(x => println(s"  $x"))
  println("Methods:")
  // All methods are private but should be public
  obj.getClass.getDeclaredMethods.foreach(x => println(s"  $x"))

It looks like a code pattern that should be avoided, but in Scala.js this is used to create javascript objects. scala-js/scala-js#1899

@scabug
Copy link
Author

scabug commented Sep 24, 2015

Imported From: https://issues.scala-lang.org/browse/SI-9487?orig=1
Reporter: Nicolas Stucki (nicolas.stucki)
Affected Versions: 2.11.7, 2.12.0-M3

@scabug
Copy link
Author

scabug commented Sep 24, 2015

@sjrd said:
Note that the methods and fields are already private directly after typer, as can be seen with -Xprint:typer. So the Component should probably be the typechecker instead of the backend.

@scabug
Copy link
Author

scabug commented Sep 25, 2015

@scabug
Copy link
Author

scabug commented Sep 25, 2015

@sjrd said:
Hum, that looks related indeed, and the comment suggests this is Hard (tm). However, IIUC, the linked backstory explains why the type of the Block needs to hide away some members. But I don't think that explains why the actual class itself (its implementation) needs to suddenly turn public members into private ones. It seems to me that there might be a relatively easy fix to that (compared to fixing the type issue).

It is also worth mentioning that if the anonymous class does not have any expected type at all, then the members are kept public. For example rewriting get() above as:

def get(): AnyRef = {
  val o = new { ... }
  o
}

allows all members to be public.

@som-snytt
Copy link

This came up recently because the private members can be reported unused in Scala 2.

Scala 3 has to do extra work to decide if a member is "effectively private".

scala/scala3#22729

Is it OK to close this as out of scope a decade later? Scala 3 made a different choice, but Scala 2 is unlikely to change.

@sjrd
Copy link
Member

sjrd commented Apr 27, 2025

Yes, let's close.

@sjrd sjrd closed this as not planned Won't fix, can't repro, duplicate, stale Apr 27, 2025
@SethTisue SethTisue removed this from the Backlog milestone Apr 30, 2025
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

5 participants