1
1
use crate :: consts:: { constant, Constant } ;
2
- use crate :: utils:: { sext, span_help_and_lint } ;
2
+ use crate :: utils:: { sext, span_note_and_lint } ;
3
3
use if_chain:: if_chain;
4
4
use rustc:: declare_lint_pass;
5
5
use rustc:: hir:: * ;
@@ -30,22 +30,23 @@ declare_clippy_lint! {
30
30
31
31
declare_lint_pass ! ( ModuloArithmetic => [ MODULO_ARITHMETIC ] ) ;
32
32
33
- fn is_negative ( operand : & Expr , cx : & LateContext < ' _ , ' _ > , expr : & Expr ) -> Option < bool > {
33
+ fn is_negative ( operand : & Expr , cx : & LateContext < ' _ , ' _ > , expr : & Expr ) -> Option < ( bool , Option < String > ) > {
34
34
match constant ( cx, cx. tables , operand) {
35
35
Some ( ( Constant :: Int ( v) , _) ) => match cx. tables . expr_ty ( expr) . kind {
36
36
ty:: Int ( ity) => {
37
- return Some ( sext ( cx. tcx , v, ity) < 0 ) ;
37
+ let value = sext ( cx. tcx , v, ity) ;
38
+ return Some ( ( value < 0 , Some ( value. to_string ( ) ) ) ) ;
38
39
} ,
39
40
ty:: Uint ( _) => {
40
- return Some ( false ) ;
41
+ return Some ( ( false , None ) ) ;
41
42
} ,
42
43
_ => { } ,
43
44
} ,
44
45
Some ( ( Constant :: F32 ( f) , _) ) => {
45
- return Some ( f < 0.0 ) ;
46
+ return Some ( ( f < 0.0 , Some ( format ! ( "{:.3}" , f ) ) ) ) ;
46
47
} ,
47
48
Some ( ( Constant :: F64 ( f) , _) ) => {
48
- return Some ( f < 0.0 ) ;
49
+ return Some ( ( f < 0.0 , Some ( format ! ( "{:.3}" , f ) ) ) ) ;
49
50
} ,
50
51
_ => { } ,
51
52
}
@@ -68,15 +69,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ModuloArithmetic {
68
69
if_chain ! {
69
70
if let Some ( lhs_negative) = lhs_negative;
70
71
if let Some ( rhs_negative) = rhs_negative;
71
- if lhs_negative ^ rhs_negative;
72
+ if lhs_negative. 0 ^ rhs_negative. 0 ;
72
73
then
73
74
{
74
- span_help_and_lint (
75
+ span_note_and_lint (
75
76
cx,
76
77
MODULO_ARITHMETIC ,
77
78
expr. span,
78
- "modulo arithemtic detected" ,
79
- "modulo operands have different signs, double check all modulo arithemtic results when interoperating with different languages" ,
79
+ & format!(
80
+ "you are using modulo operator on constants with different signs: `{} % {}`" , lhs_negative. 1 . unwrap( ) , rhs_negative. 1 . unwrap( )
81
+ ) ,
82
+ expr. span,
83
+ "double check for expected result especially when interoperating with different languages" ,
80
84
) ;
81
85
return ;
82
86
}
@@ -85,12 +89,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ModuloArithmetic {
85
89
// Operands are not consts, fallback to the 'might have different signs' lint
86
90
let lhs_type = cx. tables . expr_ty ( lhs) ;
87
91
if might_have_negative_value ( lhs_type) {
88
- span_help_and_lint (
92
+ span_note_and_lint (
89
93
cx,
90
94
MODULO_ARITHMETIC ,
91
95
expr. span ,
92
- "modulo arithemtic detected" ,
93
- "modulo operands might have different signs, double check all modulo arithemtic results when interoperating with different languages" ,
96
+ "you are using modulo operator on types that might have different signs" ,
97
+ expr. span ,
98
+ "double check for expected result especially when interoperating with different languages" ,
94
99
) ;
95
100
}
96
101
}
0 commit comments