1
1
use rustc_ast:: ast:: { LitFloatType , LitIntType , LitKind } ;
2
2
use rustc_hir:: {
3
3
intravisit:: { walk_expr, walk_stmt, NestedVisitorMap , Visitor } ,
4
- Body , Expr , ExprKind , Lit , Stmt , StmtKind ,
4
+ Body , Expr , ExprKind , HirId , Lit , Stmt , StmtKind ,
5
5
} ;
6
6
use rustc_lint:: { LateContext , LateLintPass } ;
7
7
use rustc_middle:: {
8
8
hir:: map:: Map ,
9
- ty:: { self , FloatTy , IntTy , Ty } ,
9
+ ty:: { self , FloatTy , IntTy , PolyFnSig , Ty } ,
10
10
} ;
11
11
use rustc_session:: { declare_lint_pass, declare_tool_lint} ;
12
12
@@ -64,15 +64,15 @@ struct NumericFallbackVisitor<'a, 'tcx> {
64
64
impl < ' a , ' tcx > NumericFallbackVisitor < ' a , ' tcx > {
65
65
fn new ( cx : & ' a LateContext < ' tcx > ) -> Self {
66
66
Self {
67
- ty_bounds : vec ! [ TyBound :: Nothing ] ,
67
+ ty_bounds : Vec :: new ( ) ,
68
68
cx,
69
69
}
70
70
}
71
71
72
72
/// Check whether a passed literal has potential to cause fallback or not.
73
73
fn check_lit ( & self , lit : & Lit , lit_ty : Ty < ' tcx > ) {
74
- let ty_bound = self . ty_bounds . last ( ) . unwrap ( ) ;
75
74
if_chain ! {
75
+ if let Some ( ty_bound) = self . ty_bounds. last( ) ;
76
76
if matches!( lit. node,
77
77
LitKind :: Int ( _, LitIntType :: Unsuffixed ) | LitKind :: Float ( _, LitFloatType :: Unsuffixed ) ) ;
78
78
if matches!( lit_ty. kind( ) , ty:: Int ( IntTy :: I32 ) | ty:: Float ( FloatTy :: F64 ) ) ;
@@ -98,19 +98,14 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> {
98
98
fn visit_expr ( & mut self , expr : & ' tcx Expr < ' _ > ) {
99
99
match & expr. kind {
100
100
ExprKind :: Call ( func, args) => {
101
- if_chain ! {
102
- if let ExprKind :: Path ( ref func_path) = func. kind;
103
- if let Some ( def_id) = self . cx. qpath_res( func_path, func. hir_id) . opt_def_id( ) ;
104
- then {
105
- let fn_sig = self . cx. tcx. fn_sig( def_id) . skip_binder( ) ;
106
- for ( expr, bound) in args. iter( ) . zip( fn_sig. inputs( ) . iter( ) ) {
107
- // Push found arg type, then visit arg.
108
- self . ty_bounds. push( TyBound :: Ty ( bound) ) ;
109
- self . visit_expr( expr) ;
110
- self . ty_bounds. pop( ) ;
111
- }
112
- return ;
101
+ if let Some ( fn_sig) = fn_sig_opt ( self . cx , func. hir_id ) {
102
+ for ( expr, bound) in args. iter ( ) . zip ( fn_sig. skip_binder ( ) . inputs ( ) . iter ( ) ) {
103
+ // Push found arg type, then visit arg.
104
+ self . ty_bounds . push ( TyBound :: Ty ( bound) ) ;
105
+ self . visit_expr ( expr) ;
106
+ self . ty_bounds . pop ( ) ;
113
107
}
108
+ return ;
114
109
}
115
110
} ,
116
111
@@ -160,6 +155,16 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> {
160
155
}
161
156
}
162
157
158
+ fn fn_sig_opt < ' tcx > ( cx : & LateContext < ' tcx > , hir_id : HirId ) -> Option < PolyFnSig < ' tcx > > {
159
+ let node_ty = cx. typeck_results ( ) . node_type_opt ( hir_id) ?;
160
+ // We can't use `TyS::fn_sig` because it automatically performs substs, this may result in FNs.
161
+ match node_ty. kind ( ) {
162
+ ty:: FnDef ( def_id, _) => Some ( cx. tcx . fn_sig ( * def_id) ) ,
163
+ ty:: FnPtr ( fn_sig) => Some ( * fn_sig) ,
164
+ _ => None ,
165
+ }
166
+ }
167
+
163
168
#[ derive( Debug , Clone , Copy ) ]
164
169
enum TyBound < ' ctx > {
165
170
Any ,
0 commit comments