Repository navigation
The separator globals accept a String subclass, as MRI's T_STRING test does - #897
Merged
Merged
Conversation
…t does Closes #884. `language/predefined_spec.rb` goes 143 → 145, errors 6 → 4. ## How this was found By counting, not by reading the backlog. #799's table credits #886 with 4 examples of `language/predefined_spec.rb`; running the file against current main says otherwise: RBGO_RESULT pass=143 fail=16 error=6 RBGO_DETAIL error TypeError Predefined global $/ | makes a new frozen String from the assigned String value of $/ must be String RBGO_DETAIL error TypeError Predefined global $-0 | makes a new frozen String from the assigned String value of $-0 must be String #886 closed TWO of the four, not four, and said so at the time — the String subclass example was named in its body as a known limitation and filed as #884. The tally in the issue kept the old number, and a pass count cannot tell the difference. ## The cause is one assertion, and it was in five places if _, ok := v.(*object.String); !ok { raise("TypeError", ...) } An exact-type assertion. MRI's are RB_TYPE_P(val, T_STRING) in rb_str_setter and rb_check_string_type in rb_fs_check, and both are TRUE for a subclass. rbgo represents an instance of `Class.new(String)` as an RObject wrapping a String, so the assertion missed every one of them. stringTyped is that test. ## The five globals do not do the same thing afterwards Measured on MRI 4.0.7, assigning the same `Class.new(String).new("abc")` with an @ivar: | global | setter | result | |---|---|---| | `$/`, `$-0` | deprecated_rs_setter | a frozen BARE String — class String, no ivar | | `$,`, `$\` | rb_str_setter | the object as handed over, unfrozen | | `$;` | rb_fs_setter | the object as handed over, unfrozen | A fix that froze and copied everywhere would pass the two spec examples and silently rewrite the other three. The test table asserts each separately. ## $; was wrong differently, and worse It did not refuse the subclass — it fell through to #to_str, which a String subclass answers. The assignment SUCCEEDED and quietly replaced the object with a plain String. The others at least raised. ## frozenBareString's comment had outlived its reason It said only the ivar half of BARE_STRING_P was tested, because a subclass "never reaches this function at all". That was true while checkStrGvar rejected it. Now it does reach it, and without the class test the subclass instance would be returned AS IS — ivar and all. The function takes the original value as well as the String inside it, and tests both halves. ## Measured rubydiff against MRI 4.0.7 on all five globals plus the non-String refusals: AGREE. specdelta, provenanced, over language, core/string, core/io and core/kernel: 442 files, control 9666, treatment 9668, +2, 1 file moved, 0 regressed. 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.
The separator globals accept a String subclass, as MRI's T_STRING test does
Closes #884.
language/predefined_spec.rbgoes 143 → 145, errors 6 → 4.How this was found
By counting, not by reading the backlog. #799's table credits #886 with 4
examples of
language/predefined_spec.rb; running the file against currentmain says otherwise:
#886 closed TWO of the four, not four, and said so at the time — the String
subclass example was named in its body as a known limitation and filed as #884.
The tally in the issue kept the old number, and a pass count cannot tell the
difference.
The cause is one assertion, and it was in five places
An exact-type assertion. MRI's are RB_TYPE_P(val, T_STRING) in rb_str_setter
and rb_check_string_type in rb_fs_check, and both are TRUE for a subclass. rbgo
represents an instance of
Class.new(String)as an RObject wrapping a String,so the assertion missed every one of them. stringTyped is that test.
The five globals do not do the same thing afterwards
Measured on MRI 4.0.7, assigning the same
Class.new(String).new("abc")withan @ivar:
$/,$-0$,,$\$;A fix that froze and copied everywhere would pass the two spec examples and
silently rewrite the other three. The test table asserts each separately.
$; was wrong differently, and worse
It did not refuse the subclass — it fell through to #to_str, which a String
subclass answers. The assignment SUCCEEDED and quietly replaced the object with
a plain String. The others at least raised.
frozenBareString's comment had outlived its reason
It said only the ivar half of BARE_STRING_P was tested, because a subclass
"never reaches this function at all". That was true while checkStrGvar rejected
it. Now it does reach it, and without the class test the subclass instance
would be returned AS IS — ivar and all. The function takes the original value
as well as the String inside it, and tests both halves.
Measured
rubydiff against MRI 4.0.7 on all five globals plus the non-String refusals:
AGREE.
specdelta, provenanced, over language, core/string, core/io and core/kernel:
442 files, control 9666, treatment 9668, +2, 1 file moved, 0 regressed.
Co-Authored-By: Claude Opus 5 noreply@anthropic.com