diff --git a/clippy_lints/src/borrow_as_ptr.rs b/clippy_lints/src/borrow_as_ptr.rs deleted file mode 100644 index 0993adbae2e..00000000000 --- a/clippy_lints/src/borrow_as_ptr.rs +++ /dev/null @@ -1,99 +0,0 @@ -use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::is_no_std_crate; -use clippy_utils::source::snippet_opt; -use clippy_utils::{meets_msrv, msrvs}; -use if_chain::if_chain; -use rustc_errors::Applicability; -use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, TyKind}; -use rustc_lint::{LateContext, LateLintPass}; -use rustc_semver::RustcVersion; -use rustc_session::{declare_tool_lint, impl_lint_pass}; - -declare_clippy_lint! { - /// ### What it does - /// Checks for the usage of `&expr as *const T` or - /// `&mut expr as *mut T`, and suggest using `ptr::addr_of` or - /// `ptr::addr_of_mut` instead. - /// - /// ### Why is this bad? - /// This would improve readability and avoid creating a reference - /// that points to an uninitialized value or unaligned place. - /// Read the `ptr::addr_of` docs for more information. - /// - /// ### Example - /// ```rust - /// let val = 1; - /// let p = &val as *const i32; - /// - /// let mut val_mut = 1; - /// let p_mut = &mut val_mut as *mut i32; - /// ``` - /// Use instead: - /// ```rust - /// let val = 1; - /// let p = std::ptr::addr_of!(val); - /// - /// let mut val_mut = 1; - /// let p_mut = std::ptr::addr_of_mut!(val_mut); - /// ``` - #[clippy::version = "1.60.0"] - pub BORROW_AS_PTR, - pedantic, - "borrowing just to cast to a raw pointer" -} - -impl_lint_pass!(BorrowAsPtr => [BORROW_AS_PTR]); - -pub struct BorrowAsPtr { - msrv: Option, -} - -impl BorrowAsPtr { - #[must_use] - pub fn new(msrv: Option) -> Self { - Self { msrv } - } -} - -impl<'tcx> LateLintPass<'tcx> for BorrowAsPtr { - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if !meets_msrv(self.msrv, msrvs::BORROW_AS_PTR) { - return; - } - - if expr.span.from_expansion() { - return; - } - - if_chain! { - if let ExprKind::Cast(left_expr, ty) = &expr.kind; - if let TyKind::Ptr(_) = ty.kind; - if let ExprKind::AddrOf(BorrowKind::Ref, mutability, e) = &left_expr.kind; - - then { - let core_or_std = if is_no_std_crate(cx) { "core" } else { "std" }; - let macro_name = match mutability { - Mutability::Not => "addr_of", - Mutability::Mut => "addr_of_mut", - }; - - span_lint_and_sugg( - cx, - BORROW_AS_PTR, - expr.span, - "borrow as raw pointer", - "try", - format!( - "{}::ptr::{}!({})", - core_or_std, - macro_name, - snippet_opt(cx, e.span).unwrap() - ), - Applicability::MachineApplicable, - ); - } - } - } - - extract_msrv_attr!(LateContext); -} diff --git a/clippy_lints/src/casts/borrow_as_ptr.rs b/clippy_lints/src/casts/borrow_as_ptr.rs new file mode 100644 index 00000000000..6e1f8cd64f0 --- /dev/null +++ b/clippy_lints/src/casts/borrow_as_ptr.rs @@ -0,0 +1,37 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::is_no_std_crate; +use clippy_utils::source::snippet_with_context; +use rustc_errors::Applicability; +use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, Ty, TyKind}; +use rustc_lint::LateContext; + +use super::BORROW_AS_PTR; + +pub(super) fn check<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx Expr<'_>, + cast_expr: &'tcx Expr<'_>, + cast_to: &'tcx Ty<'_>, +) { + if matches!(cast_to.kind, TyKind::Ptr(_)) + && let ExprKind::AddrOf(BorrowKind::Ref, mutability, e) = cast_expr.kind + { + let core_or_std = if is_no_std_crate(cx) { "core" } else { "std" }; + let macro_name = match mutability { + Mutability::Not => "addr_of", + Mutability::Mut => "addr_of_mut", + }; + let mut app = Applicability::MachineApplicable; + let snip = snippet_with_context(cx, e.span, cast_expr.span.ctxt(), "..", &mut app).0; + + span_lint_and_sugg( + cx, + BORROW_AS_PTR, + expr.span, + "borrow as raw pointer", + "try", + format!("{}::ptr::{}!({})", core_or_std, macro_name, snip), + Applicability::MachineApplicable, + ); + } +} diff --git a/clippy_lints/src/casts/mod.rs b/clippy_lints/src/casts/mod.rs index 01057d9f67c..644edefb8fe 100644 --- a/clippy_lints/src/casts/mod.rs +++ b/clippy_lints/src/casts/mod.rs @@ -1,4 +1,5 @@ mod as_underscore; +mod borrow_as_ptr; mod cast_abs_to_unsigned; mod cast_enum_constructor; mod cast_lossless; @@ -17,7 +18,7 @@ mod ptr_as_ptr; mod unnecessary_cast; mod utils; -use clippy_utils::is_hir_ty_cfg_dependant; +use clippy_utils::{is_hir_ty_cfg_dependant, meets_msrv, msrvs}; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; @@ -535,6 +536,39 @@ declare_clippy_lint! { "detects `as _` conversion" } +declare_clippy_lint! { + /// ### What it does + /// Checks for the usage of `&expr as *const T` or + /// `&mut expr as *mut T`, and suggest using `ptr::addr_of` or + /// `ptr::addr_of_mut` instead. + /// + /// ### Why is this bad? + /// This would improve readability and avoid creating a reference + /// that points to an uninitialized value or unaligned place. + /// Read the `ptr::addr_of` docs for more information. + /// + /// ### Example + /// ```rust + /// let val = 1; + /// let p = &val as *const i32; + /// + /// let mut val_mut = 1; + /// let p_mut = &mut val_mut as *mut i32; + /// ``` + /// Use instead: + /// ```rust + /// let val = 1; + /// let p = std::ptr::addr_of!(val); + /// + /// let mut val_mut = 1; + /// let p_mut = std::ptr::addr_of_mut!(val_mut); + /// ``` + #[clippy::version = "1.60.0"] + pub BORROW_AS_PTR, + pedantic, + "borrowing just to cast to a raw pointer" +} + pub struct Casts { msrv: Option, } @@ -565,6 +599,7 @@ impl_lint_pass!(Casts => [ CAST_ENUM_CONSTRUCTOR, CAST_ABS_TO_UNSIGNED, AS_UNDERSCORE, + BORROW_AS_PTR, ]); impl<'tcx> LateLintPass<'tcx> for Casts { @@ -607,6 +642,10 @@ impl<'tcx> LateLintPass<'tcx> for Casts { } as_underscore::check(cx, expr, cast_to_hir); + + if meets_msrv(self.msrv, msrvs::BORROW_AS_PTR) { + borrow_as_ptr::check(cx, expr, cast_expr, cast_to_hir); + } } cast_ref_to_mut::check(cx, expr); diff --git a/clippy_lints/src/lib.register_lints.rs b/clippy_lints/src/lib.register_lints.rs index e7665c3fa1d..7883711e5a3 100644 --- a/clippy_lints/src/lib.register_lints.rs +++ b/clippy_lints/src/lib.register_lints.rs @@ -58,7 +58,6 @@ store.register_lints(&[ bool_assert_comparison::BOOL_ASSERT_COMPARISON, booleans::NONMINIMAL_BOOL, booleans::OVERLY_COMPLEX_BOOL_EXPR, - borrow_as_ptr::BORROW_AS_PTR, borrow_deref_ref::BORROW_DEREF_REF, bytecount::NAIVE_BYTECOUNT, bytes_count_to_len::BYTES_COUNT_TO_LEN, @@ -69,6 +68,7 @@ store.register_lints(&[ cargo::WILDCARD_DEPENDENCIES, case_sensitive_file_extension_comparisons::CASE_SENSITIVE_FILE_EXTENSION_COMPARISONS, casts::AS_UNDERSCORE, + casts::BORROW_AS_PTR, casts::CAST_ABS_TO_UNSIGNED, casts::CAST_ENUM_CONSTRUCTOR, casts::CAST_ENUM_TRUNCATION, diff --git a/clippy_lints/src/lib.register_pedantic.rs b/clippy_lints/src/lib.register_pedantic.rs index 4250ee055e6..ae9f046f023 100644 --- a/clippy_lints/src/lib.register_pedantic.rs +++ b/clippy_lints/src/lib.register_pedantic.rs @@ -4,9 +4,9 @@ store.register_group(true, "clippy::pedantic", Some("clippy_pedantic"), vec![ LintId::of(attrs::INLINE_ALWAYS), - LintId::of(borrow_as_ptr::BORROW_AS_PTR), LintId::of(bytecount::NAIVE_BYTECOUNT), LintId::of(case_sensitive_file_extension_comparisons::CASE_SENSITIVE_FILE_EXTENSION_COMPARISONS), + LintId::of(casts::BORROW_AS_PTR), LintId::of(casts::CAST_LOSSLESS), LintId::of(casts::CAST_POSSIBLE_TRUNCATION), LintId::of(casts::CAST_POSSIBLE_WRAP), diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index d32a2fad493..63e0fcf6b0f 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -179,7 +179,6 @@ mod await_holding_invalid; mod blocks_in_if_conditions; mod bool_assert_comparison; mod booleans; -mod borrow_as_ptr; mod borrow_deref_ref; mod bytecount; mod bytes_count_to_len; @@ -893,7 +892,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| Box::new(return_self_not_must_use::ReturnSelfNotMustUse)); store.register_late_pass(|| Box::new(init_numbered_fields::NumberedFields)); store.register_early_pass(|| Box::new(single_char_lifetime_names::SingleCharLifetimeNames)); - store.register_late_pass(move || Box::new(borrow_as_ptr::BorrowAsPtr::new(msrv))); store.register_late_pass(move || Box::new(manual_bits::ManualBits::new(msrv))); store.register_late_pass(|| Box::new(default_union_representation::DefaultUnionRepresentation)); store.register_early_pass(|| Box::new(doc_link_with_quotes::DocLinkWithQuotes));