You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[Guideline] Add safe division guideline to avoid dividing by zero (rustfoundation#136)
* Add checked arithmetic guidelines
* Add more typo ignore patterns
These correspond to the unique ID's for each section.
* Remove floating point types from these guidelines
* Ensure example match
* Add statement to rationale justifying the Advisory
* Correct typos
* Update comment for directive typo check
Co-authored-by: Pete LeVasseur <[email protected]>
* Expound upon `unchecked_` functions
Additionally the code block formatting was updating, and a link was added.
Co-authored-by: Pete LeVasseur <[email protected]>
* Fix grammar of wrap around
* Change sphinx link syntax
* Add link to FLS ArithmeticExpression
* Correct description of unchecked function
As pointed out, they result in UB not necessarily panics
* Remove other mention of panics
* Narrow guideline to just integer division.
* Remove guideline on unchecked methods
As those are marked unsafe anyway
* Add remainder expression example
* Downgrade this to an advisory guideline
It could get annoying in existing codebases
* Fix missing commas for syntax
* Add subset tag
* Word choice as suggested by Felix
* Formatting
* Apply suggestions from code review
Spelling and word choice from review
Co-authored-by: Félix Fischer <[email protected]>
* Example clarification from code review
Co-authored-by: Félix Fischer <[email protected]>
* Note clarity and rewording
Co-authored-by: Félix Fischer <[email protected]>
---------
Co-authored-by: Pete LeVasseur <[email protected]>
Co-authored-by: Félix Fischer <[email protected]>
Copy file name to clipboardExpand all lines: src/coding-guidelines/expressions.rst
+64Lines changed: 64 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -82,6 +82,70 @@ Expressions
82
82
83
83
fn with_base(_: &Base) { ... }
84
84
85
+
.. guideline:: Do not use integer type as divisor
86
+
:id: gui_7y0GAMmtMhch
87
+
:category: advisory
88
+
:status: draft
89
+
:release: latest
90
+
:fls: fls_Q9dhNiICGIfr
91
+
:decidability: decidable
92
+
:scope: module
93
+
:tags: numerics, subset
94
+
95
+
This guideline applies when a `DivisionExpression
96
+
<https://rust-lang.github.io/fls/expressions.html#syntax_divisionexpression>`_ or `RemainderExpression
97
+
<https://rust-lang.github.io/fls/expressions.html#syntax_remainderexpression>`_ is used with a RightOperand of
98
+
`integer type <https://rust-lang.github.io/fls/types-and-traits.html#integer-types>`_.
99
+
100
+
.. rationale::
101
+
:id: rat_vLFlPWSCHRje
102
+
:status: draft
103
+
104
+
The built-in semantics for these expressions can result in panics when division by zero occurs. It is
105
+
recommended to either:
106
+
107
+
* Use checked division functions, which ensure the programmer handles the case when the divisor is zero, or
108
+
* To create divisors using :std:`std::num::NonZero`, which then allows the programmer to perform those
109
+
operations knowing that their divisor is not zero.
110
+
111
+
**Note:** since the compiler can assume the value of a :std:`std::num::NonZero`
112
+
variable to not be zero, checks for zero when dividing by it can be elided in the
113
+
final binary, increasing overall performance beyond what normal division can have.
114
+
115
+
.. non_compliant_example::
116
+
:id: non_compl_ex_0XeioBrgfh5z
117
+
:status: draft
118
+
119
+
When either the division or remainder are performed, the right operand is evaluated to zero and the
120
+
program panics.
121
+
122
+
.. code-block:: rust
123
+
124
+
let x = 0;
125
+
let y = 5 / x; // This line will panic.
126
+
let z = 5 % x; // This line would also panic.
127
+
128
+
.. compliant_example::
129
+
:id: compl_ex_k1CD6xoZxhXb
130
+
:status: draft
131
+
132
+
There is no compliant way to divide with an integer type. Here, instead, the developer explicitly:
133
+
134
+
* Uses a checked division function, which ensures a zero divisor is handled separately, and
135
+
* Creates a divisor using :std:`std::num::NonZero`, which outsources the check for zero to the
136
+
construction of that struct. It's worth noting that such a divisor can be used multiple times after it's been created, whilst keeping the guarantee that such divisions will be safe.
137
+
138
+
.. code-block:: rust
139
+
140
+
let x = 0;
141
+
if let Some(divisor) = match NonZero::<u32>::new(x) {
0 commit comments