]> git.proxmox.com Git - rustc.git/blame - src/tools/clippy/clippy_lints/src/borrow_as_ptr.rs
New upstream version 1.63.0+dfsg1
[rustc.git] / src / tools / clippy / clippy_lints / src / borrow_as_ptr.rs
CommitLineData
5099ac24
FG
1use clippy_utils::diagnostics::span_lint_and_sugg;
2use clippy_utils::is_no_std_crate;
3use clippy_utils::source::snippet_opt;
4use clippy_utils::{meets_msrv, msrvs};
5use if_chain::if_chain;
6use rustc_errors::Applicability;
7use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, TyKind};
8use rustc_lint::{LateContext, LateLintPass};
9use rustc_semver::RustcVersion;
10use rustc_session::{declare_tool_lint, impl_lint_pass};
11
12declare_clippy_lint! {
13 /// ### What it does
14 /// Checks for the usage of `&expr as *const T` or
15 /// `&mut expr as *mut T`, and suggest using `ptr::addr_of` or
16 /// `ptr::addr_of_mut` instead.
17 ///
18 /// ### Why is this bad?
19 /// This would improve readability and avoid creating a reference
20 /// that points to an uninitialized value or unaligned place.
21 /// Read the `ptr::addr_of` docs for more information.
22 ///
23 /// ### Example
24 /// ```rust
25 /// let val = 1;
26 /// let p = &val as *const i32;
27 ///
28 /// let mut val_mut = 1;
29 /// let p_mut = &mut val_mut as *mut i32;
30 /// ```
31 /// Use instead:
32 /// ```rust
33 /// let val = 1;
34 /// let p = std::ptr::addr_of!(val);
35 ///
36 /// let mut val_mut = 1;
37 /// let p_mut = std::ptr::addr_of_mut!(val_mut);
38 /// ```
39 #[clippy::version = "1.60.0"]
40 pub BORROW_AS_PTR,
41 pedantic,
42 "borrowing just to cast to a raw pointer"
43}
44
45impl_lint_pass!(BorrowAsPtr => [BORROW_AS_PTR]);
46
47pub struct BorrowAsPtr {
48 msrv: Option<RustcVersion>,
49}
50
51impl BorrowAsPtr {
52 #[must_use]
53 pub fn new(msrv: Option<RustcVersion>) -> Self {
54 Self { msrv }
55 }
56}
57
58impl<'tcx> LateLintPass<'tcx> for BorrowAsPtr {
59 fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
923072b8 60 if !meets_msrv(self.msrv, msrvs::BORROW_AS_PTR) {
5099ac24
FG
61 return;
62 }
63
64 if expr.span.from_expansion() {
65 return;
66 }
67
68 if_chain! {
69 if let ExprKind::Cast(left_expr, ty) = &expr.kind;
70 if let TyKind::Ptr(_) = ty.kind;
71 if let ExprKind::AddrOf(BorrowKind::Ref, mutability, e) = &left_expr.kind;
72
73 then {
74 let core_or_std = if is_no_std_crate(cx) { "core" } else { "std" };
75 let macro_name = match mutability {
76 Mutability::Not => "addr_of",
77 Mutability::Mut => "addr_of_mut",
78 };
79
80 span_lint_and_sugg(
81 cx,
82 BORROW_AS_PTR,
83 expr.span,
84 "borrow as raw pointer",
85 "try",
86 format!(
87 "{}::ptr::{}!({})",
88 core_or_std,
89 macro_name,
90 snippet_opt(cx, e.span).unwrap()
91 ),
92 Applicability::MachineApplicable,
93 );
94 }
95 }
96 }
97
98 extract_msrv_attr!(LateContext);
99}