67 lines
2.5 KiB
Rust
67 lines
2.5 KiB
Rust
use clippy_utils::diagnostics::span_lint_and_sugg;
|
|
use clippy_utils::msrvs::Msrv;
|
|
use clippy_utils::source::{snippet_with_applicability, snippet_with_context};
|
|
use clippy_utils::sugg::has_enclosing_paren;
|
|
use clippy_utils::{is_lint_allowed, msrvs, std_or_core};
|
|
use rustc_errors::Applicability;
|
|
use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, Ty, TyKind};
|
|
use rustc_lint::LateContext;
|
|
use rustc_middle::ty::adjustment::Adjust;
|
|
use rustc_span::BytePos;
|
|
|
|
use super::BORROW_AS_PTR;
|
|
|
|
pub(super) fn check<'tcx>(
|
|
cx: &LateContext<'tcx>,
|
|
expr: &'tcx Expr<'_>,
|
|
cast_expr: &'tcx Expr<'_>,
|
|
cast_to: &'tcx Ty<'_>,
|
|
msrv: Msrv,
|
|
) -> bool {
|
|
if matches!(cast_to.kind, TyKind::Ptr(_))
|
|
&& let ExprKind::AddrOf(BorrowKind::Ref, mutability, e) = cast_expr.kind
|
|
&& !is_lint_allowed(cx, BORROW_AS_PTR, expr.hir_id)
|
|
{
|
|
let mut app = Applicability::MachineApplicable;
|
|
let snip = snippet_with_context(cx, e.span, cast_expr.span.ctxt(), "..", &mut app).0;
|
|
// Fix #9884
|
|
if !e.is_place_expr(|base| {
|
|
cx.typeck_results()
|
|
.adjustments()
|
|
.get(base.hir_id)
|
|
.is_some_and(|x| x.iter().any(|adj| matches!(adj.kind, Adjust::Deref(_))))
|
|
}) {
|
|
return false;
|
|
}
|
|
|
|
let (suggestion, span) = if msrv.meets(cx, msrvs::RAW_REF_OP) {
|
|
let operator_kind = match mutability {
|
|
Mutability::Not => "const",
|
|
Mutability::Mut => "mut",
|
|
};
|
|
// Make sure that the span to be replaced doesn't include parentheses, that could break the
|
|
// suggestion.
|
|
let span = if has_enclosing_paren(snippet_with_applicability(cx, expr.span, "", &mut app)) {
|
|
expr.span
|
|
.with_lo(expr.span.lo() + BytePos(1))
|
|
.with_hi(expr.span.hi() - BytePos(1))
|
|
} else {
|
|
expr.span
|
|
};
|
|
(format!("&raw {operator_kind} {snip}"), span)
|
|
} else {
|
|
let Some(std_or_core) = std_or_core(cx) else {
|
|
return false;
|
|
};
|
|
let macro_name = match mutability {
|
|
Mutability::Not => "addr_of",
|
|
Mutability::Mut => "addr_of_mut",
|
|
};
|
|
(format!("{std_or_core}::ptr::{macro_name}!({snip})"), expr.span)
|
|
};
|
|
|
|
span_lint_and_sugg(cx, BORROW_AS_PTR, span, "borrow as raw pointer", "try", suggestion, app);
|
|
return true;
|
|
}
|
|
false
|
|
}
|