[jira] [Comment Edited] (GROOVY-8826) Captured loop variables have surprising and Java-incompatible behavior
[ https://issues.apache.org/jira/browse/GROOVY-8826?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=16642619#comment-16642619 ] Jochen Theodorou edited comment on GROOVY-8826 at 10/8/18 11:57 PM: right now {code:java} for (int i=0; i System.out.println(\i)); it is clear, that the same i is used for all parts of the loop. This is for the classic for-loop as well as for any foreach loop. The final value in my example would be btw max. A "fix" would be this transformation: {code:java} { int tmp = 0 while (tmp System.out.println(i)); it is clear, that the same i is used for all parts of the loop. This is for the classic for-loop as well as for any foreach loop. The final value in my example would be btw max. A "fix" would be this transformation: {code:java} { int tmp = 0 while (tmp Captured loop variables have surprising and Java-incompatible behavior > -- > > Key: GROOVY-8826 > URL: https://issues.apache.org/jira/browse/GROOVY-8826 > Project: Groovy > Issue Type: Bug >Affects Versions: 3.0.0-alpha-3 >Reporter: Роман Донченко >Priority: Major > > Consider this source: > {code:java} > import java.util.ArrayList; > import java.util.Arrays; > public class Test { > public static void main(String... args) { > ArrayList closures = new ArrayList<>(); > for (int i: new int[] {1, 2}) > closures.add(() -> System.out.println(i)); > for (Runnable closure: closures) > closure.run(); > } > } > {code} > If it's compiled as Java, the output is: > {code} > 1 > 2 > {code} > But if it's compiled as Groovy, the output is: > {code} > 2 > 2 > {code} > In other words, in Java each iteration gets a unique instance of the {{i}} > variable, which is captured in the corresponding closure, while in Groovy, > only one {{i}} variable exists and is captured into both closures. IMO, the > Groovy behavior is significantly less useful, and it would be nice if in 3.0 > it was changed to match Java. > Groovy also exhibits the same behavior with Groovy closures and > {{for(...in...)}} loops. I just used Java-compatible syntax for this example > in order to contrast Groovy and Java. -- This message was sent by Atlassian JIRA (v7.6.3#76005)
[jira] [Comment Edited] (GROOVY-8764) Closure inside an anonymous class uses wrong outside class instance with @CS
[ https://issues.apache.org/jira/browse/GROOVY-8764?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=16641645#comment-16641645 ] Paul King edited comment on GROOVY-8764 at 10/8/18 11:57 PM: - This doesn't occur if only the method has @CompileStatic like in this script: {code} import groovy.transform.* @Field String foo = 'FOO' @CompileStatic void test() { new Runnable() { void run() { def c = { println foo } c() } } .run() } test() {code} Or in this class: {code} import groovy.transform.* class GroovyTest { private String foo = 'FOO' @CompileStatic void test() { new Runnable() { void run() { def c = { println foo } c() } }.run() } } new GroovyTest().test() {code} Basically the inner closure will be dynamic code in those cases. was (Author: paulk): This doesn't occur if only the method has @CompileStatic like in this script: {code} import groovy.transform.* @Field String foo = 'FOO' @CompileStatic void test() { new Runnable() { void run() { def c = { println foo } c() } } .run() } test() {code} Or in this class: {code} import groovy.transform.* class GroovyTest { private String foo = 'FOO' @CompileStatic void test() { new Runnable() { void run() { def c = { println foo } c() } }.run() } } new GroovyTest().test() {code} > Closure inside an anonymous class uses wrong outside class instance with @CS > > > Key: GROOVY-8764 > URL: https://issues.apache.org/jira/browse/GROOVY-8764 > Project: Groovy > Issue Type: Bug > Components: Compiler, Static compilation >Affects Versions: 2.4.15, 3.0.0-alpha-3, 2.5.2 >Reporter: Xiaoguang Wang >Priority: Major > > This bug only occurs with @ComplieStatic > Affects 2.4/2.5/3.0 > > {code:java} > @CompileStatic > class GroovyTest { > private String foo > void test() { > new Runnable() { > void run() { > def c = { > foo > } > c() > } > } .run() > } > static void main(String ...args) { > new GroovyTest().test() > } > } > {code} > Crash: > {code:java} > Exception in thread "main" java.lang.ClassCastException: > com.test.spring4mvc.controller.GroovyTest$1 cannot be cast to > com.test.spring4mvc.controller.GroovyTest > at > com.test.spring4mvc.controller.GroovyTest$1$_run_closure1.doCall(GroovyTest.groovy) > at > com.test.spring4mvc.controller.GroovyTest$1$_run_closure1.call(GroovyTest.groovy) > at com.test.spring4mvc.controller.GroovyTest$1.run(GroovyTest.groovy:16) > at com.test.spring4mvc.controller.GroovyTest.test(GroovyTest.groovy:11) > at com.test.spring4mvc.controller.GroovyTest.main(GroovyTest.groovy:22) > {code} -- This message was sent by Atlassian JIRA (v7.6.3#76005)
[jira] [Commented] (GROOVY-8764) Closure inside an anonymous class uses wrong outside class instance with @CS
[ https://issues.apache.org/jira/browse/GROOVY-8764?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=16642618#comment-16642618 ] Paul King commented on GROOVY-8764: --- Workaround is to prefix the method call, e.g. {{this.println}} instead of {{println}}: {code:java} import groovy.transform.* @CompileStatic class GroovyTest { public String foo = 'FOO' void test() { new Runnable() { void run() { def c = { this.println foo } c() } }.run() } } new GroovyTest().test() {code} > Closure inside an anonymous class uses wrong outside class instance with @CS > > > Key: GROOVY-8764 > URL: https://issues.apache.org/jira/browse/GROOVY-8764 > Project: Groovy > Issue Type: Bug > Components: Compiler, Static compilation >Affects Versions: 2.4.15, 3.0.0-alpha-3, 2.5.2 >Reporter: Xiaoguang Wang >Priority: Major > > This bug only occurs with @ComplieStatic > Affects 2.4/2.5/3.0 > > {code:java} > @CompileStatic > class GroovyTest { > private String foo > void test() { > new Runnable() { > void run() { > def c = { > foo > } > c() > } > } .run() > } > static void main(String ...args) { > new GroovyTest().test() > } > } > {code} > Crash: > {code:java} > Exception in thread "main" java.lang.ClassCastException: > com.test.spring4mvc.controller.GroovyTest$1 cannot be cast to > com.test.spring4mvc.controller.GroovyTest > at > com.test.spring4mvc.controller.GroovyTest$1$_run_closure1.doCall(GroovyTest.groovy) > at > com.test.spring4mvc.controller.GroovyTest$1$_run_closure1.call(GroovyTest.groovy) > at com.test.spring4mvc.controller.GroovyTest$1.run(GroovyTest.groovy:16) > at com.test.spring4mvc.controller.GroovyTest.test(GroovyTest.groovy:11) > at com.test.spring4mvc.controller.GroovyTest.main(GroovyTest.groovy:22) > {code} -- This message was sent by Atlassian JIRA (v7.6.3#76005)
[jira] [Commented] (GROOVY-8815) Inconsistent class file - undefined type parameter for trait implementer
[ https://issues.apache.org/jira/browse/GROOVY-8815?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=16642424#comment-16642424 ] Eric Milles commented on GROOVY-8815: - Pending changes for 2.5.3 have moved this problem a bit. {code:java} public static Map addMethodGenerics(MethodNode current, Map oldSpec) { Map ret = new HashMap(oldSpec); // ret starts with the original type specs, now add gts for the current method if any GenericsType[] sgts = current.getGenericsTypes(); if (sgts != null) { for (GenericsType sgt : sgts) { String name = sgt.getName(); if (sgt.isPlaceholder()) { ClassNode redirect; if (sgt.getUpperBounds() != null) { redirect = sgt.getUpperBounds()[0]; } else if (sgt.getLowerBound() != null) { redirect = sgt.getLowerBound(); } else { redirect = ClassHelper.OBJECT_TYPE; } // At this point, name is "E" and redirect is "Event -> Event " ClassNode type = ClassHelper.makeWithoutCaching(name); type.setGenericsPlaceHolder(true); type.setRedirect(redirect); // this call takes "Event " only and the inconsistent class file issue returns ret.put(name, type); } else { ret.put(name, sgt.getType()); } } } return ret; } {code} > Inconsistent class file - undefined type parameter for trait implementer > > > Key: GROOVY-8815 > URL: https://issues.apache.org/jira/browse/GROOVY-8815 > Project: Groovy > Issue Type: Bug >Affects Versions: 2.4.15, 2.5.2 >Reporter: Eric Milles >Priority: Major > > When compiling the following classes, the Service class ends up with an > incomplete type parameter in it. This causes errors for the IDE: > "Inconsistent classfile encountered: The undefined type parameter T is > referenced from within Service" > {code} > import java.util.function.Consumer > import groovy.transform.CompileStatic > class Event { > Event(String id, T payload) { > } > Event setReplyTo(Object replyTo) { > } > } > @CompileStatic > trait Events { > def > Registration> on(Class key, > Closure consumer) { > } > } > interface Registration { > } > class Service implements Events { > } > {code} > javap output for Events shows: > {code:java} > public abstract > > Registration> > on(java.lang.Class, groovy.lang.Closure); > {code} > javap output for Service shows: > {code:java} > public > Registration java.util.function.Consumer> on(java.lang.Class, groovy.lang.Closure); > public > Registration java.util.function.Consumer> Eventstrait$super$on(java.lang.Class, > groovy.lang.Closure); > {code} > It is this "T" in the trait method that is not defined. I think it should be > "?" instead when looking at the original method's and the trait bridge > method's type parameters. -- This message was sent by Atlassian JIRA (v7.6.3#76005)
[jira] [Commented] (GROOVY-8764) Closure inside an anonymous class uses wrong outside class instance with @CS
[ https://issues.apache.org/jira/browse/GROOVY-8764?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=16641645#comment-16641645 ] Paul King commented on GROOVY-8764: --- This doesn't occur if only the method has @CompileStatic like in this script: {code} import groovy.transform.* @Field String foo = 'FOO' @CompileStatic void test() { new Runnable() { void run() { def c = { println foo } c() } } .run() } test() {code} Or in this class: {code} import groovy.transform.* class GroovyTest { private String foo = 'FOO' @CompileStatic void test() { new Runnable() { void run() { def c = { println foo } c() } }.run() } } new GroovyTest().test() {code} > Closure inside an anonymous class uses wrong outside class instance with @CS > > > Key: GROOVY-8764 > URL: https://issues.apache.org/jira/browse/GROOVY-8764 > Project: Groovy > Issue Type: Bug > Components: Compiler, Static compilation >Affects Versions: 2.4.15, 3.0.0-alpha-3, 2.5.2 >Reporter: Xiaoguang Wang >Priority: Major > > This bug only occurs with @ComplieStatic > Affects 2.4/2.5/3.0 > > {code:java} > @CompileStatic > class GroovyTest { > private String foo > void test() { > new Runnable() { > void run() { > def c = { > foo > } > c() > } > } .run() > } > static void main(String ...args) { > new GroovyTest().test() > } > } > {code} > Crash: > {code:java} > Exception in thread "main" java.lang.ClassCastException: > com.test.spring4mvc.controller.GroovyTest$1 cannot be cast to > com.test.spring4mvc.controller.GroovyTest > at > com.test.spring4mvc.controller.GroovyTest$1$_run_closure1.doCall(GroovyTest.groovy) > at > com.test.spring4mvc.controller.GroovyTest$1$_run_closure1.call(GroovyTest.groovy) > at com.test.spring4mvc.controller.GroovyTest$1.run(GroovyTest.groovy:16) > at com.test.spring4mvc.controller.GroovyTest.test(GroovyTest.groovy:11) > at com.test.spring4mvc.controller.GroovyTest.main(GroovyTest.groovy:22) > {code} -- This message was sent by Atlassian JIRA (v7.6.3#76005)
[jira] [Created] (GROOVY-8834) Making "public" - BinaryExpression.leftExpression and similar fields
Anton Pryamostanov created GROOVY-8834: -- Summary: Making "public" - BinaryExpression.leftExpression and similar fields Key: GROOVY-8834 URL: https://issues.apache.org/jira/browse/GROOVY-8834 Project: Groovy Issue Type: Wish Reporter: Anton Pryamostanov This is a general request related to AST API. Currently BinaryExpression.leftExpression and similar fields are having Private access. So to change the value, we need to replace the whole BinaryExpression with new one. This is not useful as it requires coding outside of Visitor methods, and I do not see reason why it should be private. It will greatly simplify visitor methods and transformations, if all Expression fields will have Public access. Alternatively please add setter methods with Public access. List of fields to be changed from Private to Public: {code:java} ArrayExpression->expressions ArrayExpression->sizeExpression BitwiseNegationExpression->expression BooleanExpression->expression CastExpression->expression ConstructorCallExpression->arguments GStringExpression->strings GStringExpression->values ListExpression->expressions MapExpression->mapEntryExpressions MethodPointerExpression->expression MethodPointerExpression->methodName PropertyExpression->property RangeExpression->from RangeExpression->to SpreadExpression->expression SpreadMapExpression->expression StaticMethodCallExpression->arguments TernaryExpression->booleanExpression TernaryExpression->trueExpression TernaryExpression->falseExpression TupleExpression->expressions UnaryMinusExpression->expression UnaryPlusExpression->expression{code} -- This message was sent by Atlassian JIRA (v7.6.3#76005)
[jira] [Updated] (GROOVY-8764) Closure inside an anonymous class uses wrong outside class instance with @CS
[ https://issues.apache.org/jira/browse/GROOVY-8764?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Paul King updated GROOVY-8764: -- Summary: Closure inside an anonymous class uses wrong outside class instance with @CS (was: Closure inside an anonymous class uses wrong outside class instance) > Closure inside an anonymous class uses wrong outside class instance with @CS > > > Key: GROOVY-8764 > URL: https://issues.apache.org/jira/browse/GROOVY-8764 > Project: Groovy > Issue Type: Bug > Components: Compiler, Static compilation >Affects Versions: 2.4.15, 3.0.0-alpha-3, 2.5.2 >Reporter: Xiaoguang Wang >Priority: Major > > This bug only occurs with @ComplieStatic > Affects 2.4/2.5/3.0 > > {code:java} > @CompileStatic > class GroovyTest { > private String foo > void test() { > new Runnable() { > void run() { > def c = { > foo > } > c() > } > } .run() > } > static void main(String ...args) { > new GroovyTest().test() > } > } > {code} > Crash: > {code:java} > Exception in thread "main" java.lang.ClassCastException: > com.test.spring4mvc.controller.GroovyTest$1 cannot be cast to > com.test.spring4mvc.controller.GroovyTest > at > com.test.spring4mvc.controller.GroovyTest$1$_run_closure1.doCall(GroovyTest.groovy) > at > com.test.spring4mvc.controller.GroovyTest$1$_run_closure1.call(GroovyTest.groovy) > at com.test.spring4mvc.controller.GroovyTest$1.run(GroovyTest.groovy:16) > at com.test.spring4mvc.controller.GroovyTest.test(GroovyTest.groovy:11) > at com.test.spring4mvc.controller.GroovyTest.main(GroovyTest.groovy:22) > {code} -- This message was sent by Atlassian JIRA (v7.6.3#76005)
[jira] [Updated] (GROOVY-8827) Close a small gap in the EMC DSL for constructors
[ https://issues.apache.org/jira/browse/GROOVY-8827?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Paul King updated GROOVY-8827: -- Fix Version/s: (was: 2.5.4) 2.5.3 > Close a small gap in the EMC DSL for constructors > - > > Key: GROOVY-8827 > URL: https://issues.apache.org/jira/browse/GROOVY-8827 > Project: Groovy > Issue Type: Improvement >Affects Versions: 2.5.3 >Reporter: Paul King >Assignee: Paul King >Priority: Major > Fix For: 3.0.0-alpha-4, 2.5.3 > > > In the sample below, the first short-hand (Integer case) is recognised, the > second two aren't for constructors even though they are for methods and work > if "" is used instead: > {code} > Integer.metaClass { > constructor = { List l -> l.size() } > } > Short.metaClass { > constructor { List l -> l.size() as short } > } > Long.metaClass { > constructor << { List l -> l.size() as long } > } > def result = [[] as Short, ['foo'] as Integer, ['bar', 'baz'] as Long] > assert result.toString() == '[0, 1, 2]' > assert result*.class == [Short, Integer, Long] > {code} -- This message was sent by Atlassian JIRA (v7.6.3#76005)
[jira] [Updated] (GROOVY-8833) @Canonical creates invalid hashCode
[ https://issues.apache.org/jira/browse/GROOVY-8833?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Paul King updated GROOVY-8833: -- Affects Version/s: (was: 2.5.3) 2.5.2 > @Canonical creates invalid hashCode > --- > > Key: GROOVY-8833 > URL: https://issues.apache.org/jira/browse/GROOVY-8833 > Project: Groovy > Issue Type: Bug > Components: Compiler >Affects Versions: 2.5.2 >Reporter: Kenzie Togami >Priority: Critical > Fix For: 3.0.0-alpha-4, 2.5.3 > > > Applying {{@Canonical}} to a class will generate an invalid hashCode method > that throws a runtime cast exception. This does not happen if you apply the > individual annotations by themselves. > These tests can be injected into a Groovy test class to see the problem: > [https://gist.github.com/kenzierocks/fb0932756c3955a7ddbc0b710791af11] > I suspect the underlying cause is that {{@EqualsAndHashCode}} does not set > {{accessedVariable}} on its {{_result}} variable, which causes the verifier > to overwrite it with {{toString}}'s {{_result}} variable (see > {{FinalVariableAnalyzer#fixVar}}). This results in an invalid cast. I > observed this behavior while debugging the compiler. I'm not sure why this > doesn't also happen if the two annotations are applied by themselves, rather > than via {{@Canonical}}. > > I was able to fix this problem by setting {{_result}} to reference itself in > the AST, but perhaps that's not the right fix here. -- This message was sent by Atlassian JIRA (v7.6.3#76005)
[jira] [Commented] (GROOVY-8833) @Canonical creates invalid hashCode
[ https://issues.apache.org/jira/browse/GROOVY-8833?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=16641636#comment-16641636 ] Paul King commented on GROOVY-8833: --- Well spotted. This is now fixed. > @Canonical creates invalid hashCode > --- > > Key: GROOVY-8833 > URL: https://issues.apache.org/jira/browse/GROOVY-8833 > Project: Groovy > Issue Type: Bug > Components: Compiler >Affects Versions: 2.5.2 >Reporter: Kenzie Togami >Priority: Critical > Fix For: 3.0.0-alpha-4, 2.5.3 > > > Applying {{@Canonical}} to a class will generate an invalid hashCode method > that throws a runtime cast exception. This does not happen if you apply the > individual annotations by themselves. > These tests can be injected into a Groovy test class to see the problem: > [https://gist.github.com/kenzierocks/fb0932756c3955a7ddbc0b710791af11] > I suspect the underlying cause is that {{@EqualsAndHashCode}} does not set > {{accessedVariable}} on its {{_result}} variable, which causes the verifier > to overwrite it with {{toString}}'s {{_result}} variable (see > {{FinalVariableAnalyzer#fixVar}}). This results in an invalid cast. I > observed this behavior while debugging the compiler. I'm not sure why this > doesn't also happen if the two annotations are applied by themselves, rather > than via {{@Canonical}}. > > I was able to fix this problem by setting {{_result}} to reference itself in > the AST, but perhaps that's not the right fix here. -- This message was sent by Atlassian JIRA (v7.6.3#76005)
[jira] [Resolved] (GROOVY-8833) @Canonical creates invalid hashCode
[ https://issues.apache.org/jira/browse/GROOVY-8833?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Paul King resolved GROOVY-8833. --- Resolution: Fixed Assignee: Paul King Fix Version/s: 2.5.3 3.0.0-alpha-4 > @Canonical creates invalid hashCode > --- > > Key: GROOVY-8833 > URL: https://issues.apache.org/jira/browse/GROOVY-8833 > Project: Groovy > Issue Type: Bug > Components: Compiler >Affects Versions: 2.5.2 >Reporter: Kenzie Togami >Assignee: Paul King >Priority: Critical > Fix For: 3.0.0-alpha-4, 2.5.3 > > > Applying {{@Canonical}} to a class will generate an invalid hashCode method > that throws a runtime cast exception. This does not happen if you apply the > individual annotations by themselves. > These tests can be injected into a Groovy test class to see the problem: > [https://gist.github.com/kenzierocks/fb0932756c3955a7ddbc0b710791af11] > I suspect the underlying cause is that {{@EqualsAndHashCode}} does not set > {{accessedVariable}} on its {{_result}} variable, which causes the verifier > to overwrite it with {{toString}}'s {{_result}} variable (see > {{FinalVariableAnalyzer#fixVar}}). This results in an invalid cast. I > observed this behavior while debugging the compiler. I'm not sure why this > doesn't also happen if the two annotations are applied by themselves, rather > than via {{@Canonical}}. > > I was able to fix this problem by setting {{_result}} to reference itself in > the AST, but perhaps that's not the right fix here. -- This message was sent by Atlassian JIRA (v7.6.3#76005)
[jira] [Updated] (GROOVY-8819) java.lang.VerifyError when calling this() with static final field from a super class
[ https://issues.apache.org/jira/browse/GROOVY-8819?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Paul King updated GROOVY-8819: -- Fix Version/s: (was: 2.5.4) 2.5.3 > java.lang.VerifyError when calling this() with static final field from a > super class > > > Key: GROOVY-8819 > URL: https://issues.apache.org/jira/browse/GROOVY-8819 > Project: Groovy > Issue Type: Bug > Components: Compiler >Affects Versions: 2.4.x, 2.5.2 >Reporter: Keith Suderman >Assignee: Daniel Sun >Priority: Minor > Fix For: 3.0.0-alpha-4, 2.5.3 > > > If a constructor attempts to call _this(X)_, where _X_ is a _static final_ > field defined in a super class a _java.lang.VerifyError_ is thrown at runtime > . This only occurs if _X_ is not qualified with the super class name. > {code:java|title=Parent.java|borderStyle=solid} > class Parent { > static final String DEFAULT = 'default' > } > {code} > {code:java|title=Child.java|borderStyle=solid} > class Child extends Parent { > String value > Child() { this(DEFAULT) } // <-- here > Child(String value) { this.value = value } > } > {code} > {noformat:title=java.lang.VerifyError} > Caught: java.lang.VerifyError: Bad type on operand stack > Exception Details: > Location: > Child.()V @10: invokeinterface > Reason: > Type uninitializedThis (current frame, stack[2]) is not assignable to > 'java/lang/Object' > Current Frame: > bci: @10 > flags: \{ flagThisUninit } > locals: \{ uninitializedThis, > '[Lorg/codehaus/groovy/runtime/callsite/CallSite;' } > stack: \{ uninitializedThis, > 'org/codehaus/groovy/runtime/callsite/CallSite', uninitializedThis } > Bytecode: > 0x000: b800 114c 2a2b 1212 322a b900 1802 00b8 > 0x010: 001e c000 20b7 0023 b1 > {noformat} > *Workaround* > Simply ensure that references to static final fields from the super class are > qualified with the super class name. > {code:java|title=Child.java|borderStyle=solid} > class Child extends Parent { > String value > Child() { this(Parent.DEFAULT) } // ok > Child(String value) { this.value = value } > } > {code} -- This message was sent by Atlassian JIRA (v7.6.3#76005)