diff options
| -rw-r--r-- | clippy_lints/src/casts/mod.rs | 5 | ||||
| -rw-r--r-- | clippy_lints/src/casts/ptr_cast_constness.rs | 27 | ||||
| -rw-r--r-- | tests/ui/ptr_cast_constness.fixed | 4 | ||||
| -rw-r--r-- | tests/ui/ptr_cast_constness.rs | 4 | ||||
| -rw-r--r-- | tests/ui/ptr_cast_constness.stderr | 24 |
5 files changed, 62 insertions, 2 deletions
diff --git a/clippy_lints/src/casts/mod.rs b/clippy_lints/src/casts/mod.rs index fccddf558ed..39f50a347c0 100644 --- a/clippy_lints/src/casts/mod.rs +++ b/clippy_lints/src/casts/mod.rs @@ -419,6 +419,8 @@ declare_clippy_lint! { /// let ptr = mut_ptr as *const u32; /// let ptr1 = std::ptr::null::<u32>() as *mut u32; /// let ptr2 = std::ptr::null_mut::<u32>() as *const u32; + /// let ptr3 = std::ptr::null::<u32>().cast_mut(); + /// let ptr4 = std::ptr::null_mut::<u32>().cast_const(); /// ``` /// Use instead: /// ```no_run @@ -427,6 +429,8 @@ declare_clippy_lint! { /// let ptr = mut_ptr.cast_const(); /// let ptr1 = std::ptr::null_mut::<u32>(); /// let ptr2 = std::ptr::null::<u32>(); + /// let ptr3 = std::ptr::null_mut::<u32>(); + /// let ptr4 = std::ptr::null::<u32>(); /// ``` #[clippy::version = "1.72.0"] pub PTR_CAST_CONSTNESS, @@ -813,6 +817,7 @@ impl<'tcx> LateLintPass<'tcx> for Casts { char_lit_as_u8::check(cx, expr); ptr_as_ptr::check(cx, expr, &self.msrv); cast_slice_different_sizes::check(cx, expr, &self.msrv); + ptr_cast_constness::check_null_ptr_cast_method(cx, expr); } extract_msrv_attr!(LateContext); diff --git a/clippy_lints/src/casts/ptr_cast_constness.rs b/clippy_lints/src/casts/ptr_cast_constness.rs index 98bc38ed134..7518dd2435a 100644 --- a/clippy_lints/src/casts/ptr_cast_constness.rs +++ b/clippy_lints/src/casts/ptr_cast_constness.rs @@ -71,3 +71,30 @@ pub(super) fn check<'tcx>( } } } + +pub(super) fn check_null_ptr_cast_method(cx: &LateContext<'_>, expr: &Expr<'_>) { + if let ExprKind::MethodCall(method, cast_expr, [], _) = expr.kind + && let ExprKind::Call(func, []) = cast_expr.kind + && let ExprKind::Path(QPath::Resolved(None, path)) = func.kind + && let Some(defid) = path.res.opt_def_id() + && let method = match (cx.tcx.get_diagnostic_name(defid), method.ident.as_str()) { + (Some(sym::ptr_null), "cast_mut") => "null_mut", + (Some(sym::ptr_null_mut), "cast_const") => "null", + _ => return, + } + && let Some(prefix) = std_or_core(cx) + && let mut app = Applicability::MachineApplicable + && let sugg = format!("{}", Sugg::hir_with_applicability(cx, cast_expr, "_", &mut app)) + && let Some((_, after_lt)) = sugg.split_once("::<") + { + span_lint_and_sugg( + cx, + PTR_CAST_CONSTNESS, + expr.span, + "changing constness of a null pointer", + format!("use `{method}()` directly instead"), + format!("{prefix}::ptr::{method}::<{after_lt}"), + app, + ); + } +} diff --git a/tests/ui/ptr_cast_constness.fixed b/tests/ui/ptr_cast_constness.fixed index 5bf9a30b016..9a5272c7adc 100644 --- a/tests/ui/ptr_cast_constness.fixed +++ b/tests/ui/ptr_cast_constness.fixed @@ -74,10 +74,14 @@ fn null_pointers() { use std::ptr; let _ = std::ptr::null_mut::<String>(); let _ = std::ptr::null::<u32>(); + let _ = std::ptr::null_mut::<u32>(); + let _ = std::ptr::null::<u32>(); // Make sure the lint is triggered inside a macro let _ = inline!(std::ptr::null_mut::<u32>()); + let _ = inline!(std::ptr::null_mut::<u32>()); // Do not lint inside macros from external crates let _ = external!(ptr::null::<u32>() as *mut u32); + let _ = external!(ptr::null::<u32>().cast_mut()); } diff --git a/tests/ui/ptr_cast_constness.rs b/tests/ui/ptr_cast_constness.rs index 2575a5923e1..43ab5f5ba7c 100644 --- a/tests/ui/ptr_cast_constness.rs +++ b/tests/ui/ptr_cast_constness.rs @@ -74,10 +74,14 @@ fn null_pointers() { use std::ptr; let _ = ptr::null::<String>() as *mut String; let _ = ptr::null_mut::<u32>() as *const u32; + let _ = ptr::null::<u32>().cast_mut(); + let _ = ptr::null_mut::<u32>().cast_const(); // Make sure the lint is triggered inside a macro let _ = inline!(ptr::null::<u32>() as *mut u32); + let _ = inline!(ptr::null::<u32>().cast_mut()); // Do not lint inside macros from external crates let _ = external!(ptr::null::<u32>() as *mut u32); + let _ = external!(ptr::null::<u32>().cast_mut()); } diff --git a/tests/ui/ptr_cast_constness.stderr b/tests/ui/ptr_cast_constness.stderr index 0806ca62806..a693793a4ae 100644 --- a/tests/ui/ptr_cast_constness.stderr +++ b/tests/ui/ptr_cast_constness.stderr @@ -55,13 +55,33 @@ error: `as` casting to make a mutable null pointer into a const null pointer LL | let _ = ptr::null_mut::<u32>() as *const u32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `null()` directly instead: `std::ptr::null::<u32>()` +error: changing constness of a null pointer + --> tests/ui/ptr_cast_constness.rs:77:13 + | +LL | let _ = ptr::null::<u32>().cast_mut(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `null_mut()` directly instead: `std::ptr::null_mut::<u32>()` + +error: changing constness of a null pointer + --> tests/ui/ptr_cast_constness.rs:78:13 + | +LL | let _ = ptr::null_mut::<u32>().cast_const(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `null()` directly instead: `std::ptr::null::<u32>()` + error: `as` casting to make a const null pointer into a mutable null pointer - --> tests/ui/ptr_cast_constness.rs:79:21 + --> tests/ui/ptr_cast_constness.rs:81:21 | LL | let _ = inline!(ptr::null::<u32>() as *mut u32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `null_mut()` directly instead: `std::ptr::null_mut::<u32>()` | = note: this error originates in the macro `__inline_mac_fn_null_pointers` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 10 previous errors +error: changing constness of a null pointer + --> tests/ui/ptr_cast_constness.rs:82:21 + | +LL | let _ = inline!(ptr::null::<u32>().cast_mut()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `null_mut()` directly instead: `std::ptr::null_mut::<u32>()` + | + = note: this error originates in the macro `__inline_mac_fn_null_pointers` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 13 previous errors |
