Repository navigation
Boxed receivers dispatch user <, >, <= and >= without coerce - #8013
Conversation
A boxed comparison reaches a user class's operator through sp_user_binop_hook. Its dispatch table already has comparison arms, but hook detection required the class to have the coerce shape. A class with its own ordering could therefore fall through to sp_poly_cmp and raise ArgumentError when its receiver arrived in a box. The existing operator scan now uses is_cmp_op and comp_method_in_chain to enable the table for a class defining or inheriting <, >, <= or >=, independently of coerce. The other hook conditions and numeric comparison fast paths stay unchanged. The regression covers all four operators, non-Boolean results, inherited methods and mixed numeric receivers. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Gate: green tree 6bddc26 master 9922a2c (linux-x86_64 gcc-13.3.0) tests 6440/0
b22c595 to
ada0f34
Compare
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configuration
📒 Files selected for processing (4)
Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 7 remain after this review. 📝 WalkthroughWalkthroughThe code generator now enables user binary-operator dispatch for comparison operators without requiring ChangesComparison dispatch
Priority: ➖ Normal Estimated code review effort: 2 (Simple) | ~10 minutes Change: Bug fix Merge Risk: ⚪ Minimal · up to The change enables comparison dispatch for classes without coerce, and the regression fixture checks comparison results and hook installation. No actionable merge-blocking risk was identified in the supplied evidence. Security Architecture ReviewSecurity architecture risk: 🔵 Low · up to The change restores comparisons for user-defined objects without demonstrating new external access or privilege. Initialization and concurrent-use guarantees remain incompletely verified, limiting assurance. Retained concerns Security review detailsSecurity Blast Radius
Trust Boundaries and Controls
Resilience and Maintainability Implications
🚥 Pre-merge checks | ✅ 4 | ❓ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (4 passed)
Full details: Docstring CoverageExplanation Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 6 functions across 1 files. (3 skipped: 2 unsupported, 1 too large.)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Probed at master
fc7ef4762800b37b70732e5910d1c1a05fa68382, macOS, Apple clang 21.trueArgumentError: comparison of Money with Money failedtruesp_user_binop_hook. Its existingsp_user_binop_dispatchtable already supports<,>,<=and>=.codegen_programenabled that table for these operators only when another operator or acoerceshape already required it. A class defining only its own ordering could fall through tosp_poly_cmp, which cannot supply that ordering.Why. A class's own comparison must work when its receiver comes out of a mixed Array or a polymorphic parameter, including inherited operators and non-Boolean return values.
The fix (
src/codegen.c). Extend the existing hook-detection scan withis_cmp_opandcomp_method_in_chain. A class defining or inheriting<,>,<=or>=enables the existing dispatch table without requiringcoerce. The other hook conditions, runtime comparison paths and String-sharing behavior stay unchanged. The source change adds four lines, including its comment.Performance and C change. This restores comparison dispatch; no benchmark speedup is claimed. All 67 benchmarks and optcarrot emit byte-identical C against the master above, both by default and with
SPINEL_SHARE_STRINGS=1(-S --no-line-map). Neither mode has a benchmark or optcarrot candidate for callgrind. Numeric receivers still avoid the user hook through the existing numeric and receiver-kind checks.In the eight related tests compared in both modes, only two programs change C:
poly_user_relop_no_coerce: the new regression gains the operator table and hook installation for Money's four comparison methods and Euro's inherited methods.visibility_explicit_receiver: the existing test gains the table and hook installation for Account's>and Savings' inherited>.The other six related tests emit identical C. All 76 samples compile in each mode; there are no refusal changes. The full corpus comparison is pending.
Corpus C diff. Against master
80e28dd29, of the 6,524 programs intest/,test/infer/,benchmark/, the packages' tests and optcarrot, 2 programs change: this PR's newtest/poly_user_relop_no_coerce.rband 1 existing ones:test/visibility_explicit_receiver.rb. The only other differences are the build stamp inRUBY_DESCRIPTION. The benchmarks and optcarrot emit the same C as before.Callgrind. Not run: optcarrot and all 67 benchmarks emit byte-identical C in both builds, and
lib/is untouched.Tests. Eight focused tests match their CRuby 4.0 frozen-literal output in 64 run configurations: default/share-strings, plain/promote, and normal/GC stress. The new regression covers all four operators, Symbol and nil results, inherited methods, mixed Array reads, a polymorphic parameter, a sort block and numeric neighbors. On current master it raises
comparison of Money with Euro failedin both string modes.make -j3,make infer-test(46 fixtures plus its C assertions), andmake share-strings-test(179 programs, normal and GC stress: 358 runs) pass. Traits checks pass for 52 kinds in both integer modes; builtin arity checks pass for 494 Method rows and 914 operation rows. The 16 focused representation/plan-check compiles preserve generated C and show no representation or call-plan conflicts. The Linux aarch64 build inspinel-cgpasses with GCC 13.3 (make -j3 all CC=gcc OPT=-O1); the new regression passes all eight string/integer/GC configurations there at-O1.Not covered, also on master:
--plan-checkreports thatopenhas a hand sharing row without an iterator row. Diagnostics for all 16 focused compiles, including the existing fallback and unrecorded-call messages, are identical to master's.make gate(on this branch merged with current master)Merged with master
9922a2c74:.expectedfiles that match CRuby 4.0 run with--enable-frozen-string-literal# spinel: int64(none in the new test)🤖 Generated with Claude Code
Summary by CodeRabbit
<,>,<=, and>=operators now work for boxed values even when the class does not definecoerce.