@@ -18,7 +18,7 @@ use crate::utils::sugg::Sugg;
1818use crate :: utils:: {
1919 get_item_name, get_parent_expr, higher, implements_trait, in_constant, is_integer_const, iter_input_pats,
2020 last_path_segment, match_qpath, match_trait_method, paths, snippet, snippet_opt, span_lint, span_lint_and_sugg,
21- span_lint_and_then, span_lint_hir_and_then, SpanlessEq ,
21+ span_lint_and_then, span_lint_hir_and_then, SpanlessEq , unsext ,
2222} ;
2323
2424declare_clippy_lint ! {
@@ -139,23 +139,26 @@ declare_clippy_lint! {
139139}
140140
141141declare_clippy_lint ! {
142- /// **What it does:** Checks for getting the remainder of a division by one.
142+ /// **What it does:** Checks for getting the remainder of a division by one or minus
143+ /// one.
143144 ///
144- /// **Why is this bad?** The result can only ever be zero. No one will write
145- /// such code deliberately, unless trying to win an Underhanded Rust
146- /// Contest. Even for that contest, it's probably a bad idea. Use something more
147- /// underhanded.
145+ /// **Why is this bad?** The result for a divisor of one can only ever be zero; for
146+ /// minus one it can cause panic/overflow (if the left operand is the minimal value of
147+ /// the respective integer type) or results in zero. No one will write such code
148+ /// deliberately, unless trying to win an Underhanded Rust Contest. Even for that
149+ /// contest, it's probably a bad idea. Use something more underhanded.
148150 ///
149151 /// **Known problems:** None.
150152 ///
151153 /// **Example:**
152154 /// ```rust
153155 /// # let x = 1;
154156 /// let a = x % 1;
157+ /// let a = x % -1;
155158 /// ```
156159 pub MODULO_ONE ,
157160 correctness,
158- "taking a number modulo 1, which always returns 0"
161+ "taking a number modulo +/- 1, which can either panic/overflow or always returns 0"
159162}
160163
161164declare_clippy_lint ! {
@@ -429,8 +432,17 @@ impl<'tcx> LateLintPass<'tcx> for MiscLints {
429432 }
430433 diag. note ( "`f32::EPSILON` and `f64::EPSILON` are available for the `error_margin`" ) ;
431434 } ) ;
432- } else if op == BinOpKind :: Rem && is_integer_const ( cx, right, 1 ) {
433- span_lint ( cx, MODULO_ONE , expr. span , "any number modulo 1 will be 0" ) ;
435+ } else if op == BinOpKind :: Rem {
436+ if is_integer_const ( cx, right, 1 ) {
437+ span_lint ( cx, MODULO_ONE , expr. span , "any number modulo 1 will be 0" ) ;
438+ }
439+
440+ if let ty:: Int ( ity) = cx. typeck_results ( ) . expr_ty ( right) . kind ( ) {
441+ if is_integer_const ( cx, right, unsext ( cx. tcx , -1 , * ity) ) {
442+ span_lint ( cx, MODULO_ONE , expr. span ,
443+ "any number modulo -1 will panic/overflow or result in 0" ) ;
444+ }
445+ } ;
434446 }
435447 } ,
436448 _ => { } ,
0 commit comments