Skip to content

Uplift clippy::fn_null_check lint #111717

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jul 11, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions compiler/rustc_lint/messages.ftl
Original file line number Diff line number Diff line change
@@ -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
112 changes: 112 additions & 0 deletions compiler/rustc_lint/src/fn_null_check.rs
Original file line number Diff line number Diff line change
@@ -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:
// <*<const/mut> <ty>>::is_null(fn_ptr as *<const/mut> <ty>)
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 *<const/mut> <ty>).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 *<const/mut> <ty>) == (0 as <ty>)
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 *<const/mut> <ty>) == 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)
},

_ => {},
}
}
_ => {}
}
}
}
3 changes: 3 additions & 0 deletions compiler/rustc_lint/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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,
6 changes: 6 additions & 0 deletions compiler/rustc_lint/src/lints.rs
Original file line number Diff line number Diff line change
@@ -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)]
2 changes: 2 additions & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
@@ -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,
1 change: 1 addition & 0 deletions library/core/src/ptr/const_ptr.rs
Original file line number Diff line number Diff line change
@@ -30,6 +30,7 @@ impl<T: ?Sized> *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]
1 change: 1 addition & 0 deletions library/core/src/ptr/mut_ptr.rs
Original file line number Diff line number Diff line change
@@ -29,6 +29,7 @@ impl<T: ?Sized> *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]
1 change: 0 additions & 1 deletion src/tools/clippy/clippy_lints/src/declared_lints.rs
Original file line number Diff line number Diff line change
@@ -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,
102 changes: 0 additions & 102 deletions src/tools/clippy/clippy_lints/src/fn_null_check.rs

This file was deleted.

2 changes: 0 additions & 2 deletions src/tools/clippy/clippy_lints/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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));
1 change: 1 addition & 0 deletions src/tools/clippy/clippy_lints/src/renamed_lints.rs
Original file line number Diff line number Diff line change
@@ -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"),
22 changes: 0 additions & 22 deletions src/tools/clippy/tests/ui/fn_null_check.rs

This file was deleted.

43 changes: 0 additions & 43 deletions src/tools/clippy/tests/ui/fn_null_check.stderr

This file was deleted.

2 changes: 2 additions & 0 deletions src/tools/clippy/tests/ui/rename.fixed
Original file line number Diff line number Diff line change
@@ -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)]
2 changes: 2 additions & 0 deletions src/tools/clippy/tests/ui/rename.rs
Original file line number Diff line number Diff line change
@@ -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)]
112 changes: 59 additions & 53 deletions src/tools/clippy/tests/ui/rename.stderr
Original file line number Diff line number Diff line change
@@ -1,316 +1,322 @@
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`
|
= 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

30 changes: 30 additions & 0 deletions tests/ui/lint/fn_null_check.rs
Original file line number Diff line number Diff line change
@@ -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 {}
}
67 changes: 67 additions & 0 deletions tests/ui/lint/fn_null_check.stderr
Original file line number Diff line number Diff line change
@@ -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