@@ -4,7 +4,7 @@ use clippy_utils::{get_parent_node, numeric_literal};
44use rustc_ast:: ast:: { LitFloatType , LitIntType , LitKind } ;
55use rustc_errors:: Applicability ;
66use 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 } ;
88use rustc_lint:: { LateContext , LateLintPass , LintContext } ;
99use rustc_middle:: lint:: in_external_macro;
1010use rustc_middle:: ty:: { self , FloatTy , IntTy , PolyFnSig , Ty } ;
@@ -122,13 +122,42 @@ impl<'a, 'tcx> NumericFallbackVisitor<'a, 'tcx> {
122122impl < ' a , ' tcx > Visitor < ' tcx > for NumericFallbackVisitor < ' a , ' tcx > {
123123 fn visit_expr ( & mut self , expr : & ' tcx Expr < ' _ > ) {
124124 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+
125149 ExprKind :: Call ( func, args) => {
126150 if let Some ( fn_sig) = fn_sig_opt ( self . cx , func. hir_id ) {
127151 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+ }
132161 }
133162 return ;
134163 }
@@ -137,7 +166,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> {
137166 ExprKind :: MethodCall ( _, receiver, args, _) => {
138167 if let Some ( def_id) = self . cx . typeck_results ( ) . type_dependent_def_id ( expr. hir_id ) {
139168 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 ( ) ) {
141170 self . ty_bounds . push ( ( * bound) . into ( ) ) ;
142171 self . visit_expr ( expr) ;
143172 self . ty_bounds . pop ( ) ;
0 commit comments