-
Notifications
You must be signed in to change notification settings - Fork 12.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Optimise and bug-fix to_digit
#132428
Comments
...PRs welcome? it's usually easiest, when you have a fix on-hand, to just have a fix to review. |
That said, the documentation here: # Errors
Returns None if the char does not refer to a digit in the given radix.
# Panics
Panics if given a radix larger than 36. suggests the correct results should probably be either Option A: assert_eq!('0'.to_digit(0), None);
assert_eq!('1'.to_digit(1), Some(1)); // https://en.wikipedia.org/wiki/Unary_numeral_system or Option B: assert_eq!('0'.to_digit(0), None);
assert_eq!('0'.to_digit(1), None); |
It conformed to panicking, when it said it would. However the radix bounds check is there to prevent wrong radices. Unary is a totally different scheme, which is not implemented by this function. All numbers Rust deals with in any base are in positional notation. There If Rust wants to special case tiny radices, it must actively do so and explain what’s going on! Otherwise they must be forbidden just like too big ones are. The current state of things is not consistent. Night’s sleep has inspired me to offer a branchless variant. Not benchmarked, hoping that compiler specialists will know whether this is even more optimised. My understanding was that a PR can’t just introduce a new function to the public API. And whether to switch all those callers to it, surely needs somebody’s prior approval. I have never compiled rustc, and possibly don’t have enough disk-space. So if I were to issue a PR it would only be syntax checked. |
If you wish to propose |
It's worth noting that also, your "Soundness" header should instead be called "Correctness". soundness in rust means whether some unsafe code allows safe code to cause UB (which can happen if a function or trait is not marked |
It's the opposite of a special case. Panicking would be a special case. |
According to the definition you have provided, then:
As we can see, when only 1 symbol is allowed, we can still have 0. So you have successfully persuaded me there is not a problem. Ask a silly question, get a silly answer. Rust is memory-safe, not foolproof. |
Unary works differently from binary and above. It only has the digit 1. A unary with digit 0 can’t work: it couldn’t count anything. Nor could a nullary system with what? No digits at all? Also a rubbish system. There’s a good reason |
As there's an ACP open, let's keep discussion there. |
I tried this code, with absurd radices:
I expected to see this happen: panic
Instead, this happened: None Some(0)
Solution
This function was quite convoluted, which lead to unnecessary operations. Radix bounds checking was forgotten at the lower end.
OTOH radix bounds checking is often not necessary to repeat for every single digit, so I propose 2 variants, the consequence of which, see at the bottom:
I have checked all callers of
to_digit
, to see where it is already safe, or can be made safe, to switch toto_digit_unchecked
. Maybe each time a comment should be added to the place that guarantees a valid radix:bounds already checked outside of loop, so can switch:
literal base in a variable, only valid values, so can switch:
in a loop, should add bounds check and switch:
literal radices, where the compiler can hopefully eliminate the
assert
s, so no need, but might do it to save compile time:The text was updated successfully, but these errors were encountered: