diff --git a/compiler/rustc_lint/src/drop_forget_useless.rs b/compiler/rustc_lint/src/drop_forget_useless.rs index c2d137986ce4d..3f98ed04392ea 100644 --- a/compiler/rustc_lint/src/drop_forget_useless.rs +++ b/compiler/rustc_lint/src/drop_forget_useless.rs @@ -4,8 +4,8 @@ use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::sym; use crate::lints::{ - DropCopyDiag, DropRefDiag, ForgetCopyDiag, ForgetRefDiag, UndroppedManuallyDropsDiag, - UndroppedManuallyDropsSuggestion, UseLetUnderscoreIgnoreSuggestion, + CopyDropInPlaceDiag, DropCopyDiag, DropRefDiag, ForgetCopyDiag, ForgetRefDiag, + UndroppedManuallyDropsDiag, UndroppedManuallyDropsSuggestion, UseLetUnderscoreIgnoreSuggestion, }; use crate::{LateContext, LateLintPass, LintContext}; @@ -134,7 +134,32 @@ declare_lint! { "calls to `std::mem::drop` with `std::mem::ManuallyDrop` instead of it's inner value" } -declare_lint_pass!(DropForgetUseless => [DROPPING_REFERENCES, FORGETTING_REFERENCES, DROPPING_COPY_TYPES, FORGETTING_COPY_TYPES, UNDROPPED_MANUALLY_DROPS]); +declare_lint! { + /// The `copy_drop_in_place` lint checks for calls to `std::ptr::drop_in_place` with + /// a pointer that points to a type that derives the Copy trait. + /// + /// ### Example + /// + /// ```rust + /// let mut x = 0u8; + /// let y = &mut x as *mut _; + /// unsafe { + /// std::ptr::drop_in_place(y); + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// Types that implement Copy do not have a destructor so calling + /// `std::ptr::drop_in_place` on a pointer to a type that implements Copy + /// won't do anything. + pub COPY_DROP_IN_PLACE, + Warn, + "calls to `std::ptr::drop_in_place` with a pointer to a value that implements Copy" +} + +declare_lint_pass!(DropForgetUseless => [DROPPING_REFERENCES, FORGETTING_REFERENCES, DROPPING_COPY_TYPES, FORGETTING_COPY_TYPES, UNDROPPED_MANUALLY_DROPS,COPY_DROP_IN_PLACE]); impl<'tcx> LateLintPass<'tcx> for DropForgetUseless { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { @@ -219,6 +244,16 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetUseless { }, ); } + sym::ptr_drop_in_place + if let ty::RawPtr(inner, ty::Mutability::Mut) = arg_ty.kind() + && cx.type_is_copy_modulo_regions(*inner) => + { + cx.emit_span_lint( + COPY_DROP_IN_PLACE, + expr.span, + CopyDropInPlaceDiag { arg_ty, label: arg.span }, + ); + } _ => return, }; } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index a745da56357a4..23ea78634fb26 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -924,6 +924,14 @@ pub(crate) struct UndroppedManuallyDropsSuggestion { pub end_span: Span, } +#[derive(Diagnostic)] +#[diag("calls to `std::ptr::drop_in_place` with a pointer to a Copy type does nothing")] +pub(crate) struct CopyDropInPlaceDiag<'a> { + pub arg_ty: Ty<'a>, + #[label("argument has type `{$arg_ty}`")] + pub label: Span, +} + // invalid_from_utf8.rs #[derive(Diagnostic)] pub(crate) enum InvalidFromUtf8Diag { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index ed12adf71cff2..760ba4a68ed7e 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1626,6 +1626,7 @@ symbols! { ptr_const_is_null, ptr_copy, ptr_copy_nonoverlapping, + ptr_drop_in_place, ptr_from_ref, ptr_guaranteed_cmp, ptr_is_null, diff --git a/tests/ui/lint/copy_drop_in_place.rs b/tests/ui/lint/copy_drop_in_place.rs new file mode 100644 index 0000000000000..ba61f78ffab60 --- /dev/null +++ b/tests/ui/lint/copy_drop_in_place.rs @@ -0,0 +1,12 @@ +// Test if the `copy_drop_in_place` lint is working correctly. + +#[deny(copy_drop_in_place)] + +fn main() { + let mut x = 0u8; + let y = &mut x as *mut _; + unsafe { + std::ptr::drop_in_place(y); + //~^ ERROR calls to `std::ptr::drop_in_place` with a pointer to a Copy type does nothing + } +} diff --git a/tests/ui/lint/copy_drop_in_place.stderr b/tests/ui/lint/copy_drop_in_place.stderr new file mode 100644 index 0000000000000..afbe70f9128ca --- /dev/null +++ b/tests/ui/lint/copy_drop_in_place.stderr @@ -0,0 +1,16 @@ +error: calls to `std::ptr::drop_in_place` with a pointer to a Copy type does nothing + --> $DIR/copy_drop_in_place.rs:9:9 + | +LL | std::ptr::drop_in_place(y); + | ^^^^^^^^^^^^^^^^^^^^^^^^-^ + | | + | argument has type `*mut u8` + | +note: the lint level is defined here + --> $DIR/copy_drop_in_place.rs:3:8 + | +LL | #[deny(copy_drop_in_place)] + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error +