Skip to content

Commit

Permalink
Auto merge of rust-lang#11288 - Centri3:rust-lang#11278, r=Alexendoo
Browse files Browse the repository at this point in the history
[`ptr_as_ptr`]: Take snippet instead of pretty printing type

Fixes rust-lang#11278

changelog: [`ptr_as_ptr`]: Include leading `super`s in suggestion
  • Loading branch information
bors committed Aug 2, 2023
2 parents 97d1cfa + fef85c9 commit 237dd59
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 42 deletions.
64 changes: 35 additions & 29 deletions clippy_lints/src/casts/ptr_as_ptr.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
use std::borrow::Cow;

use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::sugg::Sugg;
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind, Mutability, TyKind};
use rustc_lint::LateContext;
Expand All @@ -16,33 +14,41 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: &Msrv) {
return;
}

if_chain! {
if let ExprKind::Cast(cast_expr, cast_to_hir_ty) = expr.kind;
let (cast_from, cast_to) = (cx.typeck_results().expr_ty(cast_expr), cx.typeck_results().expr_ty(expr));
if let ty::RawPtr(TypeAndMut { mutbl: from_mutbl, .. }) = cast_from.kind();
if let ty::RawPtr(TypeAndMut { ty: to_pointee_ty, mutbl: to_mutbl }) = cast_to.kind();
if matches!((from_mutbl, to_mutbl),
(Mutability::Not, Mutability::Not) | (Mutability::Mut, Mutability::Mut));
if let ExprKind::Cast(cast_expr, cast_to_hir_ty) = expr.kind
&& let (cast_from, cast_to) = (cx.typeck_results().expr_ty(cast_expr), cx.typeck_results().expr_ty(expr))
&& let ty::RawPtr(TypeAndMut { mutbl: from_mutbl, .. }) = cast_from.kind()
&& let ty::RawPtr(TypeAndMut { ty: to_pointee_ty, mutbl: to_mutbl }) = cast_to.kind()
&& matches!((from_mutbl, to_mutbl),
(Mutability::Not, Mutability::Not) | (Mutability::Mut, Mutability::Mut))
// The `U` in `pointer::cast` have to be `Sized`
// as explained here: https://github.com/rust-lang/rust/issues/60602.
if to_pointee_ty.is_sized(cx.tcx, cx.param_env);
then {
let mut applicability = Applicability::MachineApplicable;
let cast_expr_sugg = Sugg::hir_with_applicability(cx, cast_expr, "_", &mut applicability);
let turbofish = match &cast_to_hir_ty.kind {
TyKind::Infer => Cow::Borrowed(""),
TyKind::Ptr(mut_ty) if matches!(mut_ty.ty.kind, TyKind::Infer) => Cow::Borrowed(""),
_ => Cow::Owned(format!("::<{to_pointee_ty}>")),
};
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()),
applicability,
);
}
&& 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) => {
if matches!(mut_ty.ty.kind, TyKind::Infer) {
String::new()
} else {
format!(
"::<{}>",
snippet_with_applicability(cx, mut_ty.ty.span, "/* type */", &mut app)
)
}
},
_ => return,
};

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()),
app,
);
}
}
16 changes: 15 additions & 1 deletion tests/ui/ptr_as_ptr.fixed
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,22 @@

#![warn(clippy::ptr_as_ptr)]

#[macro_use]
extern crate proc_macros;
use proc_macros::{external, inline_macros};

mod issue_11278_a {
#[derive(Debug)]
pub struct T<D: std::fmt::Debug + ?Sized> {
pub p: D,
}
}

mod issue_11278_b {
pub fn f(o: &mut super::issue_11278_a::T<dyn std::fmt::Debug>) -> super::issue_11278_a::T<String> {
// Retain `super`
*unsafe { Box::from_raw(Box::into_raw(Box::new(o)).cast::<super::issue_11278_a::T<String>>()) }
}
}

