Re: Tracking Methods used in runtime bytecode (WAS: Re: Next releases)

Jochen Theodorou <[email protected]> Wed, 17 Jun 2026 13:37:16 +0200
Newsgroups gmane.comp.lang.groovy.devel
Message-ID <[email protected]>
Yes, that seems to go in the right direction. in other words... I would 
not know what to add to this and it looks very usable!

bye Jochen

On 6/17/26 12:10, Paul King wrote:
> This is what AI suggests for BytecodeInterfacing. Is that the kind of
> thing you had i mind?
> 
> package org.apache.groovy.lang.annotation; // next to @Incubating
> 
> @Documented
> @Retention(RetentionPolicy.RUNTIME)              // matches
> @Internal/@Incubating; enables a build-time check
> @Target({ElementType.METHOD, ElementType.TYPE, ElementType.FIELD})
> public @interface BytecodeInterfacing {
>      /** Groovy version whose compiler first emitted references to this
> entry point. */
>      String since();
>      /** Groovy version that stopped emitting references; "" = still emitted.
>          Set this when the compiler no longer generates the reference
> but old bytecode still needs it. */
>      String obsoleteSince() default "";
>      /** Earliest Groovy version in which this may be removed (once min
> supported bytecode passes obsoleteSince). */
>      String removableIn() default "";
>      /** Frozen JVM method descriptor, so a test can assert the live
> signature never drifts. */
>      String descriptor() default "";
> }
> 
>    Why these choices:
> 
>    - Where: org.apache.groovy.lang.annotation, alongside @Incubating —
> that's the established home for framework-level (non-transform)
> annotations.
>    - The version range is exactly Jochen's "introduced → no longer used
> but still maintained." since + obsoleteSince captures the live span;
> removableIn encodes the cleanup trigger so it's not lost. This
> directly maps onto reality: staticArrayAccess would be since="2.5.0",
>    obsoleteSince="6.0.0"; the v7 entry points since="2.5.0",
> obsoleteSince="3.0.0"; bootstrap since="2.1.0" with no obsolete date.
>    - RUNTIME + descriptor() unlocks the real payoff over a doc comment:
> a tiny test (or extend the existing binary-compatibility subproject)
> can reflect over all @BytecodeInterfacing members and assert the
> descriptor still matches — so an accidental signature change to a
> frozen method fails
>    CI, while everything not annotated is understood to be freely
> mutable. That's the enforcement @Internal can't give you.
>    - It's orthogonal to @Internal/@Deprecated: a method can be
> @Internal (don't call from source) and @BytecodeInterfacing (but the
> signature is frozen for old class files). @Deprecated is wrong for the
> live bootstrap — it's not deprecated, it's permanent-by-contract;
> conversely
>    fromCache/selectMethod are @Deprecated but not @BytecodeInterfacing,
> which instantly tells you they're removable. That contrast is the
> whole argument for a distinct annotation.
> 
> On Wed, Jun 17, 2026 at 8:46 AM Jochen Theodorou <[email protected]> wrote:
>>
>> Actually I have one question...
>>
>> Can we make all the indy callsite code, including IndyInterface
>> internal, to allow us to freely change the public method signatures?
>> Plus I was thinking that maybe we should add another such annotation,
>> that we could call BytecodeInterfacing or something like that, to mark a
>> method as directly called from compiled bytecode. Even better with a
>> version range for when it was introduced to when it was no longer used,
>> but still needs to be maintained to support older Groovy versions.
>>
>> bye Jochen
>>
>> On 6/16/26 14:53, Paul King wrote:
>>> Hi folks,
>>>
>>> I have just a few things to tidy up (maybe a day or two) then I plan
>>> to do releases 5.0.7 and 6.0.0-alpha-2.
>>>
>>> Let me know if you are working on something that should be included or
>>> anything which we should wait for.
>>>
>>> Thanks, Paul.
>>