| use super::{TRANSMUTE_BYTES_TO_STR, TRANSMUTE_PTR_TO_PTR}; |
| use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; |
| use clippy_utils::source::snippet; |
| use clippy_utils::sugg; |
| use if_chain::if_chain; |
| use rustc_errors::Applicability; |
| use rustc_hir::{Expr, Mutability}; |
| use rustc_lint::LateContext; |
| use rustc_middle::ty::{self, Ty}; |
| |
| /// Checks for `transmute_bytes_to_str` and `transmute_ptr_to_ptr` lints. |
| /// Returns `true` if either one triggered, otherwise returns `false`. |
| pub(super) fn check<'tcx>( |
| cx: &LateContext<'tcx>, |
| e: &'tcx Expr<'_>, |
| from_ty: Ty<'tcx>, |
| to_ty: Ty<'tcx>, |
| arg: &'tcx Expr<'_>, |
| const_context: bool, |
| ) -> bool { |
| let mut triggered = false; |
| |
| if let (ty::Ref(_, ty_from, from_mutbl), ty::Ref(_, ty_to, to_mutbl)) = (&from_ty.kind(), &to_ty.kind()) { |
| if_chain! { |
| if let (&ty::Slice(slice_ty), &ty::Str) = (&ty_from.kind(), &ty_to.kind()); |
| if let ty::Uint(ty::UintTy::U8) = slice_ty.kind(); |
| if from_mutbl == to_mutbl; |
| then { |
| let postfix = if *from_mutbl == Mutability::Mut { |
| "_mut" |
| } else { |
| "" |
| }; |
| |
| let snippet = snippet(cx, arg.span, ".."); |
| |
| span_lint_and_sugg( |
| cx, |
| TRANSMUTE_BYTES_TO_STR, |
| e.span, |
| &format!("transmute from a `{from_ty}` to a `{to_ty}`"), |
| "consider using", |
| if const_context { |
| format!("std::str::from_utf8_unchecked{postfix}({snippet})") |
| } else { |
| format!("std::str::from_utf8{postfix}({snippet}).unwrap()") |
| }, |
| Applicability::MaybeIncorrect, |
| ); |
| triggered = true; |
| } else { |
| if (cx.tcx.erase_regions(from_ty) != cx.tcx.erase_regions(to_ty)) |
| && !const_context { |
| span_lint_and_then( |
| cx, |
| TRANSMUTE_PTR_TO_PTR, |
| e.span, |
| "transmute from a reference to a reference", |
| |diag| if let Some(arg) = sugg::Sugg::hir_opt(cx, arg) { |
| let ty_from_and_mut = ty::TypeAndMut { |
| ty: *ty_from, |
| mutbl: *from_mutbl |
| }; |
| let ty_to_and_mut = ty::TypeAndMut { ty: *ty_to, mutbl: *to_mutbl }; |
| let sugg_paren = arg |
| .as_ty(cx.tcx.mk_ptr(ty_from_and_mut)) |
| .as_ty(cx.tcx.mk_ptr(ty_to_and_mut)); |
| let sugg = if *to_mutbl == Mutability::Mut { |
| sugg_paren.mut_addr_deref() |
| } else { |
| sugg_paren.addr_deref() |
| }; |
| diag.span_suggestion( |
| e.span, |
| "try", |
| sugg, |
| Applicability::Unspecified, |
| ); |
| }, |
| ); |
| |
| triggered = true; |
| } |
| } |
| } |
| } |
| |
| triggered |
| } |