Allow Hash#[] to be aliased again - #6675
Conversation
found as a bug in mruby-hashie and bisected to commit 09336c5 which adds OP_(GET|SET)IDX. OP_SETIDX seeps to default to dispatch as of now.
if it's aliased, goto default dispatch, otherwise use mrb_hash_set
Summary of ChangesHello @pzskc383, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request introduces a critical fix to mruby by re-enabling the aliasing of the Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request restores the ability to alias Hash#[], which was broken by a previous optimization. The change in src/vm.c adds a check to see if Hash#[] has been redefined before taking the optimized path. This fixes compatibility with libraries like mruby-hashie and also allows monkey-patching Hash directly, as demonstrated by the new tests in test/t/hash.rb.
My main concern is with the implementation of the check in src/vm.c. While it correctly handles redefinitions in Ruby, it is not robust against redefinitions with another C function, which could lead to incorrect behavior. I've added a detailed comment about this. The added tests are good and cover both subclassing and direct monkey-patching scenarios.
|
My concern is the performance. If we call |
|
wouldn't it be possible to use some of the left-over flag bits of the |
Apply the same pattern as the Hash fix: the OP_GETIDX optimization now only applies to instances of the Array class itself. Subclasses fall back to method dispatch, allowing them to override the [] method. Co-authored-by: Claude <noreply@anthropic.com>
Apply the same pattern as the Array/Hash fix: the OP_GETIDX optimization now only applies to instances of the String class itself. Subclasses fall back to method dispatch, allowing them to override the [] method. Co-authored-by: Claude <noreply@anthropic.com>
Add inline optimizations for Array#[]= and Hash#[]= in OP_SETIDX, matching the pattern established for OP_GETIDX: - Array class: use mrb_ary_set() directly (integer index only) - Hash class: use mrb_hash_set() directly - Subclasses: fall back to method dispatch (can override []=) - String: unchanged (complex 2-3 argument signature) Co-authored-by: Claude <noreply@anthropic.com>
|
Thank you for the report and the PR. I've implemented an alternative fix in commit e28372df57 that takes a different approach to balance performance and flexibility The FixInstead of calling case MRB_TT_HASH:
/* optimize only for Hash class; subclasses may override [] */
if (mrb_obj_class(mrb, va) != mrb->hash_class) goto getidx_fallback;
va = mrb_hash_get(mrb, va, vb);
...Behavior
Why This Works for mruby-hashieThe mruby-hashie library uses a class Mash < Hash
alias_method :regular_reader, :[]
def [](key)
# custom logic
regular_reader(convert_key(key))
end
endSince Trade-offOverriding class Hash
def [](key); "custom"; end # Won't be called for Hash instances
endThis is an acceptable trade-off for mruby because:
This semantic is similar to having "final" method behavior on core classes - if you need custom |
This prevents
mruby-hashiefrom working properly on current mruby, it uses similar pattern here and it was working on 3.0.0, so i was able to trace it to commit 09336c5 using testcases.Now, i'm not sure about performance impact of this. An alternative would be checking if class is still Hash and allow redefining only in subclasses, i.e.
if (mrb_class(mrb, va) != mrb->hash_class) {Thank you in advance.