]> git.proxmox.com Git - rustc.git/blame - src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs
New upstream version 1.69.0+dfsg1
[rustc.git] / src / tools / clippy / clippy_lints / src / transmute / transmute_ptr_to_ref.rs
CommitLineData
f20569fa 1use super::TRANSMUTE_PTR_TO_REF;
cdc7bbd5 2use clippy_utils::diagnostics::span_lint_and_then;
487cf647 3use clippy_utils::msrvs::{self, Msrv};
064997fb 4use clippy_utils::source::snippet_with_applicability;
487cf647 5use clippy_utils::sugg;
f20569fa 6use rustc_errors::Applicability;
064997fb 7use rustc_hir::{self as hir, Expr, GenericArg, Mutability, Path, TyKind};
f20569fa 8use rustc_lint::LateContext;
9ffffee4 9use rustc_middle::ty::{self, Ty, TypeVisitableExt};
f20569fa
XL
10
11/// Checks for `transmute_ptr_to_ref` lint.
12/// Returns `true` if it's triggered, otherwise returns `false`.
13pub(super) fn check<'tcx>(
14 cx: &LateContext<'tcx>,
15 e: &'tcx Expr<'_>,
16 from_ty: Ty<'tcx>,
17 to_ty: Ty<'tcx>,
5099ac24 18 arg: &'tcx Expr<'_>,
064997fb 19 path: &'tcx Path<'_>,
487cf647 20 msrv: &Msrv,
f20569fa
XL
21) -> bool {
22 match (&from_ty.kind(), &to_ty.kind()) {
23 (ty::RawPtr(from_ptr_ty), ty::Ref(_, to_ref_ty, mutbl)) => {
24 span_lint_and_then(
25 cx,
26 TRANSMUTE_PTR_TO_REF,
27 e.span,
2b03887a 28 &format!("transmute from a pointer type (`{from_ty}`) to a reference type (`{to_ty}`)"),
f20569fa 29 |diag| {
5099ac24 30 let arg = sugg::Sugg::hir(cx, arg, "..");
f20569fa
XL
31 let (deref, cast) = if *mutbl == Mutability::Mut {
32 ("&mut *", "*mut")
33 } else {
34 ("&*", "*const")
35 };
064997fb 36 let mut app = Applicability::MachineApplicable;
f20569fa 37
064997fb
FG
38 let sugg = if let Some(ty) = get_explicit_type(path) {
39 let ty_snip = snippet_with_applicability(cx, ty.span, "..", &mut app);
487cf647 40 if msrv.meets(msrvs::POINTER_CAST) {
2b03887a 41 format!("{deref}{}.cast::<{ty_snip}>()", arg.maybe_par())
064997fb 42 } else if from_ptr_ty.has_erased_regions() {
2b03887a 43 sugg::make_unop(deref, arg.as_ty(format!("{cast} () as {cast} {ty_snip}"))).to_string()
064997fb 44 } else {
2b03887a 45 sugg::make_unop(deref, arg.as_ty(format!("{cast} {ty_snip}"))).to_string()
064997fb
FG
46 }
47 } else if from_ptr_ty.ty == *to_ref_ty {
48 if from_ptr_ty.has_erased_regions() {
487cf647 49 if msrv.meets(msrvs::POINTER_CAST) {
2b03887a 50 format!("{deref}{}.cast::<{to_ref_ty}>()", arg.maybe_par())
064997fb 51 } else {
2b03887a 52 sugg::make_unop(deref, arg.as_ty(format!("{cast} () as {cast} {to_ref_ty}")))
064997fb
FG
53 .to_string()
54 }
55 } else {
56 sugg::make_unop(deref, arg).to_string()
57 }
f20569fa 58 } else {
2b03887a 59 sugg::make_unop(deref, arg.as_ty(format!("{cast} {to_ref_ty}"))).to_string()
f20569fa
XL
60 };
61
064997fb 62 diag.span_suggestion(e.span, "try", sugg, app);
f20569fa
XL
63 },
64 );
65 true
66 },
67 _ => false,
68 }
69}
064997fb
FG
70
71/// Gets the type `Bar` in `…::transmute<Foo, &Bar>`.
72fn get_explicit_type<'tcx>(path: &'tcx Path<'tcx>) -> Option<&'tcx hir::Ty<'tcx>> {
73 if let GenericArg::Type(ty) = path.segments.last()?.args?.args.get(1)?
9c376795 74 && let TyKind::Ref(_, ty) = &ty.kind
064997fb
FG
75 {
76 Some(ty.ty)
77 } else {
78 None
79 }
80}