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

Eric Milles edited comment on GROOVY-11367 at 5/5/24 4:16 PM:
--------------------------------------------------------------

With changes (1), (3) and (4) from last comment, the first test case changes as 
follows:
{code:groovy}
@CompileDynamic test1(M map) {
  map.pub   // field
  map.pro   // entry
  map.pack  // entry
  map.priv  // entry
  map.prop  // property
  map.any   // getter (public) or entry (non-public)
  map.class // entry
  map.empty // entry
  map.metaClass // getter

  map.pub   = null // field
  map.pro   = null // entry
  map.pack  = null // entry
  map.priv  = null // entry
  map.prop  = null // property
  map.any   = null // setter (public) or entry (non-public)
  map.empty = null // entry
  map.class = null // entry
  map.metaClass = null // setter
}
{code}
Only a public member (field, method or property) comes before map lookup. 
"class" and "empty" retain special exclusion and "metaClass" aligns with public 
inclusion.


was (Author: emilles):
With changes (1), (3) and (4) from last comment, the first test case changes as 
follows:
{code:groovy}
@CompileDynamic test1(M map) {
  map.pub   // field
  map.pro   // entry
  map.pack  // entry
  map.priv  // entry
  map.prop  // property
  map.any   // getter (public) or entry (non-public)
  map.class // entry
  map.empty // entry
  map.metaClass // getter

  map.pub   = null // field
  map.pro   = null // entry
  map.pack  = null // entry
  map.priv  = null // entry
  map.prop  = null // property
  map.any   = null // setter (public) or entry (non-public)
  map.empty = null // entry
  map.class = null // entry
  map.metaClass = null // setter
}
{code}
Only public member (field, method or property) comes before map lookup. "class" 
and "empty" retain special exclusion and "metaClass" aligns with public 
inclusion.

> map-based types property semantics
> ----------------------------------
>
>                 Key: GROOVY-11367
>                 URL: https://issues.apache.org/jira/browse/GROOVY-11367
>             Project: Groovy
>          Issue Type: Bug
>            Reporter: Eric Milles
>            Assignee: Eric Milles
>            Priority: Major
>              Labels: breaking
>
> The rules for property read and write for map-based types still have several 
> inconsistencies:
> {code:groovy}
> class M extends HashMap<String,Object> {
>   public pub
>   protected pro
>   @PackageScope pack
>   private priv
>   def prop
>   def getAny() {}
>   void setAny(value) {}
> }
> {code}
>  # Read and write do not share a consistent resolution order – noted in 8555. 
> Should access method selection take visibility into account? I think sender 
> information is not always available to {{MetaClassImpl}} so the "inside 
> class" behavior is required.
> {code:groovy}
> void test1(M map) {
>   map.pub  // field (fixed in 5001)
>   map.pro  // map entry
>   map.pack // map entry
>   map.priv // map entry
>   map.prop // object property (fixed in 5001)
>   map.any  // getter (all visibilities -- fixed in 5001) or entry for 
> subclass of M (private or package-private other-package subclass -- fixed in 
> 11357)
>   map.empty // map entry ("class" and "metaClass" as well)
>   map.pub  = null // field
>   map.pro  = null // field
>   map.pack = null // map entry
>   map.priv = null // map entry
>   map.prop = null // object property
>   map.any  = null // setter (all visibilities) or entry for subclass of M 
> (private or package-private other-package subclass -- fixed in 11357)
>   map.empty = null // map entry
>   map.class = null // map entry
>   map.metaClass = null // setter via 
> ScriptBytecodeAdapter#setGroovyObjectProperty
> }
> {code}
>  # "this" and "super" have different behavior.
> {code:groovy}
>   // add this to the body of M
>   void test2(M that) {
>     this.pub  // field
>     this.pro  // field
>     this.pack // field
>     this.priv // field
>     this.prop // object property
>     this.prop = null // object property
>     this.any  // getter (all visibilities -- fixed in 5001)
>     this.any = null // setter (all visibilities) or entry for subclass of M 
> (private or package-private other-package subclass -- fixed in 11357)
>     this.class // map entry
>     this.empty // map entry
>     this.metaClass // field (added by compiler)
>     that.* // see test1
>     that = this
>     that.* // see test1
>   }
> {code}
>  # Dynamic and static compilation have different behavior.
> {code:groovy}
> @groovy.transform.CompileStatic
> void test3(M map) {
>   map.pub  // field (fixed in 5xxx)
>   map.pro  // field (fixed in 5xxx: in package or subclass) or entry
>   map.pack // field (fixed in 5xxx: in package) or entry
>   map.priv // map entry
>   map.prop // object property
>   map.any  // getter (accessible -- fixed in 5xxx) or map entry (inaccessible)
>   map.empty // isser
>   map.class // getter
>   map.metaClass // getter
>   map.pub  = null // TODO
>   map.pro  = null // TODO
>   map.pack = null // TODO
>   map.priv = null // TODO
>   map.prop = null // TODO
>   map.any  = null // TODO
>   map.empty = null // error "Cannot set read-only property: empty" ("class" 
> as well)
>   map.metaClass = null // setter
> }
> {code}
>  # Closures intercept some properties.
> {code:groovy}
> void test4(M map) {
>   map.with {
>     pub // field
>     pro // map entry
>     pack // map entry
>     priv // map entry
>     prop // object property
>     directive // closure property
>     metaClass // closure property (and so on for "owner", "delegate", 
> "thisObject", ...)
>   }
> }
> {code}
>  # The rules change a bit for fields declared by super class.
> {code:groovy}
> class MM extends M {
>   void test5() {
>     this.pub   // field (fixed in 5001)
>     this.pro   // entry
>     this.pack  // entry
>     this.priv  // entry
>     this.prop  // property (fixed in 5001)
>     this.any   // getter (fixed in 5001) (public, protected, package-private 
> if same-package) or entry (private, package-private if other-package)
>     this.class // entry
>     this.empty // entry
>     this.metaClass // entry
>     this.pub  = null // field
>     this.pro  = null // field
>     this.pack = null // entry
>     this.priv = null // entry
>     this.prop = null // property
>     this.any  = null // setter (public, protected, package-private if 
> same-package) or entry (private, package-private if other-package -- fixed in 
> 11357)
>     this.empty = null // map entry
>     this.class = null // map entry
>     this.metaClass = null // setter via 
> ScriptBytecodeAdapter#setGroovyObjectProperty
>   }
> }
> {code}
> # Calling a name bypasses map lookup.
> {code:groovy}
> void test6(M map) {
>   map.pack() // field read and call
>   map.priv() // field read and call
> }
> {code}
> GROOVY-11223, GROOVY-11319, GROOVY-9127, GROOVY-8555, GROOVY-8065, 
> GROOVY-6277, GROOVY-6144, GROOVY-5985, GROOVY-5491, GROOVY-5001, GROOVY-662



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to