-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
GROOVY-7971: do not save instanceof types under logical or #1269
Conversation
I am not sure dumbing down the type checker is the best way. It would break code like the following (for the
The above fails (randomly at runtime with a CastClassException) when using Having said that, we can improve how things are handled. We should have the concept of bottom in our type system and an arbitrary expression would yield that and then don't collect types for OR in that scenario. Then we could work on making the type checker smarter to be able to potentially handle expressions like |
Is there a test case or open ticket for your example of ArrayDeque (aka Deque, aka Queue) and Stack? There were only two test cases for the or'ing of instanceof checks. Not looking to nerf type inferencing, but in case of "... && x instanceof T" less needs to be known about what "..." represents. For "... || x instanceof T" it seems that only when "..." is another instanceof check or multiple "or instanceof" clauses do we want to track the types. Anyway, thanks for the feedback. I wanted to get something simple out there so we could talk through the possibilities. |
I've been looking at several cast exceptions over the last few days. In terms of static compilation, I find that type inferencing plays a big part. In your case "component.peek()" is probably re-written with a cast, like "((T) component).peek()". And I think T is "UnionType:ArrayDeque+Stack" in the node metadata but probably gets written out as "((java.util.ArrayDeque) component).peek()". So when component is a stack, there is a cast exception at runtime. |
This bit in StaticInvocationWriter is where a dynamic call is replaced with a cast and call to ArrayDeque#peek under static compilation. |
Yes, we'd need to augment that with either instanceof checks or some kind of invokedynamic. In theory |
So can this change go in to fix the cast exceptions and a new ticket get created for the multi-methods case? |
Well, with the current PR, we have to break the type checker to hide some of the cast errors. I'll ponder for a bit to see if we can't better fix the real underlying issues first. |
@paulk-asert Any further comments on the PR? |
I have been doing a few spikes but nothing finalised. I tried using Union and Intersection types to better model the type relationships. A logical OR with instanceof on both sides for example should have different semantics to a logical AND with instanceof on both sides. And we'd need a NotType as well at some point to have better handling of not in combination with instanceof for nested cases. I can get specific parts of our type checking processing to work as I'd hope with these in place but there are numerous places in the code which make different assumptions to what the new types would need. There are places where we ignore Object for instance which isn't what we'd now need but just removing the places where we make such tests breaks other things because various assumptions flow to other parts of the code. So, as an intermediate step, I have a slightly improved mechanism that looks for any IfStatement where the test is a binary logical OR and treats that as two individual IfStatement's corresponding to each half of the OR. It then does a separate pass to get the UnionType we currently expect for the AND case. The UnionType needs to be catered for so that we have an invokeDynamic instruction produced when @cs is in place. I think it will be a few more days before I have anything ready for review. |
@eric-milles @danielsun1106 Let me know if #1293 works for you. Failed on one CI build but works for me locally with a similar JVM. |
https://issues.apache.org/jira/browse/GROOVY-7971
This is the simplest approach I could think of. Instead of collecting all instanceof types when doing multiple checks like "it instanceof String || it instanceof Boolean || it instanceof Integer", do not collect the instanceof types because there could be any kind of boolean expresion on either side of the ||.