doc: say what a build converting case by ASCII stops refusing - #7231
Conversation
`MRB_UTF8_STRING` promises that a string holding bytes that spell no
character is refused with `ArgumentError`. `MRB_USE_ASCII_CASE` is
written up as narrowing which characters convert, and nothing beside it
says the refusal narrows away with them, so a reader carries the promise
across.
It does not hold. The refusal is raised inside the walk over characters,
and the option compiles that walk out, so every method falls to its own
ASCII loop and the loop asks nothing about what the bytes spell:
```ruby
"abc\x80".downcase #=> "abc\x80"
"abc\x80".casecmp?("ABC\x80") #=> true
```
where a build with the Unicode tables answers `ArgumentError: input
string invalid` to both. That is the wanted behaviour: a build writing
nothing over those bytes has no wrong answer left to refuse, and reading
them through would buy only the exception. Both readings are already
pinned, in `test/t/string.rb` and `mrbgems/mruby-string-ext/test/string.rb`.
What was missing is the sentence. Say in the `MRB_USE_ASCII_CASE` section
that the refusal belongs to the walk being narrowed away, name it in the
`MRB_UTF8_STRING` bullet that sends the reader there, and give
`doc/limitations.md` the same qualification.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
Included review availability: Your plan includes up to 8 reviews per rolling hour; 2 remain after this review. 📝 WalkthroughWalkthroughThe documentation clarifies ChangesEncoding documentation
Estimated code review effort: 1 (Trivial) | ~2 minutes Merge Risk: ⚪ Minimal · up to This documentation-only change clarifies existing behavior without changing code or build outputs; no actionable merge-blocking risk remains after normal checks and review. Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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 |
doc/guides/mrbconf.md, underMRB_UTF8_STRING:and, two bullets down, what the option beside it takes away:
The
MRB_USE_ASCII_CASEsection says the same at greater length: it narrows whichcharacters convert, and names the case table and the regexp
iflag as what goes withthem. Neither place says the refusal goes too, so a reader carries the promise across.
What happens
It goes too. The refusal is raised inside the walk over characters,
src/string.c:2197,and the whole walk sits inside
#if defined(MRB_UTF8_STRING) && !defined(MRB_USE_ASCII_CASE),src/string.c:2080-2251. Compiled out, every method falls to its own ASCII loop, andthat loop asks nothing about what the bytes spell.
"abc\x80", on three of thebuild_config/ci/gcc-clang.rbbuilds:bintestascii-casebyte-stringdowncaseArgumentError"abc\x80""abc\x80"upcaseArgumentError"ABC\x80""ABC\x80"capitalizeArgumentError"Abc\x80""Abc\x80"swapcaseArgumentError"ABC\x80""ABC\x80"casecmp?("ABC\x80")ArgumentErrortruetrueEvery
ArgumentErrorabove carries the messageinput string invalid.Why this changes the documents and not the code
The refusal is there because answering as though a stray byte were the character it
starts with hands back a string nobody asked for. A build that converts nothing above
ASCII writes nothing over those bytes, so there is no wrong answer left to refuse, and
reading the string through to find them would buy only the exception. The
ascii-casecolumn above is also the
byte-stringcolumn, which is the shape the last bullet of thesection already promises: a build reading its strings as bytes converts ASCII alone
whatever the option says.
Both readings are pinned already:
test/t/string.rb:452asks for theArgumentErrorfrom#downcase,#upcase,#capitalizeand#downcase!, gatedif UNICODECASE.test/t/string.rb:498asks the same bytes back untouched from#downcaseand#upcase, gatedunless UNICODECASE.mrbgems/mruby-string-ext/test/string.rb:360-362asks for it from#casecmp?and#swapcase, gatedskip unless UNICODECASE, and:376asks#casecmp?forfalseinstead, gated
skip if UNICODECASE.So what is missing is the sentence.
Fix
Three sentences, no code.
MRB_USE_ASCII_CASEsection gains a bullet: bytes that spell no character arehanded back as they stand rather than refused, the refusal belonging to the walk the
option narrows away.
MRB_UTF8_STRINGbullet that sends the reader to that option names the refusalas part of what it takes, so the promise two bullets above is not carried across.
doc/limitations.md, which said only that the option "narrows that half back withoutgiving up the indexing", gains the same qualification.
Verification
No build output changes: the diff is two Markdown files. The table above was measured on
this branch, and
rake -m testonbuild_config/ci/gcc-clang.rbreportsKO 0andCrash 0in all five builds, unchanged from03daa666.Environment
Details
The lines that actually compiled
src/string.cin the three builds the table reads,with
-MMD -c,-Iand-odropped:🤖 Generated with Claude Code
https://claude.ai/code/session_01F57Qh8PB4NJRGZPbg9QvHU
Summary by CodeRabbit
ArgumentError.