|
| 1 | +use clippy_utils::diagnostics::span_lint_and_sugg; |
| 2 | +use clippy_utils::is_no_std_crate; |
| 3 | +use clippy_utils::source::snippet_with_applicability; |
| 4 | +use clippy_utils::sugg::Sugg; |
| 5 | +use rustc_errors::Applicability; |
| 6 | +use rustc_hir::{Expr, Mutability, Ty, TyKind}; |
| 7 | +use rustc_lint::LateContext; |
| 8 | +use rustc_middle::ty::{self, TypeAndMut}; |
| 9 | + |
| 10 | +use super::REF_AS_PTR; |
| 11 | + |
| 12 | +pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, cast_to_hir_ty: &Ty<'_>) { |
| 13 | + let (cast_from, cast_to) = ( |
| 14 | + cx.typeck_results().expr_ty(cast_expr), |
| 15 | + cx.typeck_results().expr_ty(expr), |
| 16 | + ); |
| 17 | + |
| 18 | + if matches!(cast_from.kind(), ty::Ref(..)) |
| 19 | + && let ty::RawPtr(TypeAndMut { mutbl: to_mutbl, .. }) = cast_to.kind() |
| 20 | + { |
| 21 | + let core_or_std = if is_no_std_crate(cx) { "core" } else { "std" }; |
| 22 | + let fn_name = match to_mutbl { |
| 23 | + Mutability::Not => "from_ref", |
| 24 | + Mutability::Mut => "from_mut", |
| 25 | + }; |
| 26 | + |
| 27 | + let mut app = Applicability::MachineApplicable; |
| 28 | + let turbofish = match &cast_to_hir_ty.kind { |
| 29 | + TyKind::Infer => String::new(), |
| 30 | + TyKind::Ptr(mut_ty) => { |
| 31 | + if matches!(mut_ty.ty.kind, TyKind::Infer) { |
| 32 | + String::new() |
| 33 | + } else { |
| 34 | + format!( |
| 35 | + "::<{}>", |
| 36 | + snippet_with_applicability(cx, mut_ty.ty.span, "/* type */", &mut app) |
| 37 | + ) |
| 38 | + } |
| 39 | + }, |
| 40 | + _ => return, |
| 41 | + }; |
| 42 | + |
| 43 | + let cast_expr_sugg = Sugg::hir_with_applicability(cx, cast_expr, "_", &mut app); |
| 44 | + |
| 45 | + span_lint_and_sugg( |
| 46 | + cx, |
| 47 | + REF_AS_PTR, |
| 48 | + expr.span, |
| 49 | + "reference as raw pointer", |
| 50 | + "try", |
| 51 | + format!("{core_or_std}::ptr::{fn_name}{turbofish}({cast_expr_sugg})"), |
| 52 | + app, |
| 53 | + ); |
| 54 | + } |
| 55 | +} |
0 commit comments