11use clippy_utils:: consts:: { constant, Constant } ;
22use clippy_utils:: diagnostics:: span_lint_and_help;
33use clippy_utils:: { is_integer_literal, is_path_diagnostic_item} ;
4- use if_chain:: if_chain;
54use rustc_hir:: { BinOpKind , Expr , ExprKind , TyKind } ;
65use rustc_lint:: { LateContext , LateLintPass } ;
76use rustc_session:: { declare_lint_pass, declare_tool_lint} ;
@@ -33,40 +32,37 @@ declare_clippy_lint! {
3332}
3433declare_lint_pass ! ( FnNullCheck => [ FN_NULL_CHECK ] ) ;
3534
36- const LINT_MSG : & str = "function pointer assumed to be nullable, even though it isn't" ;
37- const HELP_MSG : & str = "try wrapping your function pointer type in `Option<T>` instead, and using `is_none` to check for null pointer value" ;
35+ fn lint_expr ( cx : & LateContext < ' _ > , expr : & Expr < ' _ > ) {
36+ span_lint_and_help (
37+ cx,
38+ FN_NULL_CHECK ,
39+ expr. span ,
40+ "function pointer assumed to be nullable, even though it isn't" ,
41+ None ,
42+ "try wrapping your function pointer type in `Option<T>` instead, and using `is_none` to check for null pointer value" ,
43+ )
44+ }
3845
3946fn is_fn_ptr_cast ( cx : & LateContext < ' _ > , expr : & Expr < ' _ > ) -> bool {
40- if_chain ! {
41- if let ExprKind :: Cast ( cast_expr, cast_ty) = expr. kind;
42- if let TyKind :: Ptr ( _) = cast_ty. kind;
43- if cx. typeck_results( ) . expr_ty_adjusted( cast_expr) . is_fn( ) ;
44- then {
45- true
46- } else {
47- false
48- }
47+ if let ExprKind :: Cast ( cast_expr, cast_ty) = expr. kind
48+ && let TyKind :: Ptr ( _) = cast_ty. kind
49+ {
50+ cx. typeck_results ( ) . expr_ty_adjusted ( cast_expr) . is_fn ( )
51+ } else {
52+ false
4953 }
5054}
5155
5256impl < ' tcx > LateLintPass < ' tcx > for FnNullCheck {
5357 fn check_expr ( & mut self , cx : & LateContext < ' tcx > , expr : & ' tcx Expr < ' _ > ) {
5458 // Catching:
5559 // (fn_ptr as *<const/mut> <ty>).is_null()
56- if_chain ! {
57- if let ExprKind :: MethodCall ( method_name, receiver, _, _) = expr. kind;
58- if method_name. ident. as_str( ) == "is_null" ;
59- if is_fn_ptr_cast( cx, receiver) ;
60- then {
61- span_lint_and_help(
62- cx,
63- FN_NULL_CHECK ,
64- expr. span,
65- LINT_MSG ,
66- None ,
67- HELP_MSG
68- ) ;
69- }
60+ if let ExprKind :: MethodCall ( method_name, receiver, _, _) = expr. kind
61+ && method_name. ident . as_str ( ) == "is_null"
62+ && is_fn_ptr_cast ( cx, receiver)
63+ {
64+ lint_expr ( cx, expr) ;
65+ return ;
7066 }
7167
7268 if let ExprKind :: Binary ( op, left, right) = expr. kind
@@ -85,28 +81,14 @@ impl<'tcx> LateLintPass<'tcx> for FnNullCheck {
8581 // (fn_ptr as *<const/mut> <ty>) == <const that evaluates to null_ptr>
8682 let c = constant ( cx, cx. typeck_results ( ) , to_check) ;
8783 if let Some ( ( Constant :: RawPtr ( 0 ) , _) ) = c {
88- span_lint_and_help (
89- cx,
90- FN_NULL_CHECK ,
91- expr. span ,
92- LINT_MSG ,
93- None ,
94- HELP_MSG
95- ) ;
84+ lint_expr ( cx, expr) ;
9685 return ;
9786 }
9887
9988 // Catching:
10089 // (fn_ptr as *<const/mut> <ty>) == (0 as <ty>)
10190 if let ExprKind :: Cast ( cast_expr, _) = to_check. kind && is_integer_literal ( cast_expr, 0 ) {
102- span_lint_and_help (
103- cx,
104- FN_NULL_CHECK ,
105- expr. span ,
106- LINT_MSG ,
107- None ,
108- HELP_MSG
109- ) ;
91+ lint_expr ( cx, expr) ;
11092 return ;
11193 }
11294
@@ -115,14 +97,7 @@ impl<'tcx> LateLintPass<'tcx> for FnNullCheck {
11597 if let ExprKind :: Call ( func, [ ] ) = to_check. kind &&
11698 is_path_diagnostic_item ( cx, func, sym:: ptr_null)
11799 {
118- span_lint_and_help (
119- cx,
120- FN_NULL_CHECK ,
121- expr. span ,
122- LINT_MSG ,
123- None ,
124- HELP_MSG
125- ) ;
100+ lint_expr ( cx, expr) ;
126101 }
127102 }
128103 }
0 commit comments