Skip to content

scalac compiles without error access to static protected (not visible) field #6934

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 Jan 7, 2013 · 3 comments
Closed

Comments

@scabug
Copy link

scabug commented Jan 7, 2013

Scala 2.10.0 compiles without reporting an error the following classes:

// test/JavaClass.java
package test;

public class JavaClass {

  protected static int STATIC_PROTECTED_FIELD= 4;

}
// test2/ScalaMain.scala
package test2

object ScalaMain {

  def main(args: Array[String]) {
    val a = test.JavaClass.STATIC_PROTECTED_FIELD
  }

}

But it fails during execution:

$ scalac -version
Scala compiler version 2.10.0 -- Copyright 2002-2012, LAMP/EPFL
$ scalac test*/*
$ javac test/*
$ scala test2.ScalaMain
java.lang.IllegalAccessError: tried to access field test.JavaClass.STATIC_PROTECTED_FIELD from class test2.ScalaMain$
	at test2.ScalaMain$.main(ScalaMain.scala:6)
	at test2.ScalaMain.main(ScalaMain.scala)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at scala.tools.nsc.util.ScalaClassLoader$$anonfun$run$1.apply(ScalaClassLoader.scala:71)
	at scala.tools.nsc.util.ScalaClassLoader$class.asContext(ScalaClassLoader.scala:31)
	at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.asContext(ScalaClassLoader.scala:139)
	at scala.tools.nsc.util.ScalaClassLoader$class.run(ScalaClassLoader.scala:71)
	at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.run(ScalaClassLoader.scala:139)
	at scala.tools.nsc.CommonRunner$class.run(ObjectRunner.scala:28)
	at scala.tools.nsc.ObjectRunner$.run(ObjectRunner.scala:45)
	at scala.tools.nsc.CommonRunner$class.runAndCatch(ObjectRunner.scala:35)
	at scala.tools.nsc.ObjectRunner$.runAndCatch(ObjectRunner.scala:45)
	at scala.tools.nsc.MainGenericRunner.runTarget$1(MainGenericRunner.scala:74)
	at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:96)
	at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:105)
	at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)

Compilation correctly fails when using Scala 2.9.2

$ ~/opt/scala-2.9.2/bin/scalac -version
Scala compiler version 2.9.2 -- Copyright 2002-2011, LAMP/EPFL
$ ~/opt/scala-2.9.2/bin/scalac test*/*
test2/ScalaMain.scala:6: error: variable STATIC_PROTECTED_FIELD in object JavaClass cannot be accessed in object test.JavaClass
 Access to protected variable STATIC_PROTECTED_FIELD not permitted because
 enclosing class object ScalaMain in package test2 is not a subclass of 
 object JavaClass in package test where target is defined
    val a = test.JavaClass.STATIC_PROTECTED_FIELD
                           ^
one error found

Compilation also correctly fails on 2.10.0 for non-static protected fields.

@scabug
Copy link
Author

scabug commented Jan 7, 2013

Imported From: https://issues.scala-lang.org/browse/SI-6934?orig=1
Reporter: @skyluc
Affected Versions: 2.10.0, 2.11.0-M7
See #1806

@scabug
Copy link
Author

scabug commented Jan 7, 2013

@retronym said:
Most probably introduced with the fix for #1806: scala/scala@1ebbe02

@scabug
Copy link
Author

scabug commented Jan 7, 2013

@retronym said:
Assigning to Paul to gauge whether there is a way to accomodate #1806 while disallowing this.

@scabug scabug added this to the Backlog milestone Apr 7, 2017
hrhino added a commit to hrhino/scala that referenced this issue Sep 5, 2017
…ses.

This more-or-less reverts the fix added in 1ebbe02. Instead
of wantonly treating `protected static` Java members like they're
public, it suffices to modify `isSubClassOrCompanion` to consider
a class a "subclass or companion" of the companions of its parent
classes, provided the parent is a Java-defined class.

It's a bit wacky, but comparing the Java and Scala definitions of
`protected` access:

SLS 5.2.8:
    Protected members of a class can be accessed from within

    - the template of the defining class,
    - all templates that have the defining class as a base class,
    - the companion module of any of those classes.

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

    ...
    - if the member or constructor is declared protected, then access
      is permitted only when one of the following is true:

      - Access to the member or constructor occurs from within the
        package containing the class in which the protected member
        or constructor is declared.
      - Access is correct as described in §6.6.2.

JLS 6.6.2.1:
    Let C be the class in which a protected member is declared.
    Access is permitted only within the body of a subclass S of C.

The important differences are that Java protected members are
indeed accessible from the package that they're declared in (this
behavior is implemented by `accessBoundary`, and that `static`
methods are treated the same as instance methods for purposes of
access control. Therefore, I feel comfortable adding the third
case to `isSubClassOrCompanion`, thus taking the Java access
control model when dealing with Java-defined types.

Fixes scala/bug#6934, review by adriaanm and (of course) whoever
feels like swinging by and saying hi.
@hrhino hrhino self-assigned this Sep 5, 2017
hrhino added a commit to hrhino/scala that referenced this issue Sep 5, 2017
…ses.

This more-or-less reverts the fix added in 1ebbe02. Instead
of wantonly treating `protected static` Java members like they're
public, it suffices to modify `isSubClassOrCompanion` to consider
a class a "subclass or companion" of the companions of its parent
classes, provided the parent is a Java-defined class.

It's a bit wacky, but comparing the Java and Scala definitions of
`protected` access:

SLS 5.2.8:
    Protected members of a class can be accessed from within

    - the template of the defining class,
    - all templates that have the defining class as a base class,
    - the companion module of any of those classes.

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

    ...
    - if the member or constructor is declared protected, then access
      is permitted only when one of the following is true:

      - Access to the member or constructor occurs from within the
        package containing the class in which the protected member
        or constructor is declared.
      - Access is correct as described in §6.6.2.

JLS 6.6.2.1:
    Let C be the class in which a protected member is declared.
    Access is permitted only within the body of a subclass S of C.

The important differences are that Java protected members are
indeed accessible from the package that they're declared in (this
behavior is implemented by `accessBoundary`, and that `static`
methods are treated the same as instance methods for purposes of
access control. Therefore, I feel comfortable adding the third
case to `isSubClassOrCompanion`, thus taking the Java access
control model when dealing with Java-defined types.

I also scouted a grammar tweak, which makes this have a few more
files in the diff than would be expected.

Fixes scala/bug#6934, review by adriaanm and (of course) whoever
feels like swinging by and saying hi.
@hrhino hrhino modified the milestones: 2.12.4, Backlog Sep 5, 2017
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