[
https://issues.apache.org/jira/browse/GROOVY-12717?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18140036#comment-18140036
]
ASF GitHub Bot commented on GROOVY-12717:
-----------------------------------------
codeconsole opened a new pull request, #3251:
URL: https://github.com/apache/groovy/pull/3251
Under `@CompileStatic`, this compiles and then fails when the class is
loaded:
```groovy
// package p
class A { protected A(String s) {}; protected String im() { 'im' };
protected String getQp() { 'qp' } }
// package q
@CompileStatic class B extends p.A {
B() { super('b') }
static test(p.A a) {
new p.A('x') // VerifyError: Bad access to protected <init> method
a.im() // VerifyError: Bad access to protected data in
invokevirtual
a.qp // the same, through the getter
java.util.function.Supplier<String> s = a::im //
BootstrapMethodError
}
}
```
5.0.8 and 6.0.0 fail the same way. Neither has to do with class loaders:
these are Java's rules for a protected member outside its package.
- `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. That includes a map-style
construction, which calls the protected no-argument constructor. 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.
Calls through `this`, `super` or a receiver of the subclass type are still
direct, and `A::new` still selects such a constructor at run time.
An attribute assignment `a.@f = v` through a superclass receiver still fails
verification in `putfield`. It is not changed here.
This and #3097 (GROOVY-12568) touch the same lines of
`StaticInvocationWriter`, `StaticTypesMethodReferenceExpressionWriter` and
`ConstructorCallTransformer`; whichever lands second keeps both. Once this is
in, a map-style construction reaches the check of #3097 through
`writeInvokeConstructor`, so its own call in `ConstructorCallTransformer` is
not needed.
## Compatibility
No working code is affected: this code failed verification or at link time.
It now fails at compile time, under `@CompileStatic` only.
## Tests
`Groovy7325Bug.testProtectedMethodOfAnotherPackageThroughReceiverOfSuperclass`,
`StaticCompileConstructorsTest.testProtectedConstructorOfAnotherPackage` and
`testMapStyleConstructionWithProtectedConstructorOfAnotherPackage` fail without
the change.
`Groovy7325Bug.testProtectedMembersOfAnotherPackageThroughReceiverOfSubclass`
and the `ConstructorsSTCTest` additions pin what keeps working. 5,684 tests in
`org.codehaus.groovy.classgen.asm.sc`, `groovy.transform.stc` and `gls` pass.
The Checkstyle and CodeNarc gates pass.
> SC: new of a protected constructor of another package, or a protected method
> through a superclass receiver, fails verification instead of being reported
> --------------------------------------------------------------------------------------------------------------------------------------------------------
>
> Key: GROOVY-12717
> URL: https://issues.apache.org/jira/browse/GROOVY-12717
> Project: Groovy
> Issue Type: Bug
> Components: Static compilation
> Affects Versions: 4.0.32, 5.0.8, 6.0.0
> Reporter: Scott Murphy Heiberg
> Priority: Major
>
> {code:groovy}
> // package p
> class A {
> protected A(String s) { }
> protected String im() { 'im' }
> protected String getQp() { 'qp' }
> }
> // package q
> @groovy.transform.CompileStatic
> class B extends p.A {
> B() { super('b') }
> static test(p.A a) {
> new p.A('x') // or new p.A([:]) with a protected no-argument
> constructor
> a.im()
> a.qp
> java.util.function.Supplier<String> s = a::im
> java.util.function.Function<p.A, String> f = p.A::im
> }
> }
> {code}
> *Actual:* {{VerifyError: Bad access to protected <init> method}} and
> {{VerifyError: Bad access to protected data in invokevirtual}} when {{B}} is
> loaded, and {{BootstrapMethodError}} for the method references.
> *Expected:* a compile error, as javac gives. Outside its package, a protected
> constructor can only be called by {{super(...)}} or an anonymous class (JLS
> 6.6.2.2), and a protected instance method only through a receiver of the
> subclass (JLS 6.6.2.1, JVMS 4.10.1.8).
> Cause: {{StaticInvocationWriter}} writes {{new}} of such a constructor
> directly. Its GROOVY-7325 check for a method compares the types the wrong way
> round: it tests whether the current class is a subtype of the receiver type,
> not the reverse.
> Verified on 5.0.8, 6.0.0 and master. 4.0.32 fails the same way for the
> constructors and method references, and rejects {{a.im()}} and {{a.qp}} at
> compile time.
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)