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

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

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

   In a class nested in `Outer`, the type checker accepted `sub.@f`, where `f` 
is a private field of `Outer` and `sub` is typed as a subclass of `Outer`. 
Dynamic Groovy and `@TypeChecked` threw `MissingFieldException`, because the 
meta-class of a subclass offers no private field of its superclass, and javac 
rejects it ("f has private access in Outer"); `@CompileStatic` read the field. 
With `f` declared in a nested class `Box` and `Sub extends Box`, or with a 
top-level subclass, the same access was already rejected. Both modes now report 
"Cannot access field: f of class: Outer", also for writes, compound 
assignments, closures, lambdas, `new Sub().@f` and a receiver typed as a deeper 
subclass.
   
   ```groovy
   @TypeChecked
   class Outer {
       private String f = 'outer'
       static class Sub extends Outer {
           String read(Sub sub) { sub.@f }  // threw MissingFieldException; now 
"Cannot access field: f of class: Outer"
       }
   }
   ```
   
   Split out of #3044, and builds on it: the rule reuses the check for a 
private member reached through a subclass (GROOVY-12510, GROOVY-12511) and the 
exception for a variable declared with the field's class (GROOVY-12513). Until 
#3044 is merged, this pull request also shows its commits; the one to review is 
"GROOVY-12523: STC: reject x.@name for a private field of a superclass when the 
type of x is a subclass". `Sub.this.@f` inside `Sub` is rejected too once 
GROOVY-12514 (#3049) makes `Sub.this` compile there; whichever of the two is 
merged second adds that case to the tests.
   
   ## Behaviour change
   
   Under `@CompileStatic`, which read the field directly, such code stops 
compiling; `((Outer) sub).@f` reads it. `this.@f` and `super.@f`, which read 
the field directly in every mode, keep working, as do `sub.@f` in `Outer` 
itself and a receiver declared as `Outer`. Private static fields are left 
alone, as private static methods are. 5.0.8, 6.0.0 and master compile such 
code; 4.0.33 failed at run time in every mode. The object orientation guide now 
says that within a subclass only `this.@name` and `super.@name` reach such a 
field.
   
   ## Tests
   
   `FieldsAndPropertiesSTCTest` (also run by 
`FieldsAndPropertiesStaticCompileTest`): thirteen rejected forms and a script 
with the forms that keep working; the statically compiled test also reads the 
field through a cast. They fail without the change. 15,011 tests in the 
`groovy`, `gls`, `bugs`, `org.codehaus.groovy.classgen`, `transform`, 
`runtime`, `reflection`, `vmplugin`, `control` and `ast` packages and the stub 
generator tests pass, apart from `bugs.Groovy12363`, which fails on master too 
when it runs after `bugs.Groovy12142` in the same JVM (#3025 fixes it). In that 
run the new test also failed, on a `Sub.this.@f` case that needs GROOVY-12514; 
with that case removed, `FieldsAndPropertiesSTCTest` and 
`FieldsAndPropertiesStaticCompileTest` pass. `groovy-contracts`, 
`groovy-typecheckers`, `groovy-ginq`, `groovy-macro-library`, `groovy-json`, 
`groovy-xml` and `groovy-templates` pass their tests, and every subproject 
compiles its main and test sources. The Checkstyle and CodeNarc gates pass.
   




> STC: x.@name is accepted for a private field of a superclass when the type of 
> x is a subclass
> ---------------------------------------------------------------------------------------------
>
>                 Key: GROOVY-12523
>                 URL: https://issues.apache.org/jira/browse/GROOVY-12523
>             Project: Groovy
>          Issue Type: Bug
>          Components: Static Type Checker
>    Affects Versions: 6.0.0
>            Reporter: Scott Murphy Heiberg
>            Priority: Major
>
> In a class nested in {{Outer}}, the type checker accepts {{sub.@f}}, where 
> {{f}} is a private field of {{Outer}} and {{sub}} is typed as a subclass of 
> {{Outer}}:
> {code:groovy}
> @groovy.transform.TypeChecked
> class Outer {
>     private String f = 'outer'
>     static class Sub extends Outer {
>         String read(Sub sub) { sub.@f }
>     }
> }
> new Outer.Sub().read(new Outer.Sub()) // MissingFieldException: No such 
> field: f for class: Outer$Sub
> {code}
> Dynamic Groovy and {{@TypeChecked}} throw {{MissingFieldException}}, because 
> the meta-class of a subclass offers no private field of its superclass. 
> {{@CompileStatic}} reads the field. javac rejects {{sub.f}} ("f has private 
> access in Outer"), since a private field is not a member of a subclass (JLS 
> 8.2). With {{f}} declared in a nested class {{Box}} and {{Sub extends Box}}, 
> or with a top-level subclass, the type checker already rejects {{sub.@f}} 
> with "Cannot access field". Seen in 5.0.8, 6.0.0 and master; 4.0.33 failed at 
> run time in every mode.
> Expected: "Cannot access field: f of class: Outer", also for writes, 
> closures, lambdas and {{new Sub().@f}}. {{this.@f}}, {{super.@f}}, {{((Outer) 
> sub).@f}} and {{sub.@f}} inside {{Outer}} keep compiling.
> PR: https://github.com/apache/groovy/pull/3044



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

Reply via email to