about summary refs log tree commit diff
path: root/clippy_lints/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-07-11 09:34:48 +0000
committerbors <bors@rust-lang.org>2023-07-11 09:34:48 +0000
commita8939e5eae4d6531f04599d24d9571fe8eec728f (patch)
treec06909b3822e397c297e01a339de427f13beb705 /clippy_lints/src
parentb485e4f840360feb66c2093db6246dc5f1cc311b (diff)
parent103949b241f66085d41f99d5f8ddbc281844df6d (diff)
Auto merge of #111717 - Urgau:uplift_fn_null_check, r=oli-obk
Uplift `clippy::fn_null_check` lint

This PR aims at uplifting the `clippy::fn_null_check` lint into rustc.

## `incorrect_fn_null_checks`

(warn-by-default)

The `incorrect_fn_null_checks` lint checks for expression that checks if a function pointer is null.

### Example

```rust
let fn_ptr: fn() = /* somehow obtained nullable function pointer */

if (fn_ptr as *const ()).is_null() { /* ... */ }
```

### Explanation

Function pointers are assumed to be non-null, checking for their nullity is incorrect.

-----

Mostly followed the instructions for uplifting a clippy lint described here: https://github.com/rust-lang/rust/pull/99696#pullrequestreview-1134072751

`@rustbot` label: +I-lang-nominated
r? compiler
Diffstat (limited to 'clippy_lints/src')
-rw-r--r--clippy_lints/src/declared_lints.rs1
-rw-r--r--clippy_lints/src/fn_null_check.rs102
-rw-r--r--clippy_lints/src/lib.rs2
-rw-r--r--clippy_lints/src/renamed_lints.rs1
4 files changed, 1 insertions, 105 deletions
diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs
index 9d9ee6ba307..b60f0738f64 100644
--- a/clippy_lints/src/declared_lints.rs
+++ b/clippy_lints/src/declared_lints.rs
@@ -171,7 +171,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::float_literal::LOSSY_FLOAT_LITERAL_INFO,
     crate::floating_point_arithmetic::IMPRECISE_FLOPS_INFO,
     crate::floating_point_arithmetic::SUBOPTIMAL_FLOPS_INFO,
-    crate::fn_null_check::FN_NULL_CHECK_INFO,
     crate::format::USELESS_FORMAT_INFO,
     crate::format_args::FORMAT_IN_FORMAT_ARGS_INFO,
     crate::format_args::TO_STRING_IN_FORMAT_ARGS_INFO,
