1
- #![ allow(
2
- // False positive
3
- clippy:: match_same_arms
4
- ) ]
5
-
6
1
use super :: ARITHMETIC_SIDE_EFFECTS ;
7
2
use clippy_utils:: { consts:: constant_simple, diagnostics:: span_lint} ;
8
3
use rustc_ast as ast;
@@ -14,12 +9,12 @@ use rustc_session::impl_lint_pass;
14
9
use rustc_span:: source_map:: { Span , Spanned } ;
15
10
16
11
const HARD_CODED_ALLOWED : & [ & str ] = & [
12
+ "&str" ,
17
13
"f32" ,
18
14
"f64" ,
19
15
"std::num::Saturating" ,
20
16
"std::num::Wrapping" ,
21
17
"std::string::String" ,
22
- "&str" ,
23
18
] ;
24
19
25
20
#[ derive( Debug ) ]
@@ -50,10 +45,10 @@ impl ArithmeticSideEffects {
50
45
let ast:: LitKind :: Int ( value, _) = lit. node
51
46
{
52
47
match ( & op. node , value) {
53
- ( hir:: BinOpKind :: Add | hir:: BinOpKind :: Sub , 0 ) |
54
- ( hir:: BinOpKind :: Mul , 0 | 1 ) => true ,
55
48
( hir:: BinOpKind :: Div | hir:: BinOpKind :: Rem , 0 ) => false ,
56
- ( hir:: BinOpKind :: Div | hir:: BinOpKind :: Rem , _) => true ,
49
+ ( hir:: BinOpKind :: Add | hir:: BinOpKind :: Sub , 0 )
50
+ | ( hir:: BinOpKind :: Div | hir:: BinOpKind :: Rem , _)
51
+ | ( hir:: BinOpKind :: Mul , 0 | 1 ) => true ,
57
52
_ => false ,
58
53
}
59
54
} else {
@@ -79,16 +74,13 @@ impl ArithmeticSideEffects {
79
74
self . expr_span = Some ( expr. span ) ;
80
75
}
81
76
82
- /// * If `expr` is a literal integer like `1` or `i32::MAX`, returns itself.
83
- /// * Is `expr` is a literal integer reference like `&199`, returns the literal integer without
84
- /// references.
85
- /// * If `expr` is anything else, returns `None`.
86
- fn literal_integer < ' expr , ' tcx > ( expr : & ' expr hir:: Expr < ' tcx > ) -> Option < & ' expr hir:: Expr < ' tcx > > {
77
+ /// If `expr` does not match any variant of `LiteralIntegerTy`, returns `None`.
78
+ fn literal_integer < ' expr , ' tcx > ( expr : & ' expr hir:: Expr < ' tcx > ) -> Option < LiteralIntegerTy < ' expr , ' tcx > > {
87
79
if matches ! ( expr. kind, hir:: ExprKind :: Lit ( _) ) {
88
- return Some ( expr) ;
80
+ return Some ( LiteralIntegerTy :: Value ( expr) ) ;
89
81
}
90
82
if let hir:: ExprKind :: AddrOf ( .., inn) = expr. kind && let hir:: ExprKind :: Lit ( _) = inn. kind {
91
- return Some ( inn)
83
+ return Some ( LiteralIntegerTy :: Ref ( inn) ) ;
92
84
}
93
85
None
94
86
}
@@ -126,10 +118,9 @@ impl ArithmeticSideEffects {
126
118
}
127
119
let has_valid_op = if Self :: is_integral ( lhs_ty) && Self :: is_integral ( rhs_ty) {
128
120
match ( Self :: literal_integer ( lhs) , Self :: literal_integer ( rhs) ) {
129
- ( None , None ) => false ,
130
- ( None , Some ( local_expr) ) => Self :: has_valid_op ( op, local_expr) ,
131
- ( Some ( local_expr) , None ) => Self :: has_valid_op ( op, local_expr) ,
132
- ( Some ( _) , Some ( _) ) => true ,
121
+ ( None , Some ( lit_int_ty) ) | ( Some ( lit_int_ty) , None ) => Self :: has_valid_op ( op, lit_int_ty. into ( ) ) ,
122
+ ( Some ( LiteralIntegerTy :: Value ( _) ) , Some ( LiteralIntegerTy :: Value ( _) ) ) => true ,
123
+ ( None , None ) | ( Some ( _) , Some ( _) ) => false ,
133
124
}
134
125
} else {
135
126
false
@@ -186,3 +177,22 @@ impl<'tcx> LateLintPass<'tcx> for ArithmeticSideEffects {
186
177
}
187
178
}
188
179
}
180
+
181
+ /// Tells if an expression is a integer declared by value or by reference.
182
+ ///
183
+ /// If `LiteralIntegerTy::Ref`, then the contained value will be `hir::ExprKind::Lit` rather
184
+ /// than `hirExprKind::Addr`.
185
+ enum LiteralIntegerTy < ' expr , ' tcx > {
186
+ /// For example, `&199`
187
+ Ref ( & ' expr hir:: Expr < ' tcx > ) ,
188
+ /// For example, `1` or `i32::MAX`
189
+ Value ( & ' expr hir:: Expr < ' tcx > ) ,
190
+ }
191
+
192
+ impl < ' expr , ' tcx > From < LiteralIntegerTy < ' expr , ' tcx > > for & ' expr hir:: Expr < ' tcx > {
193
+ fn from ( from : LiteralIntegerTy < ' expr , ' tcx > ) -> Self {
194
+ match from {
195
+ LiteralIntegerTy :: Ref ( elem) | LiteralIntegerTy :: Value ( elem) => elem,
196
+ }
197
+ }
198
+ }
0 commit comments