Auto merge of #11913 - KisaragiEffective:fix/ptr-as-ptr-with-null, r=llogiq
fix(ptr_as_ptr): handle `std::ptr::null{_mut}` close rust-lang#11066 close rust-lang#11665 close rust-lang#11911 *Please write a short comment explaining your change (or "none" for internal only changes)* changelog: [`ptr_as_ptr`]: handle `std::ptr::null` and `std::ptr::null_mut`
This commit is contained in:
commit
2793e8d103
@ -3,12 +3,29 @@
|
||||
use clippy_utils::source::snippet_with_applicability;
|
||||
use clippy_utils::sugg::Sugg;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{Expr, ExprKind, Mutability, TyKind};
|
||||
use rustc_hir::{Expr, ExprKind, Mutability, QPath, TyKind};
|
||||
use rustc_hir_pretty::qpath_to_string;
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_middle::ty::{self, TypeAndMut};
|
||||
use rustc_span::sym;
|
||||
|
||||
use super::PTR_AS_PTR;
|
||||
|
||||
enum OmitFollowedCastReason<'a> {
|
||||
None,
|
||||
Null(&'a QPath<'a>),
|
||||
NullMut(&'a QPath<'a>),
|
||||
}
|
||||
|
||||
impl OmitFollowedCastReason<'_> {
|
||||
fn corresponding_item(&self) -> Option<&QPath<'_>> {
|
||||
match self {
|
||||
OmitFollowedCastReason::None => None,
|
||||
OmitFollowedCastReason::Null(x) | OmitFollowedCastReason::NullMut(x) => Some(*x),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: &Msrv) {
|
||||
if !msrv.meets(msrvs::POINTER_CAST) {
|
||||
return;
|
||||
@ -25,7 +42,6 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: &Msrv) {
|
||||
&& to_pointee_ty.is_sized(cx.tcx, cx.param_env)
|
||||
{
|
||||
let mut app = Applicability::MachineApplicable;
|
||||
let cast_expr_sugg = Sugg::hir_with_applicability(cx, cast_expr, "_", &mut app);
|
||||
let turbofish = match &cast_to_hir_ty.kind {
|
||||
TyKind::Infer => String::new(),
|
||||
TyKind::Ptr(mut_ty) => {
|
||||
@ -41,13 +57,44 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: &Msrv) {
|
||||
_ => return,
|
||||
};
|
||||
|
||||
// following `cast` does not compile because it fails to infer what type is expected
|
||||
// as type argument to `std::ptr::ptr_null` or `std::ptr::ptr_null_mut`, so
|
||||
// we omit following `cast`:
|
||||
let omit_cast = if let ExprKind::Call(func, []) = cast_expr.kind
|
||||
&& let ExprKind::Path(ref qpath @ QPath::Resolved(None, path)) = func.kind
|
||||
{
|
||||
let method_defid = path.res.def_id();
|
||||
if cx.tcx.is_diagnostic_item(sym::ptr_null, method_defid) {
|
||||
OmitFollowedCastReason::Null(qpath)
|
||||
} else if cx.tcx.is_diagnostic_item(sym::ptr_null_mut, method_defid) {
|
||||
OmitFollowedCastReason::NullMut(qpath)
|
||||
} else {
|
||||
OmitFollowedCastReason::None
|
||||
}
|
||||
} else {
|
||||
OmitFollowedCastReason::None
|
||||
};
|
||||
|
||||
let (help, final_suggestion) = if let Some(method) = omit_cast.corresponding_item() {
|
||||
// don't force absolute path
|
||||
let method = qpath_to_string(method);
|
||||
("try call directly", format!("{method}{turbofish}()"))
|
||||
} else {
|
||||
let cast_expr_sugg = Sugg::hir_with_applicability(cx, cast_expr, "_", &mut app);
|
||||
|
||||
(
|
||||
"try `pointer::cast`, a safer alternative",
|
||||
format!("{}.cast{turbofish}()", cast_expr_sugg.maybe_par()),
|
||||
)
|
||||
};
|
||||
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
PTR_AS_PTR,
|
||||
expr.span,
|
||||
"`as` casting between raw pointers without changing its mutability",
|
||||
"try `pointer::cast`, a safer alternative",
|
||||
format!("{}.cast{turbofish}()", cast_expr_sugg.maybe_par()),
|
||||
help,
|
||||
final_suggestion,
|
||||
app,
|
||||
);
|
||||
}
|
||||
|
@ -71,3 +71,118 @@ fn _msrv_1_38() {
|
||||
let _ = ptr.cast::<i32>();
|
||||
let _ = mut_ptr.cast::<i32>();
|
||||
}
|
||||
|
||||
#[allow(clippy::unnecessary_cast)]
|
||||
mod null {
|
||||
fn use_path_mut() -> *mut u32 {
|
||||
use std::ptr;
|
||||
ptr::null_mut::<u32>()
|
||||
}
|
||||
|
||||
fn full_path_mut() -> *mut u32 {
|
||||
std::ptr::null_mut::<u32>()
|
||||
}
|
||||
|
||||
fn core_path_mut() -> *mut u32 {
|
||||
use core::ptr;
|
||||
ptr::null_mut::<u32>()
|
||||
}
|
||||
|
||||
fn full_core_path_mut() -> *mut u32 {
|
||||
core::ptr::null_mut::<u32>()
|
||||
}
|
||||
|
||||
fn use_path() -> *const u32 {
|
||||
use std::ptr;
|
||||
ptr::null::<u32>()
|
||||
}
|
||||
|
||||
fn full_path() -> *const u32 {
|
||||
std::ptr::null::<u32>()
|
||||
}
|
||||
|
||||
fn core_path() -> *const u32 {
|
||||
use core::ptr;
|
||||
ptr::null::<u32>()
|
||||
}
|
||||
|
||||
fn full_core_path() -> *const u32 {
|
||||
core::ptr::null::<u32>()
|
||||
}
|
||||
}
|
||||
|
||||
mod null_ptr_infer {
|
||||
fn use_path_mut() -> *mut u32 {
|
||||
use std::ptr;
|
||||
ptr::null_mut()
|
||||
}
|
||||
|
||||
fn full_path_mut() -> *mut u32 {
|
||||
std::ptr::null_mut()
|
||||
}
|
||||
|
||||
fn core_path_mut() -> *mut u32 {
|
||||
use core::ptr;
|
||||
ptr::null_mut()
|
||||
}
|
||||
|
||||
fn full_core_path_mut() -> *mut u32 {
|
||||
core::ptr::null_mut()
|
||||
}
|
||||
|
||||
fn use_path() -> *const u32 {
|
||||
use std::ptr;
|
||||
ptr::null()
|
||||
}
|
||||
|
||||
fn full_path() -> *const u32 {
|
||||
std::ptr::null()
|
||||
}
|
||||
|
||||
fn core_path() -> *const u32 {
|
||||
use core::ptr;
|
||||
ptr::null()
|
||||
}
|
||||
|
||||
fn full_core_path() -> *const u32 {
|
||||
core::ptr::null()
|
||||
}
|
||||
}
|
||||
|
||||
mod null_entire_infer {
|
||||
fn use_path_mut() -> *mut u32 {
|
||||
use std::ptr;
|
||||
ptr::null_mut()
|
||||
}
|
||||
|
||||
fn full_path_mut() -> *mut u32 {
|
||||
std::ptr::null_mut()
|
||||
}
|
||||
|
||||
fn core_path_mut() -> *mut u32 {
|
||||
use core::ptr;
|
||||
ptr::null_mut()
|
||||
}
|
||||
|
||||
fn full_core_path_mut() -> *mut u32 {
|
||||
core::ptr::null_mut()
|
||||
}
|
||||
|
||||
fn use_path() -> *const u32 {
|
||||
use std::ptr;
|
||||
ptr::null()
|
||||
}
|
||||
|
||||
fn full_path() -> *const u32 {
|
||||
std::ptr::null()
|
||||
}
|
||||
|
||||
fn core_path() -> *const u32 {
|
||||
use core::ptr;
|
||||
ptr::null()
|
||||
}
|
||||
|
||||
fn full_core_path() -> *const u32 {
|
||||
core::ptr::null()
|
||||
}
|
||||
}
|
||||
|
@ -71,3 +71,118 @@ fn _msrv_1_38() {
|
||||
let _ = ptr as *const i32;
|
||||
let _ = mut_ptr as *mut i32;
|
||||
}
|
||||
|
||||
#[allow(clippy::unnecessary_cast)]
|
||||
mod null {
|
||||
fn use_path_mut() -> *mut u32 {
|
||||
use std::ptr;
|
||||
ptr::null_mut() as *mut u32
|
||||
}
|
||||
|
||||
fn full_path_mut() -> *mut u32 {
|
||||
std::ptr::null_mut() as *mut u32
|
||||
}
|
||||
|
||||
fn core_path_mut() -> *mut u32 {
|
||||
use core::ptr;
|
||||
ptr::null_mut() as *mut u32
|
||||
}
|
||||
|
||||
fn full_core_path_mut() -> *mut u32 {
|
||||
core::ptr::null_mut() as *mut u32
|
||||
}
|
||||
|
||||
fn use_path() -> *const u32 {
|
||||
use std::ptr;
|
||||
ptr::null() as *const u32
|
||||
}
|
||||
|
||||
fn full_path() -> *const u32 {
|
||||
std::ptr::null() as *const u32
|
||||
}
|
||||
|
||||
fn core_path() -> *const u32 {
|
||||
use core::ptr;
|
||||
ptr::null() as *const u32
|
||||
}
|
||||
|
||||
fn full_core_path() -> *const u32 {
|
||||
core::ptr::null() as *const u32
|
||||
}
|
||||
}
|
||||
|
||||
mod null_ptr_infer {
|
||||
fn use_path_mut() -> *mut u32 {
|
||||
use std::ptr;
|
||||
ptr::null_mut() as *mut _
|
||||
}
|
||||
|
||||
fn full_path_mut() -> *mut u32 {
|
||||
std::ptr::null_mut() as *mut _
|
||||
}
|
||||
|
||||
fn core_path_mut() -> *mut u32 {
|
||||
use core::ptr;
|
||||
ptr::null_mut() as *mut _
|
||||
}
|
||||
|
||||
fn full_core_path_mut() -> *mut u32 {
|
||||
core::ptr::null_mut() as *mut _
|
||||
}
|
||||
|
||||
fn use_path() -> *const u32 {
|
||||
use std::ptr;
|
||||
ptr::null() as *const _
|
||||
}
|
||||
|
||||
fn full_path() -> *const u32 {
|
||||
std::ptr::null() as *const _
|
||||
}
|
||||
|
||||
fn core_path() -> *const u32 {
|
||||
use core::ptr;
|
||||
ptr::null() as *const _
|
||||
}
|
||||
|
||||
fn full_core_path() -> *const u32 {
|
||||
core::ptr::null() as *const _
|
||||
}
|
||||
}
|
||||
|
||||
mod null_entire_infer {
|
||||
fn use_path_mut() -> *mut u32 {
|
||||
use std::ptr;
|
||||
ptr::null_mut() as _
|
||||
}
|
||||
|
||||
fn full_path_mut() -> *mut u32 {
|
||||
std::ptr::null_mut() as _
|
||||
}
|
||||
|
||||
fn core_path_mut() -> *mut u32 {
|
||||
use core::ptr;
|
||||
ptr::null_mut() as _
|
||||
}
|
||||
|
||||
fn full_core_path_mut() -> *mut u32 {
|
||||
core::ptr::null_mut() as _
|
||||
}
|
||||
|
||||
fn use_path() -> *const u32 {
|
||||
use std::ptr;
|
||||
ptr::null() as _
|
||||
}
|
||||
|
||||
fn full_path() -> *const u32 {
|
||||
std::ptr::null() as _
|
||||
}
|
||||
|
||||
fn core_path() -> *const u32 {
|
||||
use core::ptr;
|
||||
ptr::null() as _
|
||||
}
|
||||
|
||||
fn full_core_path() -> *const u32 {
|
||||
core::ptr::null() as _
|
||||
}
|
||||
}
|
||||
|
@ -57,5 +57,149 @@ error: `as` casting between raw pointers without changing its mutability
|
||||
LL | let _ = mut_ptr as *mut i32;
|
||||
| ^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `mut_ptr.cast::<i32>()`
|
||||
|
||||
error: aborting due to 9 previous errors
|
||||
error: `as` casting between raw pointers without changing its mutability
|
||||
--> $DIR/ptr_as_ptr.rs:79:9
|
||||
|
|
||||
LL | ptr::null_mut() as *mut u32
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut::<u32>()`
|
||||
|
||||
error: `as` casting between raw pointers without changing its mutability
|
||||
--> $DIR/ptr_as_ptr.rs:83:9
|
||||
|
|
||||
LL | std::ptr::null_mut() as *mut u32
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null_mut::<u32>()`
|
||||
|
||||
error: `as` casting between raw pointers without changing its mutability
|
||||
--> $DIR/ptr_as_ptr.rs:88:9
|
||||
|
|
||||
LL | ptr::null_mut() as *mut u32
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut::<u32>()`
|
||||
|
||||
error: `as` casting between raw pointers without changing its mutability
|
||||
--> $DIR/ptr_as_ptr.rs:92:9
|
||||
|
|
||||
LL | core::ptr::null_mut() as *mut u32
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null_mut::<u32>()`
|
||||
|
||||
error: `as` casting between raw pointers without changing its mutability
|
||||
--> $DIR/ptr_as_ptr.rs:97:9
|
||||
|
|
||||
LL | ptr::null() as *const u32
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null::<u32>()`
|
||||
|
||||
error: `as` casting between raw pointers without changing its mutability
|
||||
--> $DIR/ptr_as_ptr.rs:101:9
|
||||
|
|
||||
LL | std::ptr::null() as *const u32
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null::<u32>()`
|
||||
|
||||
error: `as` casting between raw pointers without changing its mutability
|
||||
--> $DIR/ptr_as_ptr.rs:106:9
|
||||
|
|
||||
LL | ptr::null() as *const u32
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null::<u32>()`
|
||||
|
||||
error: `as` casting between raw pointers without changing its mutability
|
||||
--> $DIR/ptr_as_ptr.rs:110:9
|
||||
|
|
||||
LL | core::ptr::null() as *const u32
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null::<u32>()`
|
||||
|
||||
error: `as` casting between raw pointers without changing its mutability
|
||||
--> $DIR/ptr_as_ptr.rs:117:9
|
||||
|
|
||||
LL | ptr::null_mut() as *mut _
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut()`
|
||||
|
||||
error: `as` casting between raw pointers without changing its mutability
|
||||
--> $DIR/ptr_as_ptr.rs:121:9
|
||||
|
|
||||
LL | std::ptr::null_mut() as *mut _
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null_mut()`
|
||||
|
||||
error: `as` casting between raw pointers without changing its mutability
|
||||
--> $DIR/ptr_as_ptr.rs:126:9
|
||||
|
|
||||
LL | ptr::null_mut() as *mut _
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut()`
|
||||
|
||||
error: `as` casting between raw pointers without changing its mutability
|
||||
--> $DIR/ptr_as_ptr.rs:130:9
|
||||
|
|
||||
LL | core::ptr::null_mut() as *mut _
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null_mut()`
|
||||
|
||||
error: `as` casting between raw pointers without changing its mutability
|
||||
--> $DIR/ptr_as_ptr.rs:135:9
|
||||
|
|
||||
LL | ptr::null() as *const _
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null()`
|
||||
|
||||
error: `as` casting between raw pointers without changing its mutability
|
||||
--> $DIR/ptr_as_ptr.rs:139:9
|
||||
|
|
||||
LL | std::ptr::null() as *const _
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null()`
|
||||
|
||||
error: `as` casting between raw pointers without changing its mutability
|
||||
--> $DIR/ptr_as_ptr.rs:144:9
|
||||
|
|
||||
LL | ptr::null() as *const _
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null()`
|
||||
|
||||
error: `as` casting between raw pointers without changing its mutability
|
||||
--> $DIR/ptr_as_ptr.rs:148:9
|
||||
|
|
||||
LL | core::ptr::null() as *const _
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null()`
|
||||
|
||||
error: `as` casting between raw pointers without changing its mutability
|
||||
--> $DIR/ptr_as_ptr.rs:155:9
|
||||
|
|
||||
LL | ptr::null_mut() as _
|
||||
| ^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut()`
|
||||
|
||||
error: `as` casting between raw pointers without changing its mutability
|
||||
--> $DIR/ptr_as_ptr.rs:159:9
|
||||
|
|
||||
LL | std::ptr::null_mut() as _
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null_mut()`
|
||||
|
||||
error: `as` casting between raw pointers without changing its mutability
|
||||
--> $DIR/ptr_as_ptr.rs:164:9
|
||||
|
|
||||
LL | ptr::null_mut() as _
|
||||
| ^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut()`
|
||||
|
||||
error: `as` casting between raw pointers without changing its mutability
|
||||
--> $DIR/ptr_as_ptr.rs:168:9
|
||||
|
|
||||
LL | core::ptr::null_mut() as _
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null_mut()`
|
||||
|
||||
error: `as` casting between raw pointers without changing its mutability
|
||||
--> $DIR/ptr_as_ptr.rs:173:9
|
||||
|
|
||||
LL | ptr::null() as _
|
||||
| ^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null()`
|
||||
|
||||
error: `as` casting between raw pointers without changing its mutability
|
||||
--> $DIR/ptr_as_ptr.rs:177:9
|
||||
|
|
||||
LL | std::ptr::null() as _
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null()`
|
||||
|
||||
error: `as` casting between raw pointers without changing its mutability
|
||||
--> $DIR/ptr_as_ptr.rs:182:9
|
||||
|
|
||||
LL | ptr::null() as _
|
||||
| ^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null()`
|
||||
|
||||
error: `as` casting between raw pointers without changing its mutability
|
||||
--> $DIR/ptr_as_ptr.rs:186:9
|
||||
|
|
||||
LL | core::ptr::null() as _
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null()`
|
||||
|
||||
error: aborting due to 33 previous errors
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user