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:
bors 2023-12-06 13:53:07 +00:00
commit 2793e8d103
4 changed files with 426 additions and 5 deletions

View file

@ -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,
);
}

View file

@ -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()
}
}

View file

@ -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 _
}
}

View file

@ -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