@@ -31,12 +31,30 @@ declare_lint! {
3131
3232declare_lint_pass ! ( PtrNullChecks => [ USELESS_PTR_NULL_CHECKS ] ) ;
3333
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 > > {
3743 let mut had_at_least_one_cast = false ;
3844 loop {
3945 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+ }
4058 e = if let ExprKind :: Cast ( expr, t) = e. kind
4159 && let TyKind :: Ptr ( _) = t. kind {
4260 had_at_least_one_cast = true ;
@@ -46,33 +64,21 @@ fn ptr_cast_chain<'a>(cx: &'a LateContext<'_>, mut e: &'a Expr<'a>) -> Option<&'
4664 && matches ! ( cx. tcx. get_diagnostic_name( def_id) , Some ( sym:: ptr_cast | sym:: ptr_cast_mut) ) {
4765 had_at_least_one_cast = true ;
4866 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
5567 } 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+ } ;
5776 } else {
5877 return None ;
5978 } ;
6079 }
6180}
6281
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-
7682impl < ' tcx > LateLintPass < ' tcx > for PtrNullChecks {
7783 fn check_expr ( & mut self , cx : & LateContext < ' tcx > , expr : & ' tcx Expr < ' _ > ) {
7884 match expr. kind {
0 commit comments