@@ -2,7 +2,7 @@ use rustc_ast::ast::{Label, LitFloatType, LitIntType, LitKind};
2
2
use rustc_hir:: {
3
3
self as hir,
4
4
intravisit:: { walk_expr, walk_stmt, walk_ty, FnKind , NestedVisitorMap , Visitor } ,
5
- Body , Expr , ExprKind , FnDecl , FnRetTy , Guard , HirId , Lit , Stmt , StmtKind ,
5
+ Body , BodyId , Expr , ExprKind , FnDecl , FnRetTy , Guard , HirId , Lit , Stmt , StmtKind ,
6
6
} ;
7
7
use rustc_lint:: { LateContext , LateLintPass } ;
8
8
use rustc_middle:: {
@@ -50,16 +50,31 @@ declare_clippy_lint! {
50
50
51
51
declare_lint_pass ! ( DefaultNumericFallback => [ DEFAULT_NUMERIC_FALLBACK ] ) ;
52
52
53
- fn enclosing_body_owner_opt ( tcx : TyCtxt < ' _ > , hir_id : HirId ) -> Option < HirId > {
53
+ /// Return the body that includes passed `hir_id` if exists.
54
+ fn enclosing_body_opt ( tcx : TyCtxt < ' _ > , hir_id : HirId ) -> Option < BodyId > {
54
55
let hir_map = tcx. hir ( ) ;
56
+ let mut trace = vec ! [ ( hir_id) ] ;
57
+
55
58
for ( parent, _) in hir_map. parent_iter ( hir_id) {
59
+ trace. push ( parent) ;
56
60
if let Some ( body) = hir_map. maybe_body_owned_by ( parent) {
57
- return Some ( hir_map. body_owner ( body) ) ;
61
+ if trace. iter ( ) . any ( |hir_id| * hir_id == body. hir_id ) {
62
+ return Some ( body) ;
63
+ }
58
64
}
59
65
}
66
+
60
67
None
61
68
}
62
69
70
+ fn ty_from_hir_ty < ' tcx > ( cx : & LateContext < ' tcx > , hir_ty : & hir:: Ty < ' tcx > ) -> Option < Ty < ' tcx > > {
71
+ if enclosing_body_opt ( cx. tcx , hir_ty. hir_id ) . is_some ( ) {
72
+ cx. typeck_results ( ) . node_type_opt ( hir_ty. hir_id )
73
+ } else {
74
+ Some ( hir_ty_to_ty ( cx. tcx , hir_ty) )
75
+ }
76
+ }
77
+
63
78
impl LateLintPass < ' _ > for DefaultNumericFallback {
64
79
fn check_fn (
65
80
& mut self ,
@@ -68,21 +83,17 @@ impl LateLintPass<'_> for DefaultNumericFallback {
68
83
fn_decl : & ' tcx FnDecl < ' _ > ,
69
84
body : & ' tcx Body < ' _ > ,
70
85
_: Span ,
71
- hir_id : HirId ,
86
+ _ : HirId ,
72
87
) {
73
88
let ret_ty_bound = match fn_decl. output {
74
89
FnRetTy :: DefaultReturn ( _) => None ,
75
90
FnRetTy :: Return ( ty) => Some ( ty) ,
76
91
}
77
92
. and_then ( |ty| {
78
- let mut infer_ty_finder = InferTyFinder :: new ( ) ;
79
- infer_ty_finder. visit_ty ( ty) ;
80
- if infer_ty_finder. found {
93
+ if is_infer_included ( ty) {
81
94
None
82
- } else if enclosing_body_owner_opt ( cx. tcx , hir_id) . is_some ( ) {
83
- cx. typeck_results ( ) . node_type_opt ( ty. hir_id )
84
95
} else {
85
- Some ( hir_ty_to_ty ( cx . tcx , ty) )
96
+ ty_from_hir_ty ( cx , ty)
86
97
}
87
98
} ) ;
88
99
@@ -114,7 +125,7 @@ impl<'a, 'tcx> NumericFallbackVisitor<'a, 'tcx> {
114
125
}
115
126
}
116
127
117
- /// Check whether lit cause fallback or not.
128
+ /// Check whether a passed literal has potential to cause fallback or not.
118
129
fn check_lit ( & self , lit : & Lit , lit_ty : Ty < ' tcx > ) {
119
130
let ty_bound = self . ty_bounds . last ( ) . unwrap ( ) ;
120
131
@@ -334,12 +345,10 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> {
334
345
match stmt. kind {
335
346
StmtKind :: Local ( local) => {
336
347
let ty = local. ty . and_then ( |hir_ty| {
337
- let mut infer_ty_finder = InferTyFinder :: new ( ) ;
338
- infer_ty_finder. visit_ty ( hir_ty) ;
339
- if infer_ty_finder. found {
348
+ if is_infer_included ( hir_ty) {
340
349
None
341
350
} else {
342
- self . cx . typeck_results ( ) . node_type_opt ( hir_ty. hir_id )
351
+ ty_from_hir_ty ( self . cx , hir_ty)
343
352
}
344
353
} ) ;
345
354
self . ty_bounds . push ( ty) ;
@@ -357,7 +366,13 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> {
357
366
}
358
367
}
359
368
360
- /// Find `hir::TyKind::Infer` is included in passed typed.
369
+ /// Return true if a given ty includes `hir::TyKind::Infer`.
370
+ fn is_infer_included ( ty : & hir:: Ty < ' _ > ) -> bool {
371
+ let mut infer_ty_finder = InferTyFinder :: new ( ) ;
372
+ infer_ty_finder. visit_ty ( ty) ;
373
+ infer_ty_finder. found
374
+ }
375
+
361
376
struct InferTyFinder {
362
377
found : bool ,
363
378
}
0 commit comments