@@ -31,12 +31,30 @@ declare_lint! {
31
31
32
32
declare_lint_pass ! ( PtrNullChecks => [ USELESS_PTR_NULL_CHECKS ] ) ;
33
33
34
- /// This function detects and returns the original expression from a series of consecutive casts,
35
- /// ie. `(my_fn as *const _ as *mut _).cast_mut()` would return the expression for `my_fn`.
36
- fn ptr_cast_chain < ' a > ( cx : & ' a LateContext < ' _ > , mut e : & ' a Expr < ' a > ) -> Option < & ' a Expr < ' a > > {
34
+ /// This function checks if the expression is from a series of consecutive casts,
35
+ /// ie. `(my_fn as *const _ as *mut _).cast_mut()` and whether the original expression is either
36
+ /// a fn ptr, a reference, or a function call whose definition is
37
+ /// annotated with `#![rustc_never_returns_null_ptr]`.
38
+ /// If this situation is present, the function returns the appropriate diagnostic.
39
+ fn incorrect_check < ' a , ' tcx : ' a > (
40
+ cx : & ' a LateContext < ' tcx > ,
41
+ mut e : & ' a Expr < ' a > ,
42
+ ) -> Option < PtrNullChecksDiag < ' tcx > > {
37
43
let mut had_at_least_one_cast = false ;
38
44
loop {
39
45
e = e. peel_blocks ( ) ;
46
+ if let ExprKind :: MethodCall ( _, _expr, [ ] , _) = e. kind
47
+ && let Some ( def_id) = cx. typeck_results ( ) . type_dependent_def_id ( e. hir_id )
48
+ && cx. tcx . has_attr ( def_id, sym:: rustc_never_returns_null_ptr)
49
+ && let Some ( fn_name) = cx. tcx . opt_item_ident ( def_id) {
50
+ return Some ( PtrNullChecksDiag :: FnRet { fn_name } ) ;
51
+ } else if let ExprKind :: Call ( path, _args) = e. kind
52
+ && let ExprKind :: Path ( ref qpath) = path. kind
53
+ && let Some ( def_id) = cx. qpath_res ( qpath, path. hir_id ) . opt_def_id ( )
54
+ && cx. tcx . has_attr ( def_id, sym:: rustc_never_returns_null_ptr)
55
+ && let Some ( fn_name) = cx. tcx . opt_item_ident ( def_id) {
56
+ return Some ( PtrNullChecksDiag :: FnRet { fn_name } ) ;
57
+ }
40
58
e = if let ExprKind :: Cast ( expr, t) = e. kind
41
59
&& let TyKind :: Ptr ( _) = t. kind {
42
60
had_at_least_one_cast = true ;
@@ -46,33 +64,21 @@ fn ptr_cast_chain<'a>(cx: &'a LateContext<'_>, mut e: &'a Expr<'a>) -> Option<&'
46
64
&& matches ! ( cx. tcx. get_diagnostic_name( def_id) , Some ( sym:: ptr_cast | sym:: ptr_cast_mut) ) {
47
65
had_at_least_one_cast = true ;
48
66
expr
49
- } else if let ExprKind :: Call ( path, [ arg] ) = e. kind
50
- && let ExprKind :: Path ( ref qpath) = path. kind
51
- && let Some ( def_id) = cx. qpath_res ( qpath, path. hir_id ) . opt_def_id ( )
52
- && cx. tcx . has_attr ( def_id, sym:: rustc_never_returns_null_ptr) {
53
- had_at_least_one_cast = true ;
54
- arg
55
67
} else if had_at_least_one_cast {
56
- return Some ( e) ;
68
+ let orig_ty = cx. typeck_results ( ) . expr_ty ( e) ;
69
+ return if orig_ty. is_fn ( ) {
70
+ Some ( PtrNullChecksDiag :: FnPtr { orig_ty, label : e. span } )
71
+ } else if orig_ty. is_ref ( ) {
72
+ Some ( PtrNullChecksDiag :: Ref { orig_ty, label : e. span } )
73
+ } else {
74
+ None
75
+ } ;
57
76
} else {
58
77
return None ;
59
78
} ;
60
79
}
61
80
}
62
81
63
- fn incorrect_check < ' a > ( cx : & LateContext < ' a > , expr : & Expr < ' _ > ) -> Option < PtrNullChecksDiag < ' a > > {
64
- let expr = ptr_cast_chain ( cx, expr) ?;
65
-
66
- let orig_ty = cx. typeck_results ( ) . expr_ty ( expr) ;
67
- if orig_ty. is_fn ( ) {
68
- Some ( PtrNullChecksDiag :: FnPtr { orig_ty, label : expr. span } )
69
- } else if orig_ty. is_ref ( ) {
70
- Some ( PtrNullChecksDiag :: Ref { orig_ty, label : expr. span } )
71
- } else {
72
- None
73
- }
74
- }
75
-
76
82
impl < ' tcx > LateLintPass < ' tcx > for PtrNullChecks {
77
83
fn check_expr ( & mut self , cx : & LateContext < ' tcx > , expr : & ' tcx Expr < ' _ > ) {
78
84
match expr. kind {
0 commit comments