docs(LibConvert): the toX convention marks cost, not consumption - #24
Conversation
The library NatSpec claimed that "toX" is adopted from Rust "to imply the additional costs and consumption of the source". The second half misstates the convention it cites. In Rust `to_` takes `&self` and marks an expensive conversion; `into_` takes `self` and is the marker that consumes the source. Under the convention as actually stated in Rust, `unsafeTo16BitBytes` is the correctly named function: it reads its source and allocates a new target. `unsafeToBytes` is the one that consumes, and it already documents that on itself. So the convention text moves. It now marks cost only, and states that consumption and the meaning of the `unsafe` prefix are per-function properties that do not generalise across the library. `unsafeTo16BitBytes` gains an explicit non-consumption note that names the contrast with `unsafeToBytes`, closing the dangerous direction of the inference. The reference implementation test carried the same wrong inference in a comment, asserting that `us` "can no longer be used" after the 16 bit pack. Corrected. The behaviour itself is already pinned by testUnsafeTo16BitBytesLeavesTheSourceIntact and testUnsafeToBytesAliasesTheSourceAndRewritesItsLengthPrefix. Closes #22 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review. WalkthroughThe change clarifies that ChangesLibConvert documentation clarification
Estimated code review effort: 1 (Trivial) | ~5 minutes Merge Risk: ⚪ Minimal · up to This documentation-only change does not alter runtime behavior, and no actionable merge-blocking risk remains after normal checks and review. 🚥 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 |
Closes #22.
Which side moves, and why
The issue frames this as a mismatch between the library NatSpec and one of
its two functions, and offers (a) note the non-consumption, (b) soften the
library sentence, or (c) close as by design. Before picking, it is worth
checking the sentence against the authority it names, because that changes
which function is the odd one out.
The library NatSpec says:
The Rust convention (API guidelines C-CONV) splits exactly this way:
as_&selfto_&selfinto_selfto_marks the cost.into_is the marker for consuming the source. So thefirst half of the sentence is right and the second half is not — it attributes
into_'s meaning toto_.That inverts the issue's implicit reading. Measured against the convention as
it actually exists,
unsafeTo16BitBytesis the correctly named function:it reads its source and allocates a new target, which is precisely
to_.unsafeToBytesis the one whose behaviour isinto_while its name saysto_— and it is already the one that documents its consumption in full onitself.
Decision: the convention text moves. The names and the behaviour stay.
Why not the behaviour
Making
unsafeTo16BitBytesconsume its source would be a silent runtimebreak at live call sites, which is the worst failure mode available here. The
in-org call sites pass an aliased
uint256[]view of a function-pointer arraythat is still live in the caller's scope, e.g.
rain.pythsrc/abstract/PythSubParser.sol:pointersandfsare the same buffer. A consuming implementation wouldcorrupt
fs. There is also nothing to gain: the result is half the size ofthe source, so "consuming" would mean overwriting a still-needed input for no
saving.
Why not the name
Weighed explicitly rather than assumed away, in both directions.
Renaming
unsafeTo16BitBytes. This is a published soldeer package(
rain-lib-typecast, autopublished on every push tomain), so a rename is acompile-time break for every consumer with no deprecation path. It is also
wide: a code search across the org finds 21 call sites in 8 repos —
rainlang,raindex,rain.pyth,rain.merkle,rain.flare,rain.erc4626.words. And it is the wrong direction anyway, since under thereal convention this function's name is already correct.
Renaming
unsafeToBytestounsafeIntoBytes. This one is genuinelycheap — the same search finds zero call sites outside this repo — so cost is
not the argument against it. Two things are:
toX... impliesconsumption" would still be false about Rust after the rename, and would
still have to be corrected. The text has to move either way; once it has,
the rename buys nothing the corrected text has not already delivered.
available, not proof of zero consumers, and it would put a Rust
into_idiom on exactly one function in the entire org — trading a documented
mismatch for an undocumented novelty.
What changed
Library NatSpec.
toXnow marks cost only, and says why:into_isRust's consuming marker and this library has no equivalent. It then states
that consumption and the referent of the
unsafeprefix are per-functionproperties, stated on the function, that do not generalise across the
library. This is option (b), and the added sentence about
unsafeclosesthe specific hazard the issue calls out — a reader inferring from
unsafeTo16BitBytesthatunsafein this library means truncation only,and carrying that to
unsafeToBytes.unsafeTo16BitBytesNatSpec. Option (a): explicit non-consumption,naming the contrast with
unsafeToBytesso the reader is pushed toward thedangerous function rather than away from it.
testUnsafeTo16BitBytesReferenceImplementationcomment. The suiteitself already carried the wrong inference:
That is true of
unsafeToBytesand false ofunsafeTo16BitBytes— it isthe issue's failure mode having already happened, in this repo. Corrected.
The identical comment on the
unsafeToBytestest is correct and is leftalone.
unsafeToBytesitself is untouched: its NatSpec already spells out theconsumption, which is the half the issue agrees was never wrong.
QA
directions of the property are already pinned on
mainbytestUnsafeTo16BitBytesLeavesTheSourceIntact(non-consumption) andtestUnsafeToBytesAliasesTheSourceAndRewritesItsLengthPrefix(consumption),merged in test(LibConvert): pin aliasing, source lifetime and the write bounds #19, and the issue names those two as its verified repro. This diff
changes no executable line, so there is no behaviour a new test could
discriminate and the instruction was explicitly not to duplicate them.
executable line changes, so
mutation-probehas nothing to mutate and thereis no
mutants.tomlscope to declare. Verification is the existing suitecontinuing to pass unchanged under rainix-sol.
as_/to_/into_convention that thelibrary NatSpec itself cites as its source, which is external to this
codebase; plus the issue's own oracle quote of the library NatSpec sentence.
Every behavioural claim in the new text (
unsafeTo16BitBytesallocates andonly reads;
unsafeToBytesaliases and rewrites the length prefix) is onethe two tests above already assert, not a restatement of the implementation.
unsafeTo16BitBytes, (b) soften the library-level sentence, (c) close as bydesign; covered (a) and (b), with (c) rejected and the reason given in "Which
side moves, and why". The two further options the issue does not list —
moving the name and moving the behaviour — are weighed and rejected in their
own sections above.
Note for the reviewer
unsafeToBytesuses a named return (returns (bytes memory bs)), which theno-named-returns convention disallows. Left alone deliberately: it is a code
change unrelated to #22, it would churn the gas snapshot, and this PR is
otherwise comment-only. Worth its own issue.
🤖 Generated with Claude Code
Summary by CodeRabbit
unsafebehavior.unsafeTo16BitBytespreserves the source array, whileunsafeToBytesmay reuse and mutate its source buffer.unsafeTo16BitBytesdoes not alter the source array.