1
1
use crate :: utils:: { match_def_path, paths, qpath_res, span_lint} ;
2
2
use if_chain:: if_chain;
3
- use rustc:: hir:: { Expr , ExprKind } ;
3
+ use rustc:: hir:: { Expr , ExprKind , Item , ItemKind , Node } ;
4
4
use rustc:: lint:: { LateContext , LateLintPass , LintArray , LintPass } ;
5
5
use rustc:: { declare_lint_pass, declare_tool_lint} ;
6
6
@@ -11,8 +11,7 @@ declare_clippy_lint! {
11
11
/// **Why is this bad?** Ideally a program is terminated by finishing
12
12
/// the main function.
13
13
///
14
- /// **Known problems:** This can be valid code in main() to return
15
- /// errors
14
+ /// **Known problems:** None.
16
15
///
17
16
/// **Example:**
18
17
/// ```ignore
@@ -33,7 +32,29 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Exit {
33
32
if let Some ( def_id) = qpath_res( cx, path, path_expr. hir_id) . opt_def_id( ) ;
34
33
if match_def_path( cx, def_id, & paths:: EXIT ) ;
35
34
then {
36
- span_lint( cx, EXIT , e. span, "usage of `process::exit`" ) ;
35
+ let mut parent = cx. tcx. hir( ) . get_parent_item( e. hir_id) ;
36
+ // We have to traverse the parents upwards until we find a function
37
+ // otherwise a exit in a let or if in main would still trigger this
38
+ loop {
39
+ match cx. tcx. hir( ) . find( parent) {
40
+ Some ( Node :: Item ( Item { ident, kind: ItemKind :: Fn ( ..) , ..} ) ) => {
41
+ // If we found a function we check it's name if it is
42
+ // `main` we emit a lint.
43
+ if ident. name. as_str( ) != "main" {
44
+ span_lint( cx, EXIT , e. span, "usage of `process::exit`" ) ;
45
+ }
46
+ // We found any kind of function and can end our loop
47
+ break ;
48
+ }
49
+ // If we found anything but a funciton we continue with the
50
+ // loop and go one parent up
51
+ Some ( _) => {
52
+ cx. tcx. hir( ) . get_parent_item( parent) ;
53
+ } ,
54
+ // If we found nothing we break.
55
+ None => break ,
56
+ }
57
+ }
37
58
}
38
59
39
60
}
0 commit comments