#[inline_macros]
fn main() {
Expand Down
16 changes: 15 additions & 1 deletion tests/ui/ptr_as_ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,22 @@

#![warn(clippy::ptr_as_ptr)]

#[macro_use]
extern crate proc_macros;
use proc_macros::{external, inline_macros};

mod issue_11278_a {
#[derive(Debug)]
pub struct T<D: std::fmt::Debug + ?Sized> {
pub p: D,
}
}

mod issue_11278_b {
pub fn f(o: &mut super::issue_11278_a::T<dyn std::fmt::Debug>) -> super::issue_11278_a::T<String> {
// Retain `super`
*unsafe { Box::from_raw(Box::into_raw(Box::new(o)) as *mut super::issue_11278_a::T<String>) }
}
}

#[inline_macros]
fn main() {
Expand Down
28 changes: 17 additions & 11 deletions tests/ui/ptr_as_ptr.stderr
Original file line number Diff line number Diff line change
@@ -1,54 +1,60 @@
error: `as` casting between raw pointers without changing its mutability
--> $DIR/ptr_as_ptr.rs:14:13
--> $DIR/ptr_as_ptr.rs:19:33
|
LL | let _ = ptr as *const i32;
| ^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `ptr.cast::<i32>()`
LL | *unsafe { Box::from_raw(Box::into_raw(Box::new(o)) as *mut super::issue_11278_a::T<String>) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `Box::into_raw(Box::new(o)).cast::<super::issue_11278_a::T<String>>()`
|
= note: `-D clippy::ptr-as-ptr` implied by `-D warnings`

error: `as` casting between raw pointers without changing its mutability
--> $DIR/ptr_as_ptr.rs:15:13
--> $DIR/ptr_as_ptr.rs:28:13
|
LL | let _ = ptr as *const i32;
| ^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `ptr.cast::<i32>()`

error: `as` casting between raw pointers without changing its mutability
--> $DIR/ptr_as_ptr.rs:29:13
|
LL | let _ = mut_ptr as *mut i32;
| ^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `mut_ptr.cast::<i32>()`

error: `as` casting between raw pointers without changing its mutability
--> $DIR/ptr_as_ptr.rs:20:17
--> $DIR/ptr_as_ptr.rs:34:17
|
LL | let _ = *ptr_ptr as *const i32;
| ^^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `(*ptr_ptr).cast::<i32>()`

error: `as` casting between raw pointers without changing its mutability
--> $DIR/ptr_as_ptr.rs:33:25
--> $DIR/ptr_as_ptr.rs:47:25
|
LL | let _: *const i32 = ptr as *const _;
| ^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `ptr.cast()`

error: `as` casting between raw pointers without changing its mutability
--> $DIR/ptr_as_ptr.rs:34:23
--> $DIR/ptr_as_ptr.rs:48:23
|
LL | let _: *mut i32 = mut_ptr as _;
| ^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `mut_ptr.cast()`

error: `as` casting between raw pointers without changing its mutability
--> $DIR/ptr_as_ptr.rs:37:21
--> $DIR/ptr_as_ptr.rs:51:21
|
LL | let _ = inline!($ptr as *const i32);
| ^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `$ptr.cast::<i32>()`
|
= note: this error originates in the macro `__inline_mac_fn_main` (in Nightly builds, run with -Z macro-backtrace for more info)

error: `as` casting between raw pointers without changing its mutability
--> $DIR/ptr_as_ptr.rs:58:13
--> $DIR/ptr_as_ptr.rs:72:13
|
LL | let _ = ptr as *const i32;
| ^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `ptr.cast::<i32>()`

error: `as` casting between raw pointers without changing its mutability
--> $DIR/ptr_as_ptr.rs:59:13
--> $DIR/ptr_as_ptr.rs:73:13
|
LL | let _ = mut_ptr as *mut i32;
| ^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `mut_ptr.cast::<i32>()`

error: aborting due to 8 previous errors
error: aborting due to 9 previous errors

0 comments on commit 237dd59

Please sign in to comment.