diff --git a/clippy_lints/src/fn_null_check.rs b/clippy_lints/src/fn_null_check.rs
deleted file mode 100644
index 521045a9fed..00000000000
--- a/clippy_lints/src/fn_null_check.rs
+++ /dev/null
@@ -1,102 +0,0 @@
-use clippy_utils::consts::{constant, Constant};
-use clippy_utils::diagnostics::span_lint_and_help;
-use clippy_utils::{is_integer_literal, is_path_diagnostic_item};
-use rustc_hir::{BinOpKind, Expr, ExprKind, TyKind};
-use rustc_lint::{LateContext, LateLintPass};
-use rustc_session::{declare_lint_pass, declare_tool_lint};
-use rustc_span::sym;
-
-declare_clippy_lint! {
-    /// ### What it does
-    /// Checks for comparing a function pointer to null.
-    ///
-    /// ### Why is this bad?
-    /// Function pointers are assumed to not be null.
-    ///
-    /// ### Example
-    /// ```rust,ignore
-    /// let fn_ptr: fn() = /* somehow obtained nullable function pointer */
-    ///
-    /// if (fn_ptr as *const ()).is_null() { ... }
-    /// ```
-    /// Use instead:
-    /// ```rust,ignore
-    /// let fn_ptr: Option<fn()> = /* somehow obtained nullable function pointer */
-    ///
-    /// if fn_ptr.is_none() { ... }
-    /// ```
-    #[clippy::version = "1.68.0"]
-    pub FN_NULL_CHECK,
-    correctness,
-    "`fn()` type assumed to be nullable"
-}
-declare_lint_pass!(FnNullCheck => [FN_NULL_CHECK]);
-
-fn lint_expr(cx: &LateContext<'_>, expr: &Expr<'_>) {
-    span_lint_and_help(
-        cx,
-        FN_NULL_CHECK,
-        expr.span,
-        "function pointer assumed to be nullable, even though it isn't",
-        None,
-        "try wrapping your function pointer type in `Option<T>` instead, and using `is_none` to check for null pointer value",
-    );
-}
-
-fn is_fn_ptr_cast(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
-    if let ExprKind::Cast(cast_expr, cast_ty) = expr.kind
-        && let TyKind::Ptr(_) = cast_ty.kind
-    {
-        cx.typeck_results().expr_ty_adjusted(cast_expr).is_fn()
-    } else {
-        false
-    }
-}
-
-impl<'tcx> LateLintPass<'tcx> for FnNullCheck {
-    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        match expr.kind {
-            // Catching:
-            // (fn_ptr as *<const/mut> <ty>).is_null()
-            ExprKind::MethodCall(method_name, receiver, _, _)
-                if method_name.ident.as_str() == "is_null" && is_fn_ptr_cast(cx, receiver) =>
-            {
-                lint_expr(cx, expr);
-            },
-
-            ExprKind::Binary(op, left, right) if matches!(op.node, BinOpKind::Eq) => {
-                let to_check: &Expr<'_>;
-                if is_fn_ptr_cast(cx, left) {
-                    to_check = right;
-                } else if is_fn_ptr_cast(cx, right) {
-                    to_check = left;
-                } else {
-                    return;
-                }
-
-                match to_check.kind {
-                    // Catching:
-                    // (fn_ptr as *<const/mut> <ty>) == (0 as <ty>)
-                    ExprKind::Cast(cast_expr, _) if is_integer_literal(cast_expr, 0) => {
-                        lint_expr(cx, expr);
-                    },
-
-                    // Catching:
-                    // (fn_ptr as *<const/mut> <ty>) == std::ptr::null()
-                    ExprKind::Call(func, []) if is_path_diagnostic_item(cx, func, sym::ptr_null) => {
-                        lint_expr(cx, expr);
-                    },
-
-                    // Catching:
-                    // (fn_ptr as *<const/mut> <ty>) == <const that evaluates to null_ptr>
-                    _ if matches!(constant(cx, cx.typeck_results(), to_check), Some(Constant::RawPtr(0))) => {
-                        lint_expr(cx, expr);
-                    },
-
-                    _ => {},
-                }
-            },
-            _ => {},
-        }
-    }
-}
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index 87329ee5e14..365cc4c59ad 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -131,7 +131,6 @@ mod extra_unused_type_parameters;
 mod fallible_impl_from;
 mod float_literal;
 mod floating_point_arithmetic;
-mod fn_null_check;
 mod format;
 mod format_args;
 mod format_impl;
@@ -1003,7 +1002,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
             semicolon_outside_block_ignore_multiline,
         ))
     });
-    store.register_late_pass(|_| Box::new(fn_null_check::FnNullCheck));
     store.register_late_pass(|_| Box::new(permissions_set_readonly_false::PermissionsSetReadonlyFalse));
     store.register_late_pass(|_| Box::new(size_of_ref::SizeOfRef));
     store.register_late_pass(|_| Box::new(multiple_unsafe_ops_per_block::MultipleUnsafeOpsPerBlock));
diff --git a/clippy_lints/src/renamed_lints.rs b/clippy_lints/src/renamed_lints.rs
index cbcd11debfd..d24215c2292 100644
--- a/clippy_lints/src/renamed_lints.rs
+++ b/clippy_lints/src/renamed_lints.rs
@@ -42,6 +42,7 @@ pub static RENAMED_LINTS: &[(&str, &str)] = &[
     ("clippy::for_loops_over_fallibles", "for_loops_over_fallibles"),
     ("clippy::forget_copy", "forgetting_copy_types"),
     ("clippy::forget_ref", "forgetting_references"),
+    ("clippy::fn_null_check", "incorrect_fn_null_checks"),
     ("clippy::into_iter_on_array", "array_into_iter"),
     ("clippy::invalid_atomic_ordering", "invalid_atomic_ordering"),
     ("clippy::invalid_ref", "invalid_value"),