[
https://issues.apache.org/jira/browse/GROOVY-12492?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18134636#comment-18134636
]
ASF GitHub Bot commented on GROOVY-12492:
-----------------------------------------
codeconsole commented on PR #3026:
URL: https://github.com/apache/groovy/pull/3026#issuecomment-6513965682
@daniellansun Thanks. I've split it as you suggested. This PR is now only
the incubating option: the adapter, its follow-ups, and the trait `rehydrate`
change that lets a closure written in a trait method get its adapter, which
does nothing without the option. It is rebased on current master, so the
conflicts are gone. Its 31 tests pass without any of the fixes below, so
nothing has to land first. With the option off, Groovy's 8,508 root test
classes compile to the same bytes as on master.
The fixes found while testing it are now separate:
- GROOVY-12560, #3088: `<=>` with operands of different types
- GROOVY-10979, #3089: a closure, lambda or method reference passed for a
type parameter that the call binds to a functional interface
- GROOVY-12561, #3090: a closure assigned to a subscript or property of a
functional interface type
- GROOVY-12562, #3091: `instanceof` narrowing outside a guard, comparisons
with a boolean literal, and loop conditions
- GROOVY-12563, #3092: closures and lambdas in trait methods getting the
helper class
- GROOVY-12564, #3093: calling a closure of intersection type
- GROOVY-12565, #3094: the groovy-lsp `LspFixture` race that failed CI here
Each is based on master and has a test that runs without the option. The
tests here that combined the option with one of those shapes (a closure for a
type parameter or assigned to a property, trait closure
`owner`/`thisObject`/`this.m()`, a closure of intersection type, a static
closure field of a trait) are left out for now. I'll add them back here, or in
whichever of the two PRs merges second.
> Static compilation converts closure literals to functional interfaces through
> a runtime proxy
> ---------------------------------------------------------------------------------------------
>
> Key: GROOVY-12492
> URL: https://issues.apache.org/jira/browse/GROOVY-12492
> Project: Groovy
> Issue Type: Improvement
> Components: Static compilation
> Affects Versions: 6.0.0
> Reporter: Scott Murphy Heiberg
> Priority: Major
>
> Under {{@CompileStatic}}, a closure literal whose target is a functional
> interface is still compiled to a {{Closure}} subclass and converted at run
> time. That covers a literal passed to a SAM parameter, assigned or returned
> as a SAM type, cast with {{(SAM)}}, or coerced with {{as SAM}}. For example:
> {code:groovy}
> @CompileStatic
> int sum(int n) { IntStream.range(0, n).reduce(0) { int a, int b -> a + b } }
> {code}
> compiles to {{invokedynamic
> cast:(Lgroovy/lang/Closure;)Ljava/util/function/IntBinaryOperator;}}, and the
> same closure coerced with {{as IntBinaryOperator}} to an {{asType}} call. At
> run time, {{CachedSAMClass.coerceToSAM}} /
> {{TypeTransformers.createSAMTransform}} create a {{java.lang.reflect.Proxy}}
> with a {{ConvertedClosure}} handler, and each call goes through the proxy and
> {{Closure.call(Object...)}}. The same code written as a lambda uses
> {{LambdaMetafactory}}.
> Consequences: the proxy and reflective dispatch cost on every call, and in a
> GraalVM native image each interface must be registered as a proxy, otherwise
> the statically compiled conversion fails with {{GroovyCastException}}.
> Proposal: an incubating {{groovy.target.closure.sam}} compiler option, off by
> default, that converts such literals at compile time with a generated adapter
> class that behaves as the proxy does, apart from the differences the
> documentation lists, such as the class, {{equals}} and {{hashCode}}, and the
> serialized form.
> PR: https://github.com/apache/groovy/pull/3026
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)