Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ClassCastException at runtime in with closure #1412

Closed
mauromol opened this issue Oct 25, 2022 · 7 comments
Closed

ClassCastException at runtime in with closure #1412

mauromol opened this issue Oct 25, 2022 · 7 comments
Assignees
Labels
Milestone

Comments

@mauromol
Copy link

I have an inconsistent behaviour with code like this.

package testcce;
public class TestCce {
	public static void main(String[] args) {
		final Foo f = new Foo();
		f.foobar();
		f.getBar().setBar("aaa");
	}
}
package testcce
import groovy.beans.Bindable
import groovy.transform.CompileStatic
@CompileStatic
class Bar {
	@Bindable
	String bar
	String other
}
package testcce
import groovy.beans.Bindable
import groovy.transform.CompileStatic
@CompileStatic
class Foo {
	Bar bar
	@Bindable
	String foo
	
	void foobar() {
		bar = new Bar()
		bar.with {
			addPropertyChangeListener('bar') {
				other = 'something'
				println 'ok'
			}
		}
		println 'end'
	}
}

If I run this from Eclipse (using Greclipse 4.8.0.v202210232216-e2206) I get the following ClassCastException:

Exception in thread "main" java.lang.ClassCastException: class testcce.Foo cannot be cast to class testcce.Bar (testcce.Foo and testcce.Bar are in unnamed module of loader 'app')
	at testcce.Foo$_foobar_closure1$_closure2.doCall(Foo.groovy:14)

If I compile and run this with Gradle/groovyc (with Groovy 2.5.19), all works fine.
What is really strange is that this is just a test case I could extract from my real project. With my real project I see the exact same exception even if I compile it with Gradle and run the application under Tomcat in the test and production environments.

A workaround is to add @CompileDynamic to Foo.foobar().

@mauromol
Copy link
Author

mauromol commented Oct 25, 2022

Please note this problem exists at least since Groovy 2.5.13.

@eric-milles
Copy link
Member

eric-milles commented Oct 25, 2022

I was just looking at this sort of thing over the weekend. Your deepest closure block has "owner" the with closure, "owner.delegate" Bar and "owner.owner" Foo. The implicit-this calls to addPropertyChangeListener, setOther and println require some precise handling in the static compiler. "other = 'something'" is converted to "this.other = 'something'" with metadata "owner.delegate" for "this". Then the class generator converts it to "this.getOwner().getDelegate().setOther('something')" and there are check-casts for each path element.

If the latest snapshot still has a problem with this after the GROOVY-9089 fix, you can add parameter to with block or event block and then use param or "it" to qualify "other" to make it explicit instead of dynamic compilation.

@mauromol
Copy link
Author

Hi Eric,
sorry, I'm not sure I understand what I should test. Do I have to update Greclipse to the latest snapshot? It is enough?
Is there a bug in Groovy as well? The mentioned GROOVY-9089 seems to be fixed in Groovy 2.5.7, so long time ago.

@eric-milles
Copy link
Member

The latest snapshot includes a fix for 9089, which I discovered over the weekend had regressed. I cannot recreate your issue with current code unless I'm missing something.

eric-milles added a commit that referenced this issue Oct 25, 2022
@eric-milles
Copy link
Member

You can work around this with something like:

		bar.with {
			addPropertyChangeListener('bar') { event ->
				it.other = 'something'
				println 'ok'
			}
		}

@mauromol
Copy link
Author

Indeed, this seems to work when running the code from Eclipse with Greclipse 4.8.0.v202210241547-e2206. However, how is this supposed to go into Groovy? GROOVY-9089 is still closed. Should we open a new issue for Groovy or do you plan to reopen GROOVY-9089?

@eric-milles
Copy link
Member

eric-milles commented Oct 25, 2022

The fix for 9089 went into the main project at the same time. It will be in the next Groovy 2.5, 3.0 and 4.0 releases. apache/groovy@dac95ae

@eric-milles eric-milles self-assigned this Oct 26, 2022
@eric-milles eric-milles added this to the v4.8.0 milestone Oct 26, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants