@@ -4,7 +4,7 @@ use clippy_utils::{get_parent_node, numeric_literal};
4
4
use rustc_ast:: ast:: { LitFloatType , LitIntType , LitKind } ;
5
5
use rustc_errors:: Applicability ;
6
6
use rustc_hir:: intravisit:: { walk_expr, walk_stmt, Visitor } ;
7
- use rustc_hir:: { Body , Expr , ExprKind , HirId , ItemKind , Lit , Node , Stmt , StmtKind } ;
7
+ use rustc_hir:: { Block , Body , Expr , ExprKind , FnRetTy , HirId , ItemKind , Lit , Node , Stmt , StmtKind } ;
8
8
use rustc_lint:: { LateContext , LateLintPass , LintContext } ;
9
9
use rustc_middle:: lint:: in_external_macro;
10
10
use rustc_middle:: ty:: { self , FloatTy , IntTy , PolyFnSig , Ty } ;
@@ -122,13 +122,42 @@ impl<'a, 'tcx> NumericFallbackVisitor<'a, 'tcx> {
122
122
impl < ' a , ' tcx > Visitor < ' tcx > for NumericFallbackVisitor < ' a , ' tcx > {
123
123
fn visit_expr ( & mut self , expr : & ' tcx Expr < ' _ > ) {
124
124
match & expr. kind {
125
+ ExprKind :: Block (
126
+ Block {
127
+ stmts, expr : Some ( _) , ..
128
+ } ,
129
+ _,
130
+ ) => {
131
+ if let Some ( parent) = self . cx . tcx . hir ( ) . find_parent ( expr. hir_id )
132
+ && let Some ( fn_sig) = parent. fn_sig ( )
133
+ && let FnRetTy :: Return ( _ty) = fn_sig. decl . output
134
+ {
135
+ // We cannot check the exact type since it's a `hir::Ty`` which does not implement `is_numeric`
136
+ self . ty_bounds . push ( ExplicitTyBound ( true ) ) ;
137
+ for stmt in * stmts {
138
+ self . visit_stmt ( stmt) ;
139
+ }
140
+ self . ty_bounds . pop ( ) ;
141
+ // Ignore return expr since we know its type was inferred from return ty
142
+ return ;
143
+ }
144
+ } ,
145
+
146
+ // Ignore return expr since we know its type was inferred from return ty
147
+ ExprKind :: Ret ( _) => return ,
148
+
125
149
ExprKind :: Call ( func, args) => {
126
150
if let Some ( fn_sig) = fn_sig_opt ( self . cx , func. hir_id ) {
127
151
for ( expr, bound) in iter:: zip ( * args, fn_sig. skip_binder ( ) . inputs ( ) ) {
128
- // Push found arg type, then visit arg.
129
- self . ty_bounds . push ( ( * bound) . into ( ) ) ;
130
- self . visit_expr ( expr) ;
131
- self . ty_bounds . pop ( ) ;
152
+ // If is from macro, try to use last bound type (typically pushed when visiting stmt),
153
+ // otherwise push found arg type, then visit arg,
154
+ if expr. span . from_expansion ( ) {
155
+ self . visit_expr ( expr) ;
156
+ } else {
157
+ self . ty_bounds . push ( ( * bound) . into ( ) ) ;
158
+ self . visit_expr ( expr) ;
159
+ self . ty_bounds . pop ( ) ;
160
+ }
132
161
}
133
162
return ;
134
163
}
@@ -137,7 +166,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> {
137
166
ExprKind :: MethodCall ( _, receiver, args, _) => {
138
167
if let Some ( def_id) = self . cx . typeck_results ( ) . type_dependent_def_id ( expr. hir_id ) {
139
168
let fn_sig = self . cx . tcx . fn_sig ( def_id) . instantiate_identity ( ) . skip_binder ( ) ;
140
- for ( expr, bound) in iter:: zip ( std :: iter:: once ( * receiver) . chain ( args. iter ( ) ) , fn_sig. inputs ( ) ) {
169
+ for ( expr, bound) in iter:: zip ( iter:: once ( * receiver) . chain ( args. iter ( ) ) , fn_sig. inputs ( ) ) {
141
170
self . ty_bounds . push ( ( * bound) . into ( ) ) ;
142
171
self . visit_expr ( expr) ;
143
172
self . ty_bounds . pop ( ) ;
0 commit comments