daniellansun commented on PR #2736:
URL: https://github.com/apache/groovy/pull/2736#issuecomment-5133665005

   @blackdrag Thank you — this is exactly the right question, and your A/B/C, 
D/E, F/G scripts make the boundary sharp.
   
   ### Short answer
   
   Hierarchy SwitchPoint fan-out is needed in **one** live-selection situation 
only:
   
   > The **receiver’s MetaClass is unchanged**, selection previously linked a 
result that depended on an **ancestor** modified `MutableMetaClass` (almost 
always EMC) via the **missing-method** walk 
(`MetaClassImpl.findMethodInClassHierarchy`), and that ancestor later **gains 
or loses** methods that change the walk’s result.
   
   Concrete dual:
   
   | Already-linked site on child | Parent MetaClass event | Without hierarchy 
SP | With hierarchy SP |
   |---|---|---|---|
   | Miss for name `m` | Parent EMC adds `m` | Stale miss | Re-link → hit |
   | Hit found only via parent EMC | Parent EMC removed / replaced away | Stale 
hit | Re-link → miss |
   
   That is **all** hierarchy SwitchPoint is for. It is not a general “parent 
MetaClass version” for child tables, and it does **not** rebuild a child’s 
method index.
   
   ### Mapping your examples
   
   They are consistent with that rule; most of them **do not** require 
hierarchy SP:
   
   1. **Present method on the child** (your `B.m2` / declared `foo` cases)  
      The hierarchy walk does not open for that applicable name/signature. 
Parent mutation is **not** required for correctness of the *present* method. We 
may still over-invalidate subtype domains when parent EMC mutates (monomorphic 
domain trade-off), but that is over-invalidation, not a semantic necessity for 
those names.
   
   2. **Construction-time / EMC snapshot** (D/E after `removeMetaClass(E)`, F/G 
after `removeMetaClass(F)`)  
      The more specific method is already **copied into the child’s MetaClass 
instance**. Parent replace/remove does not change that instance’s tables. 
Hierarchy SP cannot and should not “undo” a snapshot. Replacing the **child** 
MetaClass is what rebuilds the view — exactly as in your D/E ladder.
   
   3. **User-surprising B vs C blocking** (`B.m2` blocks more-specific `A.m2` 
for `B` receivers, not for `C`)  
      Agreed this is awkward from a user POV. It is a property of the 
missing-method walk / “present method wins” rule, not of SwitchPoint scoping. 
We are **not** redefining that MOP rule in this PR.
   
   4. **The case that *does* need hierarchy SP** (what the machinery is for):
   
   ```groovy
   class Parent {}
   class Child extends Parent {}
   def call(x) {
     try { x.onlyOnParent(); 'hit' }
     catch (MissingMethodException e) { 'miss' }
   }
   def c = new Child()
   assert call(c) == 'miss'          // monomorphic miss linked on Child
   Parent.metaClass.onlyOnParent = { -> 'now-visible' }
   assert call(c) == 'hit'           // must re-select; Child MetaClass 
unchanged
   ```
   
   and the inverse (linked hierarchy hit → parent EMC removed → miss again).  
   Same pattern for `Object.metaClass.foo` / interface MetaClass / `Object[]` 
lattice.
   
   Without fan-out, those already-linked subtype sites stay wrong until 
something else retires the child’s domain.
   
   ### “A lot of machinery for a small feature”
   
   Fair point. The *feature* is small in description (missing-method hierarchy 
+ EMC), but it is the same feature that makes `Object.metaClass.foo = …` / 
parent EMC methods visible on subtypes without giving every subtype its own 
EMC. For 6.0 we **keep** that MOP observation path (so hierarchy SP stays as 
its invalidation counterpart). Pure unmodified `MetaClassImpl` ↔ 
`MetaClassImpl` (or null) replace stays **exact-class only** — no hierarchy.
   
   What we *did* simplify on the domain side (current tip of this PR):
   
   - SwitchPoints are per **MetaClass instance** (weak identity map in 
`IndyInvalidation`), not a process-wide SP and not a permanent ClassInfo 
“generation” dual to MetaClass.
   - `ClassInfo` only has a **pending** domain for pre-MetaClass link 
(defineClass safety); first MetaClass install retires it.
   - Hierarchy fan-out remains indexed (`ClassHierarchyIndex`) and 
MetaClass-aware (EMC / modified mutable / interface / array / global EMC → 
fan-out; hierarchy-local `MetaClassImpl` pairs → exact).
   
   So hierarchy logic is not “version every parent change for every child 
site”; it is “when parent can change what a **linked miss/hit on the 
missing-method path** means, re-select subtype sites.”
   
   ### Bottom line
   
   | Question | Answer |
   |---|---|
   | Must parent MC change invalidate a site if the receiver MC is unchanged? | 
**Only** if selection can still change via the live missing-method hierarchy 
walk (linked miss↔hit against an ancestor modified `MutableMetaClass` / EMC, 
including interface/array lattice). |
   | What is hierarchy SP trying to solve? | Keep already-linked **subtype** 
indy sites honest for that walk — nothing else. |
   | Snapshots / present methods / EMC copies? | Not hierarchy SP’s job; they 
stay until the **receiver** MetaClass is replaced or rebuilt. |
   
   Happy to tighten docs or tests further if any row of this matrix still 
disagrees with the behaviour you want for 6.0.
   


-- 
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