codeconsole opened a new pull request, #3097:
URL: https://github.com/apache/groovy/pull/3097

   The JVM allows access to a protected or package-private member only within 
the same run-time package, which is the package name and the class loader. A 
`GroovyClassLoader` defines each compilation in memory with a class loader of 
its own (a `GroovyShell` script, `parseClass`, a script run with `groovy`, 
JSR-223), so a class from an earlier parse, or a precompiled class used by such 
a script, is in another run-time package even with the same package name. 
Statically compiled code accessed such members directly and failed with 
`IllegalAccessError`:
   
   ```groovy
   // first parse
   package p
   class A { @PackageScope A(String s) {}; @PackageScope String name() { 'a' }; 
@PackageScope String tag = 't' }
   
   // second parse with the same GroovyShell
   package p
   @CompileStatic List make() { def a = new A('x'); [a.name(), a.tag] }
   ```
   
   For a compilation defined in memory, statically compiled code now reaches 
such a constructor, method or field through the meta-class, as dynamic code 
does. This covers `new` and map-style construction, instance and static 
methods, getters and setters used as properties, method references such as 
`a::name` (through a synthetic method), and field reads and writes including 
`.@`, `+=` and `++`. In dynamic code, `super.f`, `super.@f` and `this.@f` of 
such a field and `super.m()` of such a method work too (no `super$` method is 
generated for a package-private method of another run-time package). Public 
members, classes of the same compilation, and protected members used from a 
subclass through `this`, `super` or a receiver of the subclass type are still 
accessed directly. Code compiled to class files (groovyc, Gradle, Maven, Ant, 
joint compilation with Java) keeps direct access to the members of the other 
classes of its package, as javac does, and a full and an incremental build give 
t
 he same bytecode. The rule is `AsmClassGenerator.isInSameRuntimePackage`, 
which #3022 introduces for constructor references; this applies it to the rest.
   
   Protected members of another package, in a subclass, under static 
compilation:
   
   - `new A(...)` of a protected constructor of another package is reported: 
"Cannot call protected constructor for p.A from class q.B". As in Java, only 
`super(...)` and `new A(...) {}` can call it. It used to compile and then fail 
verification. The error is raised while the class is generated, so 
`@TypeChecked` code is not checked for it and works through the meta-class.
   - A protected method of another package called through a receiver of the 
superclass type (`a.m()`, `a.name`, `a::m`, `A::m`) is reported as "Cannot 
access method", as GROOVY-7325 intended: its check compared the types the wrong 
way round. These used to compile and then fail with `VerifyError`. `a.@field = 
value` through such a receiver now goes through the meta-class, like the read.
   
   With invokedynamic, a dynamic `new` of a constructor that the JVM refuses, 
such as `new ObjectInputStream()` in a subclass, now fails with "could not 
access constructor", as it does without invokedynamic, instead of 
`GroovyBugError`.
   
   COMPATIBILITY.md has an entry for the meta-class semantics of these accesses 
and the two new compile errors.
   
   This builds on #3022 (constructor references), which adds 
`isInSameRuntimePackage`, the `GroovyClassLoader` marker and 
`StaticInvocationWriter.isDirectlyAccessible`; its commits are included here 
until it is merged.
   
   ## Tests
   
   All marked `// GROOVY-12568`, each failing without the change it covers:
   
   - `StaticCompileRuntimePackageTest`: constructors, map-style construction 
(literal and `Map` variable), methods, properties, method references (also in 
static and default methods of an interface) and fields of a class of another 
class loader, with and without invokedynamic, compared with the same code 
compiled dynamically; bytecode tests pin that classes of the same compilation, 
public members, class files, incremental builds and joint compilation keep 
direct access;
   - `bugs.Groovy12568`: dynamic `super.m()` of a package-private method of 
another class loader, and invokedynamic `new` of a protected constructor of 
another package or of the JDK;
   - `ConstructorsSTCTest` and `StaticCompileConstructorsTest`: `new` of a 
protected constructor of another package, with `super(...)` and anonymous 
classes still direct;
   - `Groovy7325Bug`: protected methods of another package through a receiver 
of the superclass and of the subclass.
   
   The `groovy.*`, `gls.*`, `bugs.*`, `org.codehaus.groovy.classgen` and 
`org.codehaus.groovy.transform` packages pass (13,458 tests), apart from 
`bugs.Groovy12363`, which also fails on master when it runs after 
`bugs.Groovy12142` in the same JVM (GROOVY-12580, #3096, fixes it), and 
`bugs.Groovy9815`, whose `@Grab` download failed once and passes when rerun. 
The Checkstyle and CodeNarc gates pass.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to