mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-27 23:20:39 +00:00
Auto merge of #10193 - Jarcho:issue_9894, r=Manishearth
Fix suggestion in `transmutes_expressible_as_ptr_casts` when the source type is a borrow. fixes #9894 changelog: `transmutes_expressible_as_ptr_casts`: Fix suggestion when the source type is a borrow.
This commit is contained in:
commit
89d443a4c3
6 changed files with 60 additions and 43 deletions
|
@ -479,7 +479,10 @@ impl<'tcx> LateLintPass<'tcx> for Transmute {
|
|||
// - char conversions (https://github.com/rust-lang/rust/issues/89259)
|
||||
let const_context = in_constant(cx, e.hir_id);
|
||||
|
||||
let from_ty = cx.typeck_results().expr_ty_adjusted(arg);
|
||||
let (from_ty, from_ty_adjusted) = match cx.typeck_results().expr_adjustments(arg) {
|
||||
[] => (cx.typeck_results().expr_ty(arg), false),
|
||||
[.., a] => (a.target, true),
|
||||
};
|
||||
// Adjustments for `to_ty` happen after the call to `transmute`, so don't use them.
|
||||
let to_ty = cx.typeck_results().expr_ty(e);
|
||||
|
||||
|
@ -506,7 +509,7 @@ impl<'tcx> LateLintPass<'tcx> for Transmute {
|
|||
);
|
||||
|
||||
if !linted {
|
||||
transmutes_expressible_as_ptr_casts::check(cx, e, from_ty, to_ty, arg);
|
||||
transmutes_expressible_as_ptr_casts::check(cx, e, from_ty, from_ty_adjusted, to_ty, arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use super::utils::can_be_expressed_as_pointer_cast;
|
||||
use super::utils::check_cast;
|
||||
use super::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS;
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::sugg;
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::sugg::Sugg;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::Expr;
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_middle::ty::Ty;
|
||||
use rustc_middle::ty::{cast::CastKind, Ty};
|
||||
|
||||
/// Checks for `transmutes_expressible_as_ptr_casts` lint.
|
||||
/// Returns `true` if it's triggered, otherwise returns `false`.
|
||||
|
@ -13,24 +13,40 @@ pub(super) fn check<'tcx>(
|
|||
cx: &LateContext<'tcx>,
|
||||
e: &'tcx Expr<'_>,
|
||||
from_ty: Ty<'tcx>,
|
||||
from_ty_adjusted: bool,
|
||||
to_ty: Ty<'tcx>,
|
||||
arg: &'tcx Expr<'_>,
|
||||
) -> bool {
|
||||
if can_be_expressed_as_pointer_cast(cx, e, from_ty, to_ty) {
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS,
|
||||
e.span,
|
||||
&format!("transmute from `{from_ty}` to `{to_ty}` which could be expressed as a pointer cast instead"),
|
||||
|diag| {
|
||||
if let Some(arg) = sugg::Sugg::hir_opt(cx, arg) {
|
||||
let sugg = arg.as_ty(to_ty.to_string()).to_string();
|
||||
diag.span_suggestion(e.span, "try", sugg, Applicability::MachineApplicable);
|
||||
}
|
||||
},
|
||||
);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
use CastKind::{AddrPtrCast, ArrayPtrCast, FnPtrAddrCast, FnPtrPtrCast, PtrAddrCast, PtrPtrCast};
|
||||
let mut app = Applicability::MachineApplicable;
|
||||
let sugg = match check_cast(cx, e, from_ty, to_ty) {
|
||||
Some(PtrPtrCast | AddrPtrCast | ArrayPtrCast | FnPtrPtrCast | FnPtrAddrCast) => {
|
||||
Sugg::hir_with_context(cx, arg, e.span.ctxt(), "..", &mut app)
|
||||
.as_ty(to_ty.to_string())
|
||||
.to_string()
|
||||
},
|
||||
Some(PtrAddrCast) if !from_ty_adjusted => Sugg::hir_with_context(cx, arg, e.span.ctxt(), "..", &mut app)
|
||||
.as_ty(to_ty.to_string())
|
||||
.to_string(),
|
||||
|
||||
// The only adjustments here would be ref-to-ptr and unsize coercions. The result of an unsize coercions can't
|
||||
// be transmuted to a usize. For ref-to-ptr coercions, borrows need to be cast to a pointer before being cast to
|
||||
// a usize.
|
||||
Some(PtrAddrCast) => format!(
|
||||
"{} as {to_ty}",
|
||||
Sugg::hir_with_context(cx, arg, e.span.ctxt(), "..", &mut app).as_ty(from_ty)
|
||||
),
|
||||
_ => return false,
|
||||
};
|
||||
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS,
|
||||
e.span,
|
||||
&format!("transmute from `{from_ty}` to `{to_ty}` which could be expressed as a pointer cast instead"),
|
||||
"try",
|
||||
sugg,
|
||||
app,
|
||||
);
|
||||
true
|
||||
}
|
||||
|
|
|
@ -20,28 +20,16 @@ pub(super) fn is_layout_incompatible<'tcx>(cx: &LateContext<'tcx>, from: Ty<'tcx
|
|||
}
|
||||
}
|
||||
|
||||
/// Check if the type conversion can be expressed as a pointer cast, instead of
|
||||
/// a transmute. In certain cases, including some invalid casts from array
|
||||
/// references to pointers, this may cause additional errors to be emitted and/or
|
||||
/// ICE error messages. This function will panic if that occurs.
|
||||
pub(super) fn can_be_expressed_as_pointer_cast<'tcx>(
|
||||
cx: &LateContext<'tcx>,
|
||||
e: &'tcx Expr<'_>,
|
||||
from_ty: Ty<'tcx>,
|
||||
to_ty: Ty<'tcx>,
|
||||
) -> bool {
|
||||
use CastKind::{AddrPtrCast, ArrayPtrCast, FnPtrAddrCast, FnPtrPtrCast, PtrAddrCast, PtrPtrCast};
|
||||
matches!(
|
||||
check_cast(cx, e, from_ty, to_ty),
|
||||
Some(PtrPtrCast | PtrAddrCast | AddrPtrCast | ArrayPtrCast | FnPtrPtrCast | FnPtrAddrCast)
|
||||
)
|
||||
}
|
||||
|
||||
/// If a cast from `from_ty` to `to_ty` is valid, returns an Ok containing the kind of
|
||||
/// the cast. In certain cases, including some invalid casts from array references
|
||||
/// to pointers, this may cause additional errors to be emitted and/or ICE error
|
||||
/// messages. This function will panic if that occurs.
|
||||
fn check_cast<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty<'tcx>, to_ty: Ty<'tcx>) -> Option<CastKind> {
|
||||
pub(super) fn check_cast<'tcx>(
|
||||
cx: &LateContext<'tcx>,
|
||||
e: &'tcx Expr<'_>,
|
||||
from_ty: Ty<'tcx>,
|
||||
to_ty: Ty<'tcx>,
|
||||
) -> Option<CastKind> {
|
||||
let hir_id = e.hir_id;
|
||||
let local_def_id = hir_id.owner.def_id;
|
||||
|
||||
|
|
|
@ -51,6 +51,8 @@ fn main() {
|
|||
// e is a function pointer type and U is an integer; fptr-addr-cast
|
||||
let _usize_from_fn_ptr_transmute = unsafe { foo as usize };
|
||||
let _usize_from_fn_ptr = foo as *const usize;
|
||||
|
||||
let _usize_from_ref = unsafe { &1u32 as *const u32 as usize };
|
||||
}
|
||||
|
||||
// If a ref-to-ptr cast of this form where the pointer type points to a type other
|
||||
|
|
|
@ -51,6 +51,8 @@ fn main() {
|
|||
// e is a function pointer type and U is an integer; fptr-addr-cast
|
||||
let _usize_from_fn_ptr_transmute = unsafe { transmute::<fn(usize) -> u8, usize>(foo) };
|
||||
let _usize_from_fn_ptr = foo as *const usize;
|
||||
|
||||
let _usize_from_ref = unsafe { transmute::<*const u32, usize>(&1u32) };
|
||||
}
|
||||
|
||||
// If a ref-to-ptr cast of this form where the pointer type points to a type other
|
||||
|
|
|
@ -46,11 +46,17 @@ error: transmute from `fn(usize) -> u8` to `usize` which could be expressed as a
|
|||
LL | let _usize_from_fn_ptr_transmute = unsafe { transmute::<fn(usize) -> u8, usize>(foo) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `foo as usize`
|
||||
|
||||
error: transmute from `*const u32` to `usize` which could be expressed as a pointer cast instead
|
||||
--> $DIR/transmutes_expressible_as_ptr_casts.rs:55:36
|
||||
|
|
||||
LL | let _usize_from_ref = unsafe { transmute::<*const u32, usize>(&1u32) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&1u32 as *const u32 as usize`
|
||||
|
||||
error: transmute from a reference to a pointer
|
||||
--> $DIR/transmutes_expressible_as_ptr_casts.rs:64:14
|
||||
--> $DIR/transmutes_expressible_as_ptr_casts.rs:66:14
|
||||
|
|
||||
LL | unsafe { transmute::<&[i32; 1], *const u8>(in_param) }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `in_param as *const [i32; 1] as *const u8`
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
error: aborting due to 9 previous errors
|
||||
|
||||
|
|
Loading…
Reference in a new issue