1
1
use clippy_utils:: diagnostics:: span_lint_hir_and_then;
2
- use clippy_utils:: numeric_literal;
3
2
use clippy_utils:: source:: snippet_opt;
3
+ use clippy_utils:: { get_parent_node, numeric_literal} ;
4
4
use if_chain:: if_chain;
5
5
use rustc_ast:: ast:: { LitFloatType , LitIntType , LitKind } ;
6
6
use rustc_errors:: Applicability ;
7
7
use rustc_hir:: {
8
8
intravisit:: { walk_expr, walk_stmt, Visitor } ,
9
- Body , Expr , ExprKind , HirId , Lit , Stmt , StmtKind ,
9
+ Body , Expr , ExprKind , HirId , ItemKind , Lit , Node , Stmt , StmtKind ,
10
10
} ;
11
11
use rustc_lint:: { LateContext , LateLintPass , LintContext } ;
12
12
use rustc_middle:: {
@@ -55,22 +55,31 @@ declare_lint_pass!(DefaultNumericFallback => [DEFAULT_NUMERIC_FALLBACK]);
55
55
56
56
impl < ' tcx > LateLintPass < ' tcx > for DefaultNumericFallback {
57
57
fn check_body ( & mut self , cx : & LateContext < ' tcx > , body : & ' tcx Body < ' _ > ) {
58
- let mut visitor = NumericFallbackVisitor :: new ( cx) ;
58
+ let is_parent_const = if let Some ( Node :: Item ( item) ) = get_parent_node ( cx. tcx , body. id ( ) . hir_id ) {
59
+ matches ! ( item. kind, ItemKind :: Const ( ..) )
60
+ } else {
61
+ false
62
+ } ;
63
+ let mut visitor = NumericFallbackVisitor :: new ( cx, is_parent_const) ;
59
64
visitor. visit_body ( body) ;
60
65
}
61
66
}
62
67
63
68
struct NumericFallbackVisitor < ' a , ' tcx > {
64
69
/// Stack manages type bound of exprs. The top element holds current expr type.
65
- ty_bounds : Vec < TyBound < ' tcx > > ,
70
+ ty_bounds : Vec < ExplicitTyBound > ,
66
71
67
72
cx : & ' a LateContext < ' tcx > ,
68
73
}
69
74
70
75
impl < ' a , ' tcx > NumericFallbackVisitor < ' a , ' tcx > {
71
- fn new ( cx : & ' a LateContext < ' tcx > ) -> Self {
76
+ fn new ( cx : & ' a LateContext < ' tcx > , is_parent_const : bool ) -> Self {
72
77
Self {
73
- ty_bounds : vec ! [ TyBound :: Nothing ] ,
78
+ ty_bounds : vec ! [ if is_parent_const {
79
+ ExplicitTyBound ( true )
80
+ } else {
81
+ ExplicitTyBound ( false )
82
+ } ] ,
74
83
cx,
75
84
}
76
85
}
@@ -79,10 +88,9 @@ impl<'a, 'tcx> NumericFallbackVisitor<'a, 'tcx> {
79
88
fn check_lit ( & self , lit : & Lit , lit_ty : Ty < ' tcx > , emit_hir_id : HirId ) {
80
89
if_chain ! {
81
90
if !in_external_macro( self . cx. sess( ) , lit. span) ;
82
- if let Some ( ty_bound ) = self . ty_bounds. last( ) ;
91
+ if matches! ( self . ty_bounds. last( ) , Some ( ExplicitTyBound ( false ) ) ) ;
83
92
if matches!( lit. node,
84
93
LitKind :: Int ( _, LitIntType :: Unsuffixed ) | LitKind :: Float ( _, LitFloatType :: Unsuffixed ) ) ;
85
- if !ty_bound. is_numeric( ) ;
86
94
then {
87
95
let ( suffix, is_float) = match lit_ty. kind( ) {
88
96
ty:: Int ( IntTy :: I32 ) => ( "i32" , false ) ,
@@ -123,7 +131,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> {
123
131
if let Some ( fn_sig) = fn_sig_opt ( self . cx , func. hir_id ) {
124
132
for ( expr, bound) in iter:: zip ( * args, fn_sig. skip_binder ( ) . inputs ( ) ) {
125
133
// Push found arg type, then visit arg.
126
- self . ty_bounds . push ( TyBound :: Ty ( * bound) ) ;
134
+ self . ty_bounds . push ( ( * bound) . into ( ) ) ;
127
135
self . visit_expr ( expr) ;
128
136
self . ty_bounds . pop ( ) ;
129
137
}
@@ -135,7 +143,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> {
135
143
if let Some ( def_id) = self . cx . typeck_results ( ) . type_dependent_def_id ( expr. hir_id ) {
136
144
let fn_sig = self . cx . tcx . fn_sig ( def_id) . skip_binder ( ) ;
137
145
for ( expr, bound) in iter:: zip ( std:: iter:: once ( * receiver) . chain ( args. iter ( ) ) , fn_sig. inputs ( ) ) {
138
- self . ty_bounds . push ( TyBound :: Ty ( * bound) ) ;
146
+ self . ty_bounds . push ( ( * bound) . into ( ) ) ;
139
147
self . visit_expr ( expr) ;
140
148
self . ty_bounds . pop ( ) ;
141
149
}
@@ -169,7 +177,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> {
169
177
170
178
// Visit base with no bound.
171
179
if let Some ( base) = base {
172
- self . ty_bounds. push( TyBound :: Nothing ) ;
180
+ self . ty_bounds. push( ExplicitTyBound ( false ) ) ;
173
181
self . visit_expr( base) ;
174
182
self . ty_bounds. pop( ) ;
175
183
}
@@ -192,15 +200,10 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> {
192
200
193
201
fn visit_stmt ( & mut self , stmt : & ' tcx Stmt < ' _ > ) {
194
202
match stmt. kind {
195
- StmtKind :: Local ( local) => {
196
- if local. ty . is_some ( ) {
197
- self . ty_bounds . push ( TyBound :: Any ) ;
198
- } else {
199
- self . ty_bounds . push ( TyBound :: Nothing ) ;
200
- }
201
- } ,
203
+ // we cannot check the exact type since it's a hir::Ty which does not implement `is_numeric`
204
+ StmtKind :: Local ( local) => self . ty_bounds . push ( ExplicitTyBound ( local. ty . is_some ( ) ) ) ,
202
205
203
- _ => self . ty_bounds . push ( TyBound :: Nothing ) ,
206
+ _ => self . ty_bounds . push ( ExplicitTyBound ( false ) ) ,
204
207
}
205
208
206
209
walk_stmt ( self , stmt) ;
@@ -218,28 +221,18 @@ fn fn_sig_opt<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<PolyFnSig<'
218
221
}
219
222
}
220
223
224
+ /// Wrapper around a `bool` to make the meaning of the value clearer
221
225
#[ derive( Debug , Clone , Copy ) ]
222
- enum TyBound < ' tcx > {
223
- Any ,
224
- Ty ( Ty < ' tcx > ) ,
225
- Nothing ,
226
- }
226
+ struct ExplicitTyBound ( pub bool ) ;
227
227
228
- impl < ' tcx > TyBound < ' tcx > {
229
- fn is_numeric ( self ) -> bool {
230
- match self {
231
- TyBound :: Any => true ,
232
- TyBound :: Ty ( t) => t. is_numeric ( ) ,
233
- TyBound :: Nothing => false ,
234
- }
228
+ impl < ' tcx > From < Ty < ' tcx > > for ExplicitTyBound {
229
+ fn from ( v : Ty < ' tcx > ) -> Self {
230
+ Self ( v. is_numeric ( ) )
235
231
}
236
232
}
237
233
238
- impl < ' tcx > From < Option < Ty < ' tcx > > > for TyBound < ' tcx > {
234
+ impl < ' tcx > From < Option < Ty < ' tcx > > > for ExplicitTyBound {
239
235
fn from ( v : Option < Ty < ' tcx > > ) -> Self {
240
- match v {
241
- Some ( t) => TyBound :: Ty ( t) ,
242
- None => TyBound :: Nothing ,
243
- }
236
+ Self ( v. map_or ( false , Ty :: is_numeric) )
244
237
}
245
238
}
0 commit comments