From 1e377c16fe93b893056bb1d661e16453bd2f7d24 Mon Sep 17 00:00:00 2001 From: Urgau Date: Wed, 17 May 2023 16:49:18 +0200 Subject: [PATCH 1/3] Add diagnostic items for `<*mut _>::is_null` and `<*const _>::is_null` --- compiler/rustc_span/src/symbol.rs | 2 ++ library/core/src/ptr/const_ptr.rs | 1 + library/core/src/ptr/mut_ptr.rs | 1 + 3 files changed, 4 insertions(+) diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index c58d85b99f79f..95702a5e3cde7 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1151,8 +1151,10 @@ symbols! { profiler_runtime, ptr, ptr_cast_mut, + ptr_const_is_null, ptr_from_ref, ptr_guaranteed_cmp, + ptr_is_null, ptr_mask, ptr_null, ptr_null_mut, diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 926189a17b204..74046a9c7c380 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -30,6 +30,7 @@ impl *const T { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_ptr_is_null", issue = "74939")] + #[rustc_diagnostic_item = "ptr_const_is_null"] #[inline] pub const fn is_null(self) -> bool { #[inline] diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index c6f43857887c9..e7f27439540b9 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -29,6 +29,7 @@ impl *mut T { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_ptr_is_null", issue = "74939")] + #[rustc_diagnostic_item = "ptr_is_null"] #[inline] pub const fn is_null(self) -> bool { #[inline] From f6d2bf63d3ce225a79dfdb9bab0f93568ad6e137 Mon Sep 17 00:00:00 2001 From: Urgau Date: Wed, 17 May 2023 11:22:26 +0200 Subject: [PATCH 2/3] Uplift `clippy::fn_null_check` to rustc --- compiler/rustc_lint/messages.ftl | 3 + compiler/rustc_lint/src/fn_null_check.rs | 112 +++++++++++++++++++++++ compiler/rustc_lint/src/lib.rs | 3 + compiler/rustc_lint/src/lints.rs | 6 ++ tests/ui/lint/fn_null_check.rs | 30 ++++++ tests/ui/lint/fn_null_check.stderr | 67 ++++++++++++++ 6 files changed, 221 insertions(+) create mode 100644 compiler/rustc_lint/src/fn_null_check.rs create mode 100644 tests/ui/lint/fn_null_check.rs create mode 100644 tests/ui/lint/fn_null_check.stderr diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 34b7e09576af5..2c92277b50d21 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -215,6 +215,9 @@ lint_expectation = this lint expectation is unfulfilled .note = the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message .rationale = {$rationale} +lint_fn_null_check = function pointers are not nullable, so checking them for null will always return false + .help = wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value + lint_for_loops_over_fallibles = for loop over {$article} `{$ty}`. This is more readably written as an `if let` statement .suggestion = consider using `if let` to clear intent diff --git a/compiler/rustc_lint/src/fn_null_check.rs b/compiler/rustc_lint/src/fn_null_check.rs new file mode 100644 index 0000000000000..e3b33463ccfbc --- /dev/null +++ b/compiler/rustc_lint/src/fn_null_check.rs @@ -0,0 +1,112 @@ +use crate::{lints::FnNullCheckDiag, LateContext, LateLintPass, LintContext}; +use rustc_ast::LitKind; +use rustc_hir::{BinOpKind, Expr, ExprKind, TyKind}; +use rustc_session::{declare_lint, declare_lint_pass}; +use rustc_span::sym; + +declare_lint! { + /// The `incorrect_fn_null_checks` lint checks for expression that checks if a + /// function pointer is null. + /// + /// ### Example + /// + /// ```rust + /// # fn test() {} + /// let fn_ptr: fn() = /* somehow obtained nullable function pointer */ + /// # test; + /// + /// if (fn_ptr as *const ()).is_null() { /* ... */ } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Function pointers are assumed to be non-null, checking them for null will always + /// return false. + INCORRECT_FN_NULL_CHECKS, + Warn, + "incorrect checking of null function pointer" +} + +declare_lint_pass!(IncorrectFnNullChecks => [INCORRECT_FN_NULL_CHECKS]); + +fn is_fn_ptr_cast(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { + let mut expr = expr.peel_blocks(); + let mut had_at_least_one_cast = false; + while let ExprKind::Cast(cast_expr, cast_ty) = expr.kind + && let TyKind::Ptr(_) = cast_ty.kind { + expr = cast_expr.peel_blocks(); + had_at_least_one_cast = true; + } + had_at_least_one_cast && cx.typeck_results().expr_ty_adjusted(expr).is_fn() +} + +impl<'tcx> LateLintPass<'tcx> for IncorrectFnNullChecks { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { + match expr.kind { + // Catching: + // <* >::is_null(fn_ptr as * ) + ExprKind::Call(path, [arg]) + if let ExprKind::Path(ref qpath) = path.kind + && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id() + && matches!( + cx.tcx.get_diagnostic_name(def_id), + Some(sym::ptr_const_is_null | sym::ptr_is_null) + ) + && is_fn_ptr_cast(cx, arg) => + { + cx.emit_spanned_lint(INCORRECT_FN_NULL_CHECKS, expr.span, FnNullCheckDiag) + } + + // Catching: + // (fn_ptr as * ).is_null() + ExprKind::MethodCall(_, receiver, _, _) + if let Some(def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) + && matches!( + cx.tcx.get_diagnostic_name(def_id), + Some(sym::ptr_const_is_null | sym::ptr_is_null) + ) + && is_fn_ptr_cast(cx, receiver) => + { + cx.emit_spanned_lint(INCORRECT_FN_NULL_CHECKS, expr.span, FnNullCheckDiag) + } + + 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 * ) == (0 as ) + ExprKind::Cast(cast_expr, _) + if let ExprKind::Lit(spanned) = cast_expr.kind + && let LitKind::Int(v, _) = spanned.node && v == 0 => + { + cx.emit_spanned_lint(INCORRECT_FN_NULL_CHECKS, expr.span, FnNullCheckDiag) + }, + + // Catching: + // (fn_ptr as * ) == std::ptr::null() + ExprKind::Call(path, []) + if let ExprKind::Path(ref qpath) = path.kind + && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id() + && let Some(diag_item) = cx.tcx.get_diagnostic_name(def_id) + && (diag_item == sym::ptr_null || diag_item == sym::ptr_null_mut) => + { + cx.emit_spanned_lint(INCORRECT_FN_NULL_CHECKS, expr.span, FnNullCheckDiag) + }, + + _ => {}, + } + } + _ => {} + } + } +} diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 5e3f057d42834..beb38dbb94c32 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -58,6 +58,7 @@ mod early; mod enum_intrinsics_non_enums; mod errors; mod expect; +mod fn_null_check; mod for_loops_over_fallibles; pub mod hidden_unicode_codepoints; mod internal; @@ -102,6 +103,7 @@ use cast_ref_to_mut::*; use deref_into_dyn_supertrait::*; use drop_forget_useless::*; use enum_intrinsics_non_enums::EnumIntrinsicsNonEnums; +use fn_null_check::*; use for_loops_over_fallibles::*; use hidden_unicode_codepoints::*; use internal::*; @@ -225,6 +227,7 @@ late_lint_methods!( // Depends on types used in type definitions MissingCopyImplementations: MissingCopyImplementations, // Depends on referenced function signatures in expressions + IncorrectFnNullChecks: IncorrectFnNullChecks, MutableTransmutes: MutableTransmutes, TypeAliasBounds: TypeAliasBounds, TrivialConstraints: TrivialConstraints, diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 0613ef2c5e958..1dea758bb294b 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -613,6 +613,12 @@ pub struct ExpectationNote { pub rationale: Symbol, } +// fn_null_check.rs +#[derive(LintDiagnostic)] +#[diag(lint_fn_null_check)] +#[help] +pub struct FnNullCheckDiag; + // for_loops_over_fallibles.rs #[derive(LintDiagnostic)] #[diag(lint_for_loops_over_fallibles)] diff --git a/tests/ui/lint/fn_null_check.rs b/tests/ui/lint/fn_null_check.rs new file mode 100644 index 0000000000000..7f01f2c428395 --- /dev/null +++ b/tests/ui/lint/fn_null_check.rs @@ -0,0 +1,30 @@ +// check-pass + +fn main() { + let fn_ptr = main; + + if (fn_ptr as *mut ()).is_null() {} + //~^ WARN function pointers are not nullable + if (fn_ptr as *const u8).is_null() {} + //~^ WARN function pointers are not nullable + if (fn_ptr as *const ()) == std::ptr::null() {} + //~^ WARN function pointers are not nullable + if (fn_ptr as *mut ()) == std::ptr::null_mut() {} + //~^ WARN function pointers are not nullable + if (fn_ptr as *const ()) == (0 as *const ()) {} + //~^ WARN function pointers are not nullable + if <*const _>::is_null(fn_ptr as *const ()) {} + //~^ WARN function pointers are not nullable + if (fn_ptr as *mut fn() as *const fn() as *const ()).is_null() {} + //~^ WARN function pointers are not nullable + if (fn_ptr as fn() as *const ()).is_null() {} + //~^ WARN function pointers are not nullable + + const ZPTR: *const () = 0 as *const _; + const NOT_ZPTR: *const () = 1 as *const _; + + // unlike the uplifted clippy::fn_null_check lint we do + // not lint on them + if (fn_ptr as *const ()) == ZPTR {} + if (fn_ptr as *const ()) == NOT_ZPTR {} +} diff --git a/tests/ui/lint/fn_null_check.stderr b/tests/ui/lint/fn_null_check.stderr new file mode 100644 index 0000000000000..0398c0da50feb --- /dev/null +++ b/tests/ui/lint/fn_null_check.stderr @@ -0,0 +1,67 @@ +warning: function pointers are not nullable, so checking them for null will always return false + --> $DIR/fn_null_check.rs:6:8 + | +LL | if (fn_ptr as *mut ()).is_null() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value + = note: `#[warn(incorrect_fn_null_checks)]` on by default + +warning: function pointers are not nullable, so checking them for null will always return false + --> $DIR/fn_null_check.rs:8:8 + | +LL | if (fn_ptr as *const u8).is_null() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value + +warning: function pointers are not nullable, so checking them for null will always return false + --> $DIR/fn_null_check.rs:10:8 + | +LL | if (fn_ptr as *const ()) == std::ptr::null() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value + +warning: function pointers are not nullable, so checking them for null will always return false + --> $DIR/fn_null_check.rs:12:8 + | +LL | if (fn_ptr as *mut ()) == std::ptr::null_mut() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value + +warning: function pointers are not nullable, so checking them for null will always return false + --> $DIR/fn_null_check.rs:14:8 + | +LL | if (fn_ptr as *const ()) == (0 as *const ()) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value + +warning: function pointers are not nullable, so checking them for null will always return false + --> $DIR/fn_null_check.rs:16:8 + | +LL | if <*const _>::is_null(fn_ptr as *const ()) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value + +warning: function pointers are not nullable, so checking them for null will always return false + --> $DIR/fn_null_check.rs:18:8 + | +LL | if (fn_ptr as *mut fn() as *const fn() as *const ()).is_null() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value + +warning: function pointers are not nullable, so checking them for null will always return false + --> $DIR/fn_null_check.rs:20:8 + | +LL | if (fn_ptr as fn() as *const ()).is_null() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value + +warning: 8 warnings emitted + From c0fbeeab1697d52b47fad4fff73ac3f334b85562 Mon Sep 17 00:00:00 2001 From: Urgau Date: Wed, 17 May 2023 20:01:36 +0200 Subject: [PATCH 3/3] Drop uplifted `clippy::fn_null_check` --- .../clippy/clippy_lints/src/declared_lints.rs | 1 - .../clippy/clippy_lints/src/fn_null_check.rs | 102 ---------------- src/tools/clippy/clippy_lints/src/lib.rs | 2 - .../clippy/clippy_lints/src/renamed_lints.rs | 1 + src/tools/clippy/tests/ui/fn_null_check.rs | 22 ---- .../clippy/tests/ui/fn_null_check.stderr | 43 ------- src/tools/clippy/tests/ui/rename.fixed | 2 + src/tools/clippy/tests/ui/rename.rs | 2 + src/tools/clippy/tests/ui/rename.stderr | 112 +++++++++--------- 9 files changed, 64 insertions(+), 223 deletions(-) delete mode 100644 src/tools/clippy/clippy_lints/src/fn_null_check.rs delete mode 100644 src/tools/clippy/tests/ui/fn_null_check.rs delete mode 100644 src/tools/clippy/tests/ui/fn_null_check.stderr diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs index 9d9ee6ba30792..b60f0738f6497 100644 --- a/src/tools/clippy/clippy_lints/src/declared_lints.rs +++ b/src/tools/clippy/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/src/tools/clippy/clippy_lints/src/fn_null_check.rs b/src/tools/clippy/clippy_lints/src/fn_null_check.rs deleted file mode 100644 index 521045a9fed8f..0000000000000 --- a/src/tools/clippy/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 = /* 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` 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 * ).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 * ) == (0 as ) - ExprKind::Cast(cast_expr, _) if is_integer_literal(cast_expr, 0) => { - lint_expr(cx, expr); - }, - - // Catching: - // (fn_ptr as * ) == std::ptr::null() - ExprKind::Call(func, []) if is_path_diagnostic_item(cx, func, sym::ptr_null) => { - lint_expr(cx, expr); - }, - - // Catching: - // (fn_ptr as * ) == - _ if matches!(constant(cx, cx.typeck_results(), to_check), Some(Constant::RawPtr(0))) => { - lint_expr(cx, expr); - }, - - _ => {}, - } - }, - _ => {}, - } - } -} diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs index 87329ee5e14ac..365cc4c59ad46 100644 --- a/src/tools/clippy/clippy_lints/src/lib.rs +++ b/src/tools/clippy/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/src/tools/clippy/clippy_lints/src/renamed_lints.rs b/src/tools/clippy/clippy_lints/src/renamed_lints.rs index cbcd11debfd76..d24215c229245 100644 --- a/src/tools/clippy/clippy_lints/src/renamed_lints.rs +++ b/src/tools/clippy/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"), diff --git a/src/tools/clippy/tests/ui/fn_null_check.rs b/src/tools/clippy/tests/ui/fn_null_check.rs deleted file mode 100644 index dfdea100c8fd7..0000000000000 --- a/src/tools/clippy/tests/ui/fn_null_check.rs +++ /dev/null @@ -1,22 +0,0 @@ -#![allow(unused)] -#![warn(clippy::fn_null_check)] -#![allow(clippy::cmp_null)] -#![allow(clippy::needless_if)] -#![allow(clippy::ptr_eq)] -#![allow(clippy::zero_ptr)] - -pub const ZPTR: *const () = 0 as *const _; -pub const NOT_ZPTR: *const () = 1 as *const _; - -fn main() { - let fn_ptr = main; - - if (fn_ptr as *mut ()).is_null() {} - if (fn_ptr as *const u8).is_null() {} - if (fn_ptr as *const ()) == std::ptr::null() {} - if (fn_ptr as *const ()) == (0 as *const ()) {} - if (fn_ptr as *const ()) == ZPTR {} - - // no lint - if (fn_ptr as *const ()) == NOT_ZPTR {} -} diff --git a/src/tools/clippy/tests/ui/fn_null_check.stderr b/src/tools/clippy/tests/ui/fn_null_check.stderr deleted file mode 100644 index 5b9f48a961caf..0000000000000 --- a/src/tools/clippy/tests/ui/fn_null_check.stderr +++ /dev/null @@ -1,43 +0,0 @@ -error: function pointer assumed to be nullable, even though it isn't - --> $DIR/fn_null_check.rs:14:8 - | -LL | if (fn_ptr as *mut ()).is_null() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: try wrapping your function pointer type in `Option` instead, and using `is_none` to check for null pointer value - = note: `-D clippy::fn-null-check` implied by `-D warnings` - -error: function pointer assumed to be nullable, even though it isn't - --> $DIR/fn_null_check.rs:15:8 - | -LL | if (fn_ptr as *const u8).is_null() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: try wrapping your function pointer type in `Option` instead, and using `is_none` to check for null pointer value - -error: function pointer assumed to be nullable, even though it isn't - --> $DIR/fn_null_check.rs:16:8 - | -LL | if (fn_ptr as *const ()) == std::ptr::null() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: try wrapping your function pointer type in `Option` instead, and using `is_none` to check for null pointer value - -error: function pointer assumed to be nullable, even though it isn't - --> $DIR/fn_null_check.rs:17:8 - | -LL | if (fn_ptr as *const ()) == (0 as *const ()) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: try wrapping your function pointer type in `Option` instead, and using `is_none` to check for null pointer value - -error: function pointer assumed to be nullable, even though it isn't - --> $DIR/fn_null_check.rs:18:8 - | -LL | if (fn_ptr as *const ()) == ZPTR {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: try wrapping your function pointer type in `Option` instead, and using `is_none` to check for null pointer value - -error: aborting due to 5 previous errors - diff --git a/src/tools/clippy/tests/ui/rename.fixed b/src/tools/clippy/tests/ui/rename.fixed index b24c83d9a0da2..cab02bb93c9ce 100644 --- a/src/tools/clippy/tests/ui/rename.fixed +++ b/src/tools/clippy/tests/ui/rename.fixed @@ -37,6 +37,7 @@ #![allow(for_loops_over_fallibles)] #![allow(forgetting_copy_types)] #![allow(forgetting_references)] +#![allow(incorrect_fn_null_checks)] #![allow(array_into_iter)] #![allow(invalid_atomic_ordering)] #![allow(invalid_value)] @@ -89,6 +90,7 @@ #![warn(for_loops_over_fallibles)] #![warn(forgetting_copy_types)] #![warn(forgetting_references)] +#![warn(incorrect_fn_null_checks)] #![warn(array_into_iter)] #![warn(invalid_atomic_ordering)] #![warn(invalid_value)] diff --git a/src/tools/clippy/tests/ui/rename.rs b/src/tools/clippy/tests/ui/rename.rs index baa6345a64f83..e5e31452149dd 100644 --- a/src/tools/clippy/tests/ui/rename.rs +++ b/src/tools/clippy/tests/ui/rename.rs @@ -37,6 +37,7 @@ #![allow(for_loops_over_fallibles)] #![allow(forgetting_copy_types)] #![allow(forgetting_references)] +#![allow(incorrect_fn_null_checks)] #![allow(array_into_iter)] #![allow(invalid_atomic_ordering)] #![allow(invalid_value)] @@ -89,6 +90,7 @@ #![warn(clippy::for_loops_over_fallibles)] #![warn(clippy::forget_copy)] #![warn(clippy::forget_ref)] +#![warn(clippy::fn_null_check)] #![warn(clippy::into_iter_on_array)] #![warn(clippy::invalid_atomic_ordering)] #![warn(clippy::invalid_ref)] diff --git a/src/tools/clippy/tests/ui/rename.stderr b/src/tools/clippy/tests/ui/rename.stderr index ae25c3b46bd24..783608a084102 100644 --- a/src/tools/clippy/tests/ui/rename.stderr +++ b/src/tools/clippy/tests/ui/rename.stderr @@ -1,5 +1,5 @@ error: lint `clippy::almost_complete_letter_range` has been renamed to `clippy::almost_complete_range` - --> $DIR/rename.rs:52:9 + --> $DIR/rename.rs:53:9 | LL | #![warn(clippy::almost_complete_letter_range)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::almost_complete_range` @@ -7,310 +7,316 @@ LL | #![warn(clippy::almost_complete_letter_range)] = note: `-D renamed-and-removed-lints` implied by `-D warnings` error: lint `clippy::blacklisted_name` has been renamed to `clippy::disallowed_names` - --> $DIR/rename.rs:53:9 + --> $DIR/rename.rs:54:9 | LL | #![warn(clippy::blacklisted_name)] | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_names` error: lint `clippy::block_in_if_condition_expr` has been renamed to `clippy::blocks_in_if_conditions` - --> $DIR/rename.rs:54:9 + --> $DIR/rename.rs:55:9 | LL | #![warn(clippy::block_in_if_condition_expr)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions` error: lint `clippy::block_in_if_condition_stmt` has been renamed to `clippy::blocks_in_if_conditions` - --> $DIR/rename.rs:55:9 + --> $DIR/rename.rs:56:9 | LL | #![warn(clippy::block_in_if_condition_stmt)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions` error: lint `clippy::box_vec` has been renamed to `clippy::box_collection` - --> $DIR/rename.rs:56:9 + --> $DIR/rename.rs:57:9 | LL | #![warn(clippy::box_vec)] | ^^^^^^^^^^^^^^^ help: use the new name: `clippy::box_collection` error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes` - --> $DIR/rename.rs:57:9 + --> $DIR/rename.rs:58:9 | LL | #![warn(clippy::const_static_lifetime)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes` error: lint `clippy::cyclomatic_complexity` has been renamed to `clippy::cognitive_complexity` - --> $DIR/rename.rs:58:9 + --> $DIR/rename.rs:59:9 | LL | #![warn(clippy::cyclomatic_complexity)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::cognitive_complexity` error: lint `clippy::derive_hash_xor_eq` has been renamed to `clippy::derived_hash_with_manual_eq` - --> $DIR/rename.rs:59:9 + --> $DIR/rename.rs:60:9 | LL | #![warn(clippy::derive_hash_xor_eq)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::derived_hash_with_manual_eq` error: lint `clippy::disallowed_method` has been renamed to `clippy::disallowed_methods` - --> $DIR/rename.rs:60:9 + --> $DIR/rename.rs:61:9 | LL | #![warn(clippy::disallowed_method)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_methods` error: lint `clippy::disallowed_type` has been renamed to `clippy::disallowed_types` - --> $DIR/rename.rs:61:9 + --> $DIR/rename.rs:62:9 | LL | #![warn(clippy::disallowed_type)] | ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_types` error: lint `clippy::eval_order_dependence` has been renamed to `clippy::mixed_read_write_in_expression` - --> $DIR/rename.rs:62:9 + --> $DIR/rename.rs:63:9 | LL | #![warn(clippy::eval_order_dependence)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::mixed_read_write_in_expression` error: lint `clippy::identity_conversion` has been renamed to `clippy::useless_conversion` - --> $DIR/rename.rs:63:9 + --> $DIR/rename.rs:64:9 | LL | #![warn(clippy::identity_conversion)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::useless_conversion` error: lint `clippy::if_let_some_result` has been renamed to `clippy::match_result_ok` - --> $DIR/rename.rs:64:9 + --> $DIR/rename.rs:65:9 | LL | #![warn(clippy::if_let_some_result)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok` error: lint `clippy::integer_arithmetic` has been renamed to `clippy::arithmetic_side_effects` - --> $DIR/rename.rs:65:9 + --> $DIR/rename.rs:66:9 | LL | #![warn(clippy::integer_arithmetic)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::arithmetic_side_effects` error: lint `clippy::logic_bug` has been renamed to `clippy::overly_complex_bool_expr` - --> $DIR/rename.rs:66:9 + --> $DIR/rename.rs:67:9 | LL | #![warn(clippy::logic_bug)] | ^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::overly_complex_bool_expr` error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default` - --> $DIR/rename.rs:67:9 + --> $DIR/rename.rs:68:9 | LL | #![warn(clippy::new_without_default_derive)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default` error: lint `clippy::option_and_then_some` has been renamed to `clippy::bind_instead_of_map` - --> $DIR/rename.rs:68:9 + --> $DIR/rename.rs:69:9 | LL | #![warn(clippy::option_and_then_some)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::bind_instead_of_map` error: lint `clippy::option_expect_used` has been renamed to `clippy::expect_used` - --> $DIR/rename.rs:69:9 + --> $DIR/rename.rs:70:9 | LL | #![warn(clippy::option_expect_used)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used` error: lint `clippy::option_map_unwrap_or` has been renamed to `clippy::map_unwrap_or` - --> $DIR/rename.rs:70:9 + --> $DIR/rename.rs:71:9 | LL | #![warn(clippy::option_map_unwrap_or)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or` error: lint `clippy::option_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or` - --> $DIR/rename.rs:71:9 + --> $DIR/rename.rs:72:9 | LL | #![warn(clippy::option_map_unwrap_or_else)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or` error: lint `clippy::option_unwrap_used` has been renamed to `clippy::unwrap_used` - --> $DIR/rename.rs:72:9 + --> $DIR/rename.rs:73:9 | LL | #![warn(clippy::option_unwrap_used)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used` error: lint `clippy::ref_in_deref` has been renamed to `clippy::needless_borrow` - --> $DIR/rename.rs:73:9 + --> $DIR/rename.rs:74:9 | LL | #![warn(clippy::ref_in_deref)] | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::needless_borrow` error: lint `clippy::result_expect_used` has been renamed to `clippy::expect_used` - --> $DIR/rename.rs:74:9 + --> $DIR/rename.rs:75:9 | LL | #![warn(clippy::result_expect_used)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used` error: lint `clippy::result_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or` - --> $DIR/rename.rs:75:9 + --> $DIR/rename.rs:76:9 | LL | #![warn(clippy::result_map_unwrap_or_else)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or` error: lint `clippy::result_unwrap_used` has been renamed to `clippy::unwrap_used` - --> $DIR/rename.rs:76:9 + --> $DIR/rename.rs:77:9 | LL | #![warn(clippy::result_unwrap_used)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used` error: lint `clippy::single_char_push_str` has been renamed to `clippy::single_char_add_str` - --> $DIR/rename.rs:77:9 + --> $DIR/rename.rs:78:9 | LL | #![warn(clippy::single_char_push_str)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::single_char_add_str` error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions` - --> $DIR/rename.rs:78:9 + --> $DIR/rename.rs:79:9 | LL | #![warn(clippy::stutter)] | ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions` error: lint `clippy::to_string_in_display` has been renamed to `clippy::recursive_format_impl` - --> $DIR/rename.rs:79:9 + --> $DIR/rename.rs:80:9 | LL | #![warn(clippy::to_string_in_display)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::recursive_format_impl` error: lint `clippy::zero_width_space` has been renamed to `clippy::invisible_characters` - --> $DIR/rename.rs:80:9 + --> $DIR/rename.rs:81:9 | LL | #![warn(clippy::zero_width_space)] | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters` error: lint `clippy::cast_ref_to_mut` has been renamed to `cast_ref_to_mut` - --> $DIR/rename.rs:81:9 + --> $DIR/rename.rs:82:9 | LL | #![warn(clippy::cast_ref_to_mut)] | ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `cast_ref_to_mut` error: lint `clippy::clone_double_ref` has been renamed to `suspicious_double_ref_op` - --> $DIR/rename.rs:82:9 + --> $DIR/rename.rs:83:9 | LL | #![warn(clippy::clone_double_ref)] | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `suspicious_double_ref_op` error: lint `clippy::cmp_nan` has been renamed to `invalid_nan_comparisons` - --> $DIR/rename.rs:83:9 + --> $DIR/rename.rs:84:9 | LL | #![warn(clippy::cmp_nan)] | ^^^^^^^^^^^^^^^ help: use the new name: `invalid_nan_comparisons` error: lint `clippy::drop_bounds` has been renamed to `drop_bounds` - --> $DIR/rename.rs:84:9 + --> $DIR/rename.rs:85:9 | LL | #![warn(clippy::drop_bounds)] | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds` error: lint `clippy::drop_copy` has been renamed to `dropping_copy_types` - --> $DIR/rename.rs:85:9 + --> $DIR/rename.rs:86:9 | LL | #![warn(clippy::drop_copy)] | ^^^^^^^^^^^^^^^^^ help: use the new name: `dropping_copy_types` error: lint `clippy::drop_ref` has been renamed to `dropping_references` - --> $DIR/rename.rs:86:9 + --> $DIR/rename.rs:87:9 | LL | #![warn(clippy::drop_ref)] | ^^^^^^^^^^^^^^^^ help: use the new name: `dropping_references` error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles` - --> $DIR/rename.rs:87:9 + --> $DIR/rename.rs:88:9 | LL | #![warn(clippy::for_loop_over_option)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles` error: lint `clippy::for_loop_over_result` has been renamed to `for_loops_over_fallibles` - --> $DIR/rename.rs:88:9 + --> $DIR/rename.rs:89:9 | LL | #![warn(clippy::for_loop_over_result)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles` error: lint `clippy::for_loops_over_fallibles` has been renamed to `for_loops_over_fallibles` - --> $DIR/rename.rs:89:9 + --> $DIR/rename.rs:90:9 | LL | #![warn(clippy::for_loops_over_fallibles)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles` error: lint `clippy::forget_copy` has been renamed to `forgetting_copy_types` - --> $DIR/rename.rs:90:9 + --> $DIR/rename.rs:91:9 | LL | #![warn(clippy::forget_copy)] | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_copy_types` error: lint `clippy::forget_ref` has been renamed to `forgetting_references` - --> $DIR/rename.rs:91:9 + --> $DIR/rename.rs:92:9 | LL | #![warn(clippy::forget_ref)] | ^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_references` +error: lint `clippy::fn_null_check` has been renamed to `incorrect_fn_null_checks` + --> $DIR/rename.rs:93:9 + | +LL | #![warn(clippy::fn_null_check)] + | ^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `incorrect_fn_null_checks` + error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter` - --> $DIR/rename.rs:92:9 + --> $DIR/rename.rs:94:9 | LL | #![warn(clippy::into_iter_on_array)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter` error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering` - --> $DIR/rename.rs:93:9 + --> $DIR/rename.rs:95:9 | LL | #![warn(clippy::invalid_atomic_ordering)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering` error: lint `clippy::invalid_ref` has been renamed to `invalid_value` - --> $DIR/rename.rs:94:9 + --> $DIR/rename.rs:96:9 | LL | #![warn(clippy::invalid_ref)] | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value` error: lint `clippy::invalid_utf8_in_unchecked` has been renamed to `invalid_from_utf8_unchecked` - --> $DIR/rename.rs:95:9 + --> $DIR/rename.rs:97:9 | LL | #![warn(clippy::invalid_utf8_in_unchecked)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_from_utf8_unchecked` error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop` - --> $DIR/rename.rs:96:9 + --> $DIR/rename.rs:98:9 | LL | #![warn(clippy::let_underscore_drop)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `let_underscore_drop` error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums` - --> $DIR/rename.rs:97:9 + --> $DIR/rename.rs:99:9 | LL | #![warn(clippy::mem_discriminant_non_enum)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums` error: lint `clippy::panic_params` has been renamed to `non_fmt_panics` - --> $DIR/rename.rs:98:9 + --> $DIR/rename.rs:100:9 | LL | #![warn(clippy::panic_params)] | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics` error: lint `clippy::positional_named_format_parameters` has been renamed to `named_arguments_used_positionally` - --> $DIR/rename.rs:99:9 + --> $DIR/rename.rs:101:9 | LL | #![warn(clippy::positional_named_format_parameters)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `named_arguments_used_positionally` error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `temporary_cstring_as_ptr` - --> $DIR/rename.rs:100:9 + --> $DIR/rename.rs:102:9 | LL | #![warn(clippy::temporary_cstring_as_ptr)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr` error: lint `clippy::undropped_manually_drops` has been renamed to `undropped_manually_drops` - --> $DIR/rename.rs:101:9 + --> $DIR/rename.rs:103:9 | LL | #![warn(clippy::undropped_manually_drops)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `undropped_manually_drops` error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints` - --> $DIR/rename.rs:102:9 + --> $DIR/rename.rs:104:9 | LL | #![warn(clippy::unknown_clippy_lints)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints` error: lint `clippy::unused_label` has been renamed to `unused_labels` - --> $DIR/rename.rs:103:9 + --> $DIR/rename.rs:105:9 | LL | #![warn(clippy::unused_label)] | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels` -error: aborting due to 52 previous errors +error: aborting due to 53 previous errors