mirror of
https://github.com/rust-lang/rust-clippy
synced 2025-02-18 15:08:47 +00:00
Handle null pointer constness cast through methods
This covers two cases: - `core::ptr::null::<T>().cast_mut()` -> `core::ptr::null_mut::<T>()` - `core::ptr::null_mut::<T>().cast_const()` -> `core::ptr::null::<T>()`
This commit is contained in:
parent
9e9526c6ab
commit
30608732c2
5 changed files with 62 additions and 2 deletions
|
@ -419,6 +419,8 @@ declare_clippy_lint! {
|
||||||
/// let ptr = mut_ptr as *const u32;
|
/// let ptr = mut_ptr as *const u32;
|
||||||
/// let ptr1 = std::ptr::null::<u32>() as *mut u32;
|
/// let ptr1 = std::ptr::null::<u32>() as *mut u32;
|
||||||
/// let ptr2 = std::ptr::null_mut::<u32>() as *const 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:
|
/// Use instead:
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
|
@ -427,6 +429,8 @@ declare_clippy_lint! {
|
||||||
/// let ptr = mut_ptr.cast_const();
|
/// let ptr = mut_ptr.cast_const();
|
||||||
/// let ptr1 = std::ptr::null_mut::<u32>();
|
/// let ptr1 = std::ptr::null_mut::<u32>();
|
||||||
/// let ptr2 = std::ptr::null::<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"]
|
#[clippy::version = "1.72.0"]
|
||||||
pub PTR_CAST_CONSTNESS,
|
pub PTR_CAST_CONSTNESS,
|
||||||
|
@ -813,6 +817,7 @@ impl<'tcx> LateLintPass<'tcx> for Casts {
|
||||||
char_lit_as_u8::check(cx, expr);
|
char_lit_as_u8::check(cx, expr);
|
||||||
ptr_as_ptr::check(cx, expr, &self.msrv);
|
ptr_as_ptr::check(cx, expr, &self.msrv);
|
||||||
cast_slice_different_sizes::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);
|
extract_msrv_attr!(LateContext);
|
||||||
|
|
|
@ -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,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -74,10 +74,14 @@ fn null_pointers() {
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
let _ = std::ptr::null_mut::<String>();
|
let _ = std::ptr::null_mut::<String>();
|
||||||
let _ = std::ptr::null::<u32>();
|
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
|
// Make sure the lint is triggered inside a macro
|
||||||
let _ = inline!(std::ptr::null_mut::<u32>());
|
let _ = inline!(std::ptr::null_mut::<u32>());
|
||||||
|
let _ = inline!(std::ptr::null_mut::<u32>());
|
||||||
|
|
||||||
// Do not lint inside macros from external crates
|
// Do not lint inside macros from external crates
|
||||||
let _ = external!(ptr::null::<u32>() as *mut u32);
|
let _ = external!(ptr::null::<u32>() as *mut u32);
|
||||||
|
let _ = external!(ptr::null::<u32>().cast_mut());
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,10 +74,14 @@ fn null_pointers() {
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
let _ = ptr::null::<String>() as *mut String;
|
let _ = ptr::null::<String>() as *mut String;
|
||||||
let _ = ptr::null_mut::<u32>() as *const u32;
|
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
|
// Make sure the lint is triggered inside a macro
|
||||||
let _ = inline!(ptr::null::<u32>() as *mut u32);
|
let _ = inline!(ptr::null::<u32>() as *mut u32);
|
||||||
|
let _ = inline!(ptr::null::<u32>().cast_mut());
|
||||||
|
|
||||||
// Do not lint inside macros from external crates
|
// Do not lint inside macros from external crates
|
||||||
let _ = external!(ptr::null::<u32>() as *mut u32);
|
let _ = external!(ptr::null::<u32>() as *mut u32);
|
||||||
|
let _ = external!(ptr::null::<u32>().cast_mut());
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
LL | let _ = ptr::null_mut::<u32>() as *const u32;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `null()` directly instead: `std::ptr::null::<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
|
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);
|
LL | let _ = inline!(ptr::null::<u32>() as *mut u32);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `null_mut()` directly instead: `std::ptr::null_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)
|
= 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
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue