-
-
Notifications
You must be signed in to change notification settings - Fork 925
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
Wrong control flow order with Constant ||= #4807
Comments
There's actually something very odd going on. Here's a simple script showing how not only is JRuby not doing the right thing, but it's not even consistently doing the wrong thing...
|
FWIW,
|
I think the root of the problem is not the control flow itself. It seems that when setting a constant in the "root" (starting with
Note that all of the problems go away when not using Clearly not set where it should be...
Both uses of ::OR_EQUAL2 refer to the same (wrong) place, since the 1 is kept between both uses:
The same problem happens when using &&=. But the different flow generates a weird exception early. (In MRI, there is no exception). The output of this example should be
Note also how weird the exception message is. The refered constant is just All of the above was tested on:
OS: |
Ah, didn't see that other case. Here is some fun investigation into it. The following should puts 'h1' and then fail. Instead, we get "h1" then "h3" then "h1" then fail.
Looks like the "getting a constant" of ||= to check if the assignation is needed swallows the exception and assumes that it doesn't exist. Then, after evaluating the value, does the lookup again, without swallowing this time. Note that even if the constant exists, the lookup is done twice:
|
I have been working on this one and it will be fixed but it opened up a wormhole and I discovered another class of bugs where lhs of colon2 (foo::B) will execute twice! Fixing this is more involved but pretty imperative that it is fixed first (all cases will be fixed though). The originally reported issue was due to two issues in how we emitted instructions for this clause:
So just correct the second of those items would fix originally reported issue (and possibly the other ones) but it would be calling raise 'a' twice. If this was a user method which threw an exception but also made a db transaction you would be wondering why there were two updates instead of just one :| |
After having fixed design of ||= for constants all of that is working and it is not executing the same method twice. I ran into the second bug which was that ::A ||= was recording '::' as the name of the constant and not 'A'. Amazingly it only happens for this single case of ::{constant} {op}=. I still have to figure out &&= though. Getting much closer. |
More specifically this fixes: 1. emitting rhs of ||= in wrong order 1. not calling lhs and evaluating it twice 1. making &&= semantics correct (we need specs for that somewhere) 1. correcting return value emitted from ||= and &&= expression 1. colon3 nodes in ||= or &&= in AST was giving itself name of '::' So many things in a tiny esoteric corner of Ruby.
I almost feel bad pointing out a bug that's probably irrelevant, but maybe it could be a real issue for some strange usage of
const_missing
.Environment
Expected Behavior
In the expression
scope::Constant ||= value
,scope
should be resolved first, thenConstant
should be looked up, and only then shouldvalue
be resolved (assuming it is falsy or undefined). MRI does that, JRuby doesn't respect that order.The text was updated successfully, but these errors were encountered: