diff options
| author | Urgau <urgau@numericable.fr> | 2023-03-28 18:47:37 +0200 |
|---|---|---|
| committer | Urgau <urgau@numericable.fr> | 2023-05-10 19:36:01 +0200 |
| commit | 971b9b23b5ce0573dcc28e928410b4795b548bcc (patch) | |
| tree | 85771fc14cdffd19f5b761289e0b829ca710d98e | |
| parent | cf6d2272c51406c03d8e1b1b3e7c1d36a5535877 (diff) | |
| download | rust-971b9b23b5ce0573dcc28e928410b4795b548bcc.tar.gz rust-971b9b23b5ce0573dcc28e928410b4795b548bcc.zip | |
Uplift clippy::forget_copy to rustc
| -rw-r--r-- | compiler/rustc_lint/messages.ftl | 3 | ||||
| -rw-r--r-- | compiler/rustc_lint/src/drop_forget_useless.rs | 38 | ||||
| -rw-r--r-- | compiler/rustc_lint/src/lints.rs | 8 | ||||
| -rw-r--r-- | tests/ui/lint/forget_copy.rs | 56 | ||||
| -rw-r--r-- | tests/ui/lint/forget_copy.stderr | 104 |
5 files changed, 207 insertions, 2 deletions
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index a570f03e28c..0db4b3160df 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -529,3 +529,6 @@ lint_drop_copy = calls to `std::mem::drop` with a value that implements `Copy`. lint_forget_ref = calls to `std::mem::forget` with a reference instead of an owned value .note = argument has type `{$arg_ty}` + +lint_forget_copy = calls to `std::mem::forget` with a value that implements `Copy`. + .note = argument has type `{$arg_ty}` diff --git a/compiler/rustc_lint/src/drop_forget_useless.rs b/compiler/rustc_lint/src/drop_forget_useless.rs index 32594178fe8..e72439439a4 100644 --- a/compiler/rustc_lint/src/drop_forget_useless.rs +++ b/compiler/rustc_lint/src/drop_forget_useless.rs @@ -1,7 +1,10 @@ use rustc_hir::{Arm, Expr, ExprKind, Node}; use rustc_span::sym; -use crate::{lints::{DropRefDiag, DropCopyDiag, ForgetRefDiag}, LateContext, LateLintPass, LintContext}; +use crate::{ + lints::{DropCopyDiag, DropRefDiag, ForgetCopyDiag, ForgetRefDiag}, + LateContext, LateLintPass, LintContext, +}; declare_lint! { /// The `drop_ref` lint checks for calls to `std::mem::drop` with a reference @@ -78,7 +81,35 @@ declare_lint! { "calls to `std::mem::drop` with a value that implements Copy" } -declare_lint_pass!(DropForgetUseless => [DROP_REF, FORGET_REF, DROP_COPY]); +declare_lint! { + /// The `forget_copy` lint checks for calls to `std::mem::forget` with a value + /// that derives the Copy trait. + /// + /// ### Example + /// + /// ```rust + /// let x: i32 = 42; // i32 implements Copy + /// std::mem::forget(x); // A copy of x is passed to the function, leaving the + /// // original unaffected + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Calling `std::mem::forget` [does nothing for types that + /// implement Copy](https://doc.rust-lang.org/std/mem/fn.drop.html) since the + /// value will be copied and moved into the function on invocation. + /// + /// An alternative, but also valid, explanation is that Copy types do not + /// implement the Drop trait, which means they have no destructors. Without a + /// destructor, there is nothing for `std::mem::forget` to ignore. + pub FORGET_COPY, + Warn, + "calls to `std::mem::forget` with a value that implements Copy" +} + +declare_lint_pass!(DropForgetUseless => [DROP_REF, FORGET_REF, DROP_COPY, FORGET_COPY]); impl<'tcx> LateLintPass<'tcx> for DropForgetUseless { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { @@ -100,6 +131,9 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetUseless { sym::mem_drop if is_copy && !drop_is_single_call_in_arm => { cx.emit_spanned_lint(DROP_COPY, expr.span, DropCopyDiag { arg_ty, note: arg.span }); } + sym::mem_forget if is_copy => { + cx.emit_spanned_lint(FORGET_COPY, expr.span, ForgetCopyDiag { arg_ty, note: arg.span }); + } _ => return, }; } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 2431c3707f5..102a149a410 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -687,6 +687,14 @@ pub struct ForgetRefDiag<'a> { pub note: Span, } +#[derive(LintDiagnostic)] +#[diag(lint_forget_copy)] +pub struct ForgetCopyDiag<'a> { + pub arg_ty: Ty<'a>, + #[note] + pub note: Span, +} + // hidden_unicode_codepoints.rs #[derive(LintDiagnostic)] #[diag(lint_hidden_unicode_codepoints)] diff --git a/tests/ui/lint/forget_copy.rs b/tests/ui/lint/forget_copy.rs new file mode 100644 index 00000000000..a6b17b76971 --- /dev/null +++ b/tests/ui/lint/forget_copy.rs @@ -0,0 +1,56 @@ +// check-pass + +#![warn(forget_copy)] + +use std::mem::forget; +use std::vec::Vec; + +#[derive(Copy, Clone)] +struct SomeStruct; + +struct AnotherStruct { + x: u8, + y: u8, + z: Vec<u8>, +} + +impl Clone for AnotherStruct { + fn clone(&self) -> AnotherStruct { + AnotherStruct { + x: self.x, + y: self.y, + z: self.z.clone(), + } + } +} + +fn main() { + let s1 = SomeStruct {}; + let s2 = s1; + let s3 = &s1; + let mut s4 = s1; + let ref s5 = s1; + + forget(s1); //~ WARN calls to `std::mem::forget` + forget(s2); //~ WARN calls to `std::mem::forget` + forget(s3); //~ WARN calls to `std::mem::forget` + forget(s4); //~ WARN calls to `std::mem::forget` + forget(s5); //~ WARN calls to `std::mem::forget` + + let a1 = AnotherStruct { + x: 255, + y: 0, + z: vec![1, 2, 3], + }; + let a2 = &a1; + let mut a3 = a1.clone(); + let ref a4 = a1; + let a5 = a1.clone(); + + forget(a2); //~ WARN calls to `std::mem::forget` + let a3 = &a1; + forget(a3); //~ WARN calls to `std::mem::forget` + forget(a4); //~ WARN calls to `std::mem::forget` + let a5 = a1.clone(); + forget(a5); +} diff --git a/tests/ui/lint/forget_copy.stderr b/tests/ui/lint/forget_copy.stderr new file mode 100644 index 00000000000..d33dfa0fd3d --- /dev/null +++ b/tests/ui/lint/forget_copy.stderr @@ -0,0 +1,104 @@ +warning: calls to `std::mem::forget` with a value that implements `Copy`. + --> $DIR/forget_copy.rs:34:5 + | +LL | forget(s1); + | ^^^^^^^^^^ + | +note: argument has type `SomeStruct` + --> $DIR/forget_copy.rs:34:12 + | +LL | forget(s1); + | ^^ +note: the lint level is defined here + --> $DIR/forget_copy.rs:3:9 + | +LL | #![warn(forget_copy)] + | ^^^^^^^^^^^ + +warning: calls to `std::mem::forget` with a value that implements `Copy`. + --> $DIR/forget_copy.rs:35:5 + | +LL | forget(s2); + | ^^^^^^^^^^ + | +note: argument has type `SomeStruct` + --> $DIR/forget_copy.rs:35:12 + | +LL | forget(s2); + | ^^ + +warning: calls to `std::mem::forget` with a reference instead of an owned value + --> $DIR/forget_copy.rs:36:5 + | +LL | forget(s3); + | ^^^^^^^^^^ + | +note: argument has type `&SomeStruct` + --> $DIR/forget_copy.rs:36:12 + | +LL | forget(s3); + | ^^ + = note: `#[warn(forget_ref)]` on by default + +warning: calls to `std::mem::forget` with a value that implements `Copy`. + --> $DIR/forget_copy.rs:37:5 + | +LL | forget(s4); + | ^^^^^^^^^^ + | +note: argument has type `SomeStruct` + --> $DIR/forget_copy.rs:37:12 + | +LL | forget(s4); + | ^^ + +warning: calls to `std::mem::forget` with a reference instead of an owned value + --> $DIR/forget_copy.rs:38:5 + | +LL | forget(s5); + | ^^^^^^^^^^ + | +note: argument has type `&SomeStruct` + --> $DIR/forget_copy.rs:38:12 + | +LL | forget(s5); + | ^^ + +warning: calls to `std::mem::forget` with a reference instead of an owned value + --> $DIR/forget_copy.rs:50:5 + | +LL | forget(a2); + | ^^^^^^^^^^ + | +note: argument has type `&AnotherStruct` + --> $DIR/forget_copy.rs:50:12 + | +LL | forget(a2); + | ^^ + +warning: calls to `std::mem::forget` with a reference instead of an owned value + --> $DIR/forget_copy.rs:52:5 + | +LL | forget(a3); + | ^^^^^^^^^^ + | +note: argument has type `&AnotherStruct` + --> $DIR/forget_copy.rs:52:12 + | +LL | forget(a3); + | ^^ + +warning: calls to `std::mem::forget` with a reference instead of an owned value + --> $DIR/forget_copy.rs:53:5 + | +LL | forget(a4); + | ^^^^^^^^^^ + | +note: argument has type `&AnotherStruct` + --> $DIR/forget_copy.rs:53:12 + | +LL | forget(a4); + | ^^ + +warning: 8 warnings emitted + |
