-
Notifications
You must be signed in to change notification settings - Fork 16
[Guideline] Add do not divide by 0 #132
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
base: main
Are you sure you want to change the base?
Conversation
✅ Deploy Preview for scrc-coding-guidelines ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
Hi @vapdrs! I have already sent you a message in Zulip, but here seems like a better place to do so. I come to add a couple of things to this guideline :)
There are other such operations for division, such as And for other arithmetic operations, there are quite a few functions one can use to avoid Undefined Behavior: https://doc.rust-lang.org/std/?search=checked
This combines rather well with Option, as in Option<NonZero>, since the compiler can do some memory layout optimization due to the fact that the value being enclosed by NonZero has one bit-pattern that is known to not be possible (the 000...000 pattern) I will review the PR shortly :3 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for opening this up @vapdrs! Could you check the comments I left?
As stated there is no compliant way to do this, so no example should be present.
While the guideline does not strictly apply to this example, it is a good suggestion for what to do instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for pulling this together @vapdrs! I left a few suggestions based on how conf.py
works together with Sphinx Needs as well as a way to use our coding guidelines extension. Could you take a look?
@@ -81,3 +81,44 @@ Expressions | |||
} | |||
|
|||
fn with_base(_: &Base) { ... } | |||
|
|||
.. guideline:: Do not divide by 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Asking a bit of a practical question to folks. Does the combination of:
mandatory
undecidable
put too great of a burden on reviewers / auditors or is this "just the way it is and should be" given the nature of writing safety-critical code?
Tagging @AlexCeleste and @rcseacord for their thoughts as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a bit of rationale for why I chose that combination. I used "mandatory" as a stand in for "very important" as a reason it goes above and beyond "required".
I would not want to mandate that no safety-critical programmer could never used unchecked arithmetic, the decidable subset version of this rule, but I do want to mandate that they do not take an action (divide by zero) that would lead to a panic.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, "do not divide by zero" is undecidable in the sense that statically knowing if the b
in a / b
is 0
is undecidable.
However, the guideline is not impossible to comply with since the user themselves can check (if b != 0
etc) but also because there are APIs that we can use for this, like the NonZero<T>
struct and the checked_div
and checked_rem
functions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is true, there are more clever ways to enforce this in Rust.
I would be fine mandating that any division must use checked functions, or have a NonZero<T>
divisor (which elides any performance penalty from checking). This would then kick the can down the road, where as now your problem is don't use NonZero<T>::new_unchecked
and cause UB.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
However, the guideline is not impossible to comply with since the user themselves can check
Definitely, I agree. Perhaps this is an instance of where we need to make use of the Exceptions section to list the sorts of suggestions you made. What do you two think?
like the
NonZero<T>
TIL about NonZero<T>
. Super cool.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The rule already shouldn't apply to this, it is specified as applying to:
unsigned integer or two’s complement division
which is the "built-in" rules of the ArithmeticExpression. Using NonZero<T>
goes through core::ops::Div::div
which is already outside the scope of this guideline. I will clarify that to make it more explicit though.
Co-authored-by: Pete LeVasseur <[email protected]>
Co-authored-by: Pete LeVasseur <[email protected]>
Closes #131