[ 
https://issues.apache.org/jira/browse/GROOVY-12621?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18135659#comment-18135659
 ] 

ASF GitHub Bot commented on GROOVY-12621:
-----------------------------------------

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

   Stacked on #3137 (GROOVY-12610). After that change, `@TypeChecked` still 
accepted three kinds of private superclass field access that fail at run time 
with a `MissingPropertyException`:
   
   ```groovy
   @groovy.transform.TypeChecked
   enum E {
       A { def n() { z } }          // also this.z, super.z
       private String z = 'x'
   }
   
   @groovy.transform.TypeChecked
   class Base {
       private String z = 'x'
       static class Nested extends Base {}
       class Sub extends Base {
           def m() { super.z = 'y' } // also super.z += .., super.z++
       }
       class Inner {
           def m(Nested n) { n.z }   // receiver is not an Inner
       }
   }
   ```
   
   The enum case fails the same way in 4.0.33, 5.0.8 and 6.0.0.
   
   - **Enum constant body.** It is created by the enum's static initializer, so 
it has no enum instance to fall back to. 
`ClassNodeUtils.hasNoEnclosingInstance` now says so. As a result `E.this` in 
the body is a compile error instead of a `VerifyError`.
   - **Write through `super`.** The runtime falls back to the enclosing 
instance for reads and writes in an inner class, but not for a write through 
`super` (GROOVY-11823). `StaticTypeCheckingVisitor.isFieldAccessible` now knows 
whether the access is a write, and rejects a `super` write from a class other 
than the declaring class.
   - **Receiver of another class.** The fallback applies only when the receiver 
is an instance of the calling class. A receiver that is not `super` must now be 
derived from the current class. The exception is the `Outer.this.z` that the 
checker builds for an implicit `z`: it is still dispatched on `this`, so it is 
marked and left unaffected.
   
   `@CompileStatic` still accesses the field directly in every case. A 
non-static inner subclass still reaches the field through `this.z`, `z`, 
`super.z` reads, closures, lambdas and writes. Attribute access and access from 
the declaring class are unchanged.
   
   ## Tests
   
   `FieldsAndPropertiesSTCTest.testPrivateFieldOfEnumViaConstantBody`, 
`testPrivateFieldOfSuperclassWrittenThroughSuperInInnerSubclass`, 
`testPrivateFieldOfSuperclassViaReceiverOfOtherClass` and 
`InnerClassTest.testOuterThisInEnumConstantBody` fail without the change. 
`testPrivateFieldOfSuperclassViaReceiverOfCallingClass` and the 
`FieldsAndPropertiesStaticCompileTest` overrides cover the forms that must keep 
compiling under type checking and static compilation. `groovy.transform.stc.*`, 
`org.codehaus.groovy.classgen.asm.sc.*`, `gls.*`, 
`org.codehaus.groovy.transform.traitx.*`, `groovy.ThisAndSuperTest`, `bugs.*` 
and `groovy.bugs.*` pass. The Checkstyle and CodeNarc gates pass.
   




> STC still accepts some private superclass field accesses under @TypeChecked 
> that fail at run time
> -------------------------------------------------------------------------------------------------
>
>                 Key: GROOVY-12621
>                 URL: https://issues.apache.org/jira/browse/GROOVY-12621
>             Project: Groovy
>          Issue Type: Bug
>    Affects Versions: 4.0.33, 5.0.8, 6.0.0
>            Reporter: Scott Murphy Heiberg
>            Priority: Major
>
> GROOVY-12610 makes the type checker reject property access to a private 
> instance field of a superclass when dynamic dispatch can never find it. Three 
> shapes are still accepted and fail with a MissingPropertyException.
> Enum constant body (z, this.z and super.z all fail):
> {code:groovy}
> @groovy.transform.TypeChecked
> enum E {
>     A { def n() { z } }
>     private String z = 'x'
> }
> E.A.n()
> {code}
> Write through super in a non-static inner subclass (compound assignment and 
> increment also fail):
> {code:groovy}
> @groovy.transform.TypeChecked
> class Base {
>     private String z = 'x'
>     class Sub extends Base {
>         def m() { super.z = 'y' }
>     }
>     def t() { new Sub().m() }
> }
> new Base().t()
> {code}
> Receiver that is not an instance of the calling inner class:
> {code:groovy}
> @groovy.transform.TypeChecked
> class Base {
>     private String z = 'x'
>     static class Sub extends Base {}
>     class Inner {
>         def m(Sub sub) { sub.z }
>     }
>     def t() { new Inner().m(new Sub()) }
> }
> new Base().t()
> {code}
> Actual: all three compile and then fail with MissingPropertyException: No 
> such property: z for class: E$1 (or Base$Sub).
> Expected: compile errors "No such property: z for class: ...", as for the 
> shapes GROOVY-12610 covers. Under @CompileStatic all three keep compiling, 
> since static compilation accesses the field directly.
> Cause: ClassNodeUtils.hasNoEnclosingInstance returned false for an enum 
> constant body, which is created in the enum's static initializer. The type 
> checker also did not take two run-time limits into account: there is no 
> enclosing-instance fallback for a write through super (GROOVY-11823), and the 
> fallback applies only when the receiver is an instance of the calling class.
> The enum case is seen in 4.0.33, 5.0.8 and 6.0.0.



--
This message was sent by Atlassian Jira
(v10.3.26#10030026)

Reply via email to