-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Incorrect treatment of structural type #4496
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
Comments
Can be reproduced outside of the repl as well: import scala.reflect.Selectable.reflectiveSelectable
object Test {
def main(args: Array[String]): Unit = {
println((new Object { val a: Int = 10} : {val a: Int}).a) // crash
println((new Object { def a: Int = 10} : {def a: Int}).a) // crash
}
} |
I see two issues:
scala> import scala.reflect.Selectable.reflectiveSelectable; class Foo { val a: Int = 10 }; (new Foo: {val a: Int}).a
// defined class Foo
java.lang.NoSuchFieldException: a
at java.lang.Class.getField(Class.java:1703)
at scala.reflect.Selectable$.selectDynamic$extension(Selectable.scala:7)
at scala.reflect.Selectable.selectDynamic(Selectable.scala:4)
at rs$line$1$.<init>(rs$line$1:1) into scala> import scala.reflect.Selectable.reflectiveSelectable; class Foo { val a: Int = 10 }; (new Foo: {val a: Int}).a
// defined class Foo
val res0: Int = 10
The access modifier is fixed to private during scala> import scala.reflect.Selectable.reflectiveSelectable; (new Object { val a: Int = 10} : {val a: Int}).a
java.lang.IllegalAccessException: Class scala.reflect.Selectable$ can not access a member of class rs$line$1$$anon$1 with modifiers "public"
at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102)
at java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:296)
at java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:288)
at java.lang.reflect.Method.invoke(Method.java:491)
at scala.reflect.Selectable$.$anonfun$selectDynamicMethod$2(Selectable.scala:22)
at scala.reflect.Selectable$.selectDynamic$extension(Selectable.scala:12)
at scala.reflect.Selectable.selectDynamic(Selectable.scala:4)
at rs$line$1$.<init>(rs$line$1:1)
at rs$line$1$.<clinit>(rs$line$1)
at rs$line$1.res0Show(rs$line$1)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) import scala.reflect.Selectable.reflectiveSelectable; (new Object { val a: Int = 10} : {val a: Int}).a |
FWIW the JDK code I consulted is http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes/sun/reflect/Reflection.java but beware usual license warnings if you want to work on JRE stdlib alternatives. |
TLDR:
Scalac behaviorThe Scala reflection likes to call By calling Reflective field access should succeed even on private classes, at least for fields inherited from public classesScalac supports reflective calls even on private classes (example courtesy of @allanrenucci), probably by using the scala> import scala.language.reflectiveCalls
import scala.language.reflectiveCalls
scala> trait Foo { def a: Int }
defined trait Foo
// This code appears clearly well-typed.
// XXX for a realistic use case imagine more indirection between the upcast and the access, as in better-files.
scala> def consumeFoo(foo: Foo) = (foo: { def a: Int }).a
consumeFoo: (foo: Foo)Int
// This code appears also clearly well-typed: Even if Bar is private, it can clearly be upcast to Foo
scala> object A { private class Bar extends Foo { def a = 42 }; def tester = consumeFoo(new Bar) }
scala> A.tester
defined class Bar
res0: Int = 42 On the better-files usecase see #1175 (comment). Existing decisions in Dotty@allanrenucci suggested we might not want to enable reflective access to a member first introduced in an anonymous class. What has been clearly decided is that we never infer and export structural types in interfaces (e.g. #1743), but I think this is different, and as shown above Dotty fails even accessing members introduced in accessible superclasses. |
Just learned that |
Fix #4496: call ensureAccessible to bypass class-level accessibility
The text was updated successfully, but these errors were encountered: