Repository navigation
internal/vm: Kernel#to_s prints the address for a plain object, and Thread::* carry their qualified names - #818
Open
tannevaled wants to merge 1 commit into
Open
tannevaled wants to merge 1 commit into
tannevaled wants to merge 1 commit into
Conversation
…hread::* carry their qualified names Two issues that meet on one line of output, so they are fixed together: doing either alone trades one divergence for another. #756 -- Kernel#to_s is MRI's rb_any_to_s, which ALWAYS prints the address. `Object.new.to_s` is "#<Object:0x…>", not "#<Object>". rbgo printed the short form, so #to_s and #inspect disagreed with each other INSIDE rbgo while #inspect agreed with MRI. #759 (kind A) -- Thread::Mutex, Thread::Queue, Thread::SizedQueue and Thread::ConditionVariable answered their BARE name. In MRI the class has one name, the qualified one, and the top-level `Mutex` is a second constant pointing at the same class: `Mutex.name` is "Thread::Mutex" however it was reached, and `Mutex.equal?(Thread::Mutex)` is true in both engines. They are coupled because RMutex.ToS hardcoded "#<Thread::Mutex>". Once Kernel#to_s builds its string from classOf(self).name, the bare name becomes visible as "#<Mutex:0x…>" -- a correct address with a wrong name. The first version of this commit did exactly that. ⚠ THE SCOPE IS NARROWER THAN MRI'S, deliberately. The fix applies to a plain *RObject only. Thirteen core classes reach Kernel#to_s here and MRI gives all thirteen an address, but most are Go types whose own ToS() IS their #to_s -- rbgo implements many objects' to_s as the Go method rather than as a registered Ruby one, and they arrive at Kernel#to_s relying on the delegation. A version that applied the identity form to everything reaching Kernel#to_s broke 78 TESTS, and they were right to break: Capistrano::Server#to_s "db1" the hostname Capistrano::Task#to_s "solo" the task name Net::SMTP::Response#to_s "250 2.0.0 queued" OpenIDConnect::ProviderMetadata "#<… issuer=…>" the top-level self "main" irb's prompt I had transposed a rule that is true of MRI -- "reaching rb_any_to_s means the receiver has no useful representation" -- into an engine whose dispatch works differently. The count is in the code comment so the next person to widen this knows what they will meet. Three tests needed updating, each checked against MRI 4.0.7 rather than assumed: two pinned "#<Plain>" / "#<E>" for a PLAIN object, which MRI contradicts, and wave59's wrapper block already normalised addresses to 0xA, so it was built for this. That block is now byte-identical to MRI on 13 of its 14 lines; the fourteenth, Enumerator#to_s answering MRI's *inspect* form, is a separate divergence named in the test rather than folded into the expectation. The full suite is green: 0 failures. Closes #756. Closes the kind-A half of issue 759. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes issue 756. Closes the kind-A half of issue 759.
Two issues that meet on one line of output
756 —
Kernel#to_sis MRI'srb_any_to_s, which always prints theaddress.
Object.new.to_sis#<Object:0x…>, not#<Object>. rbgo printed theshort form, so
#to_sand#inspectdisagreed with each other inside rbgowhile
#inspectagreed with MRI.759 (kind A) —
Thread::Mutexand three siblings answered their barename. In MRI the class has one name, the qualified one, and top-level
Mutexisa second constant pointing at the same class:
Mutex.nameis"Thread::Mutex"however it was reached, and
Mutex.equal?(Thread::Mutex)is true in both.They are coupled:
RMutex.ToShardcoded"#<Thread::Mutex>", so onceKernel#to_sbuilds its string fromclassOf(self).namethe bare name becomesvisible as
#<Mutex:0x…>— a correct address with a wrong name. The firstversion of this branch did exactly that. Fixing either alone trades one
divergence for another.
⚠ The scope is narrower than MRI's, deliberately
The fix applies to a plain
*RObjectonly. Thirteen core classes reachKernel#to_shere and MRI gives all thirteen an address — but most are Go typeswhose own
ToS()is their#to_s: rbgo implements many objects'to_sasthe Go method rather than as a registered Ruby one, and they arrive at
Kernel#to_srelying on the delegation.A version that applied the identity form to everything reaching
Kernel#to_sbroke 78 tests, and every one of them was right to break:
#to_smust beCapistrano::Server"db1"— the hostnameCapistrano::Task"solo"— the task nameNet::SMTP::Response"250 2.0.0 queued"OpenIDConnect::ProviderMetadata#<… issuer=https://…>self"main"— which is what irb's prompt is built fromI had transposed a rule that is true of MRI — "reaching
rb_any_to_smeansthe receiver has no useful representation" — into an engine whose dispatch works
differently. My seven targeted probes were all green; only the full suite said
otherwise. The count is in the code comment so the next person to widen this
knows what they will meet.
The three tests that needed updating, each checked against MRI
builtin_subclass_test.goandphase1_test.gopinned"#<Plain>"and"#<E>"for a plain object. MRI 4.0.7 answers"#<Plain:0xA>"and#<E:0xA>, so those were green only while rbgo omitted the address.wave59_puts_to_s_test.go's wrapper block already normalised addresses to0xA— it was built for this. That block is now byte-identical to MRI on 13of its 14 lines.
The fourteenth is worth naming rather than folding in: rbgo's
Enumerator#to_sanswers MRI's inspect form,
#<Enumerator: [1, 2]:each>, where MRI's#to_sinherits Kernel's and answers#<Enumerator:0x…>. A separatedivergence, recorded in the test.
Measured
Reach established by census, not assumption: of 31 core classes asked
instance_method(:to_s).owner, thirteen answerKernelin rbgo and MRIanswers
Kernelfor the same thirteen. Everything else — including a subclassof
StringorArray— defines or inherits its own, and a control case assertseach of those is untouched.
Full suite: 0 failures.
🤖 Generated with Claude Code