]> git.lizzy.rs Git - rust.git/blob - src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs
Auto merge of #98120 - TaKO8Ki:box-diagnostic-metadata-field, r=estebank
[rust.git] / src / tools / clippy / clippy_lints / src / transmute / useless_transmute.rs
1 use super::USELESS_TRANSMUTE;
2 use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
3 use clippy_utils::sugg;
4 use rustc_errors::Applicability;
5 use rustc_hir::Expr;
6 use rustc_lint::LateContext;
7 use rustc_middle::ty::{self, Ty, TypeVisitable};
8
9 /// Checks for `useless_transmute` lint.
10 /// Returns `true` if it's triggered, otherwise returns `false`.
11 pub(super) fn check<'tcx>(
12     cx: &LateContext<'tcx>,
13     e: &'tcx Expr<'_>,
14     from_ty: Ty<'tcx>,
15     to_ty: Ty<'tcx>,
16     arg: &'tcx Expr<'_>,
17 ) -> bool {
18     match (&from_ty.kind(), &to_ty.kind()) {
19         _ if from_ty == to_ty && !from_ty.has_erased_regions() => {
20             span_lint(
21                 cx,
22                 USELESS_TRANSMUTE,
23                 e.span,
24                 &format!("transmute from a type (`{}`) to itself", from_ty),
25             );
26             true
27         },
28         (ty::Ref(_, rty, rty_mutbl), ty::RawPtr(ptr_ty)) => {
29             // No way to give the correct suggestion here. Avoid linting for now.
30             if !rty.has_erased_regions() {
31                 span_lint_and_then(
32                     cx,
33                     USELESS_TRANSMUTE,
34                     e.span,
35                     "transmute from a reference to a pointer",
36                     |diag| {
37                         if let Some(arg) = sugg::Sugg::hir_opt(cx, arg) {
38                             let rty_and_mut = ty::TypeAndMut {
39                                 ty: *rty,
40                                 mutbl: *rty_mutbl,
41                             };
42
43                             let sugg = if *ptr_ty == rty_and_mut {
44                                 arg.as_ty(to_ty)
45                             } else {
46                                 arg.as_ty(cx.tcx.mk_ptr(rty_and_mut)).as_ty(to_ty)
47                             };
48
49                             diag.span_suggestion(e.span, "try", sugg, Applicability::Unspecified);
50                         }
51                     },
52                 );
53             }
54             true
55         },
56         (ty::Int(_) | ty::Uint(_), ty::RawPtr(_)) => {
57             span_lint_and_then(
58                 cx,
59                 USELESS_TRANSMUTE,
60                 e.span,
61                 "transmute from an integer to a pointer",
62                 |diag| {
63                     if let Some(arg) = sugg::Sugg::hir_opt(cx, arg) {
64                         diag.span_suggestion(e.span, "try", arg.as_ty(&to_ty.to_string()), Applicability::Unspecified);
65                     }
66                 },
67             );
68             true
69         },
70         _ => false,
71     }
72 }