]> git.proxmox.com Git - rustc.git/blame - src/tools/clippy/clippy_lints/src/transmute/transmute_ref_to_ref.rs
New upstream version 1.53.0+dfsg1
[rustc.git] / src / tools / clippy / clippy_lints / src / transmute / transmute_ref_to_ref.rs
CommitLineData
f20569fa 1use super::{TRANSMUTE_BYTES_TO_STR, TRANSMUTE_PTR_TO_PTR};
cdc7bbd5
XL
2use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
3use clippy_utils::source::snippet;
4use clippy_utils::sugg;
f20569fa
XL
5use if_chain::if_chain;
6use rustc_errors::Applicability;
7use rustc_hir::{Expr, Mutability};
8use rustc_lint::LateContext;
9use rustc_middle::ty::{self, Ty};
10
11/// Checks for `transmute_bytes_to_str` and `transmute_ptr_to_ptr` lints.
12/// Returns `true` if either one 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>,
18 args: &'tcx [Expr<'_>],
19 const_context: bool,
20) -> bool {
21 let mut triggered = false;
22
23 if let (ty::Ref(_, ty_from, from_mutbl), ty::Ref(_, ty_to, to_mutbl)) = (&from_ty.kind(), &to_ty.kind()) {
24 if_chain! {
25 if let (&ty::Slice(slice_ty), &ty::Str) = (&ty_from.kind(), &ty_to.kind());
26 if let ty::Uint(ty::UintTy::U8) = slice_ty.kind();
27 if from_mutbl == to_mutbl;
28 then {
29 let postfix = if *from_mutbl == Mutability::Mut {
30 "_mut"
31 } else {
32 ""
33 };
34
35 span_lint_and_sugg(
36 cx,
37 TRANSMUTE_BYTES_TO_STR,
38 e.span,
39 &format!("transmute from a `{}` to a `{}`", from_ty, to_ty),
40 "consider using",
41 format!(
42 "std::str::from_utf8{}({}).unwrap()",
43 postfix,
44 snippet(cx, args[0].span, ".."),
45 ),
46 Applicability::Unspecified,
47 );
48 triggered = true;
49 } else {
50 if (cx.tcx.erase_regions(from_ty) != cx.tcx.erase_regions(to_ty))
51 && !const_context {
52 span_lint_and_then(
53 cx,
54 TRANSMUTE_PTR_TO_PTR,
55 e.span,
56 "transmute from a reference to a reference",
57 |diag| if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) {
58 let ty_from_and_mut = ty::TypeAndMut {
59 ty: ty_from,
60 mutbl: *from_mutbl
61 };
62 let ty_to_and_mut = ty::TypeAndMut { ty: ty_to, mutbl: *to_mutbl };
63 let sugg_paren = arg
64 .as_ty(cx.tcx.mk_ptr(ty_from_and_mut))
65 .as_ty(cx.tcx.mk_ptr(ty_to_and_mut));
66 let sugg = if *to_mutbl == Mutability::Mut {
67 sugg_paren.mut_addr_deref()
68 } else {
69 sugg_paren.addr_deref()
70 };
71 diag.span_suggestion(
72 e.span,
73 "try",
74 sugg.to_string(),
75 Applicability::Unspecified,
76 );
77 },
78 );
79
80 triggered = true;
81 }
82 }
83 }
84 }
85
86 triggered
87}