Skip to content

Commit 971b9b2

Browse files
committed
Uplift clippy::forget_copy to rustc
1 parent cf6d227 commit 971b9b2

File tree

5 files changed

+207
-2
lines changed

5 files changed

+207
-2
lines changed

compiler/rustc_lint/messages.ftl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,3 +529,6 @@ lint_drop_copy = calls to `std::mem::drop` with a value that implements `Copy`.
529529
530530
lint_forget_ref = calls to `std::mem::forget` with a reference instead of an owned value
531531
.note = argument has type `{$arg_ty}`
532+
533+
lint_forget_copy = calls to `std::mem::forget` with a value that implements `Copy`.
534+
.note = argument has type `{$arg_ty}`

compiler/rustc_lint/src/drop_forget_useless.rs

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
use rustc_hir::{Arm, Expr, ExprKind, Node};
22
use rustc_span::sym;
33

4-
use crate::{lints::{DropRefDiag, DropCopyDiag, ForgetRefDiag}, LateContext, LateLintPass, LintContext};
4+
use crate::{
5+
lints::{DropCopyDiag, DropRefDiag, ForgetCopyDiag, ForgetRefDiag},
6+
LateContext, LateLintPass, LintContext,
7+
};
58

69
declare_lint! {
710
/// The `drop_ref` lint checks for calls to `std::mem::drop` with a reference
@@ -78,7 +81,35 @@ declare_lint! {
7881
"calls to `std::mem::drop` with a value that implements Copy"
7982
}
8083

81-
declare_lint_pass!(DropForgetUseless => [DROP_REF, FORGET_REF, DROP_COPY]);
84+
declare_lint! {
85+
/// The `forget_copy` lint checks for calls to `std::mem::forget` with a value
86+
/// that derives the Copy trait.
87+
///
88+
/// ### Example
89+
///
90+
/// ```rust
91+
/// let x: i32 = 42; // i32 implements Copy
92+
/// std::mem::forget(x); // A copy of x is passed to the function, leaving the
93+
/// // original unaffected
94+
/// ```
95+
///
96+
/// {{produces}}
97+
///
98+
/// ### Explanation
99+
///
100+
/// Calling `std::mem::forget` [does nothing for types that
101+
/// implement Copy](https://doc.rust-lang.org/std/mem/fn.drop.html) since the
102+
/// value will be copied and moved into the function on invocation.
103+
///
104+
/// An alternative, but also valid, explanation is that Copy types do not
105+
/// implement the Drop trait, which means they have no destructors. Without a
106+
/// destructor, there is nothing for `std::mem::forget` to ignore.
107+
pub FORGET_COPY,
108+
Warn,
109+
"calls to `std::mem::forget` with a value that implements Copy"
110+
}
111+
112+
declare_lint_pass!(DropForgetUseless => [DROP_REF, FORGET_REF, DROP_COPY, FORGET_COPY]);
82113

83114
impl<'tcx> LateLintPass<'tcx> for DropForgetUseless {
84115
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
@@ -100,6 +131,9 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetUseless {
100131
sym::mem_drop if is_copy && !drop_is_single_call_in_arm => {
101132
cx.emit_spanned_lint(DROP_COPY, expr.span, DropCopyDiag { arg_ty, note: arg.span });
102133
}
134+
sym::mem_forget if is_copy => {
135+
cx.emit_spanned_lint(FORGET_COPY, expr.span, ForgetCopyDiag { arg_ty, note: arg.span });
136+
}
103137
_ => return,
104138
};
105139
}

compiler/rustc_lint/src/lints.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,14 @@ pub struct ForgetRefDiag<'a> {
687687
pub note: Span,
688688
}
689689

690+
#[derive(LintDiagnostic)]
691+
#[diag(lint_forget_copy)]
692+
pub struct ForgetCopyDiag<'a> {
693+
pub arg_ty: Ty<'a>,
694+
#[note]
695+
pub note: Span,
696+
}
697+
690698
// hidden_unicode_codepoints.rs
691699
#[derive(LintDiagnostic)]
692700
#[diag(lint_hidden_unicode_codepoints)]

tests/ui/lint/forget_copy.rs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// check-pass
2+
3+
#![warn(forget_copy)]
4+
5+
use std::mem::forget;
6+
use std::vec::Vec;
7+
8+
#[derive(Copy, Clone)]
9+
struct SomeStruct;
10+
11+
struct AnotherStruct {
12+
x: u8,
13+
y: u8,
14+
z: Vec<u8>,
15+
}
16+
17+
impl Clone for AnotherStruct {
18+
fn clone(&self) -> AnotherStruct {
19+
AnotherStruct {
20+
x: self.x,
21+
y: self.y,
22+
z: self.z.clone(),
23+
}
24+
}
25+
}
26+
27+
fn main() {
28+
let s1 = SomeStruct {};
29+
let s2 = s1;
30+
let s3 = &s1;
31+
let mut s4 = s1;
32+
let ref s5 = s1;
33+
34+
forget(s1); //~ WARN calls to `std::mem::forget`
35+
forget(s2); //~ WARN calls to `std::mem::forget`
36+
forget(s3); //~ WARN calls to `std::mem::forget`
37+
forget(s4); //~ WARN calls to `std::mem::forget`
38+
forget(s5); //~ WARN calls to `std::mem::forget`
39+
40+
let a1 = AnotherStruct {
41+
x: 255,
42+
y: 0,
43+
z: vec![1, 2, 3],
44+
};
45+
let a2 = &a1;
46+
let mut a3 = a1.clone();
47+
let ref a4 = a1;
48+
let a5 = a1.clone();
49+
50+
forget(a2); //~ WARN calls to `std::mem::forget`
51+
let a3 = &a1;
52+
forget(a3); //~ WARN calls to `std::mem::forget`
53+
forget(a4); //~ WARN calls to `std::mem::forget`
54+
let a5 = a1.clone();
55+
forget(a5);
56+
}

tests/ui/lint/forget_copy.stderr

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
warning: calls to `std::mem::forget` with a value that implements `Copy`.
2+
--> $DIR/forget_copy.rs:34:5
3+
|
4+
LL | forget(s1);
5+
| ^^^^^^^^^^
6+
|
7+
note: argument has type `SomeStruct`
8+
--> $DIR/forget_copy.rs:34:12
9+
|
10+
LL | forget(s1);
11+
| ^^
12+
note: the lint level is defined here
13+
--> $DIR/forget_copy.rs:3:9
14+
|
15+
LL | #![warn(forget_copy)]
16+
| ^^^^^^^^^^^
17+
18+
warning: calls to `std::mem::forget` with a value that implements `Copy`.
19+
--> $DIR/forget_copy.rs:35:5
20+
|
21+
LL | forget(s2);
22+
| ^^^^^^^^^^
23+
|
24+
note: argument has type `SomeStruct`
25+
--> $DIR/forget_copy.rs:35:12
26+
|
27+
LL | forget(s2);
28+
| ^^
29+
30+
warning: calls to `std::mem::forget` with a reference instead of an owned value
31+
--> $DIR/forget_copy.rs:36:5
32+
|
33+
LL | forget(s3);
34+
| ^^^^^^^^^^
35+
|
36+
note: argument has type `&SomeStruct`
37+
--> $DIR/forget_copy.rs:36:12
38+
|
39+
LL | forget(s3);
40+
| ^^
41+
= note: `#[warn(forget_ref)]` on by default
42+
43+
warning: calls to `std::mem::forget` with a value that implements `Copy`.
44+
--> $DIR/forget_copy.rs:37:5
45+
|
46+
LL | forget(s4);
47+
| ^^^^^^^^^^
48+
|
49+
note: argument has type `SomeStruct`
50+
--> $DIR/forget_copy.rs:37:12
51+
|
52+
LL | forget(s4);
53+
| ^^
54+
55+
warning: calls to `std::mem::forget` with a reference instead of an owned value
56+
--> $DIR/forget_copy.rs:38:5
57+
|
58+
LL | forget(s5);
59+
| ^^^^^^^^^^
60+
|
61+
note: argument has type `&SomeStruct`
62+
--> $DIR/forget_copy.rs:38:12
63+
|
64+
LL | forget(s5);
65+
| ^^
66+
67+
warning: calls to `std::mem::forget` with a reference instead of an owned value
68+
--> $DIR/forget_copy.rs:50:5
69+
|
70+
LL | forget(a2);
71+
| ^^^^^^^^^^
72+
|
73+
note: argument has type `&AnotherStruct`
74+
--> $DIR/forget_copy.rs:50:12
75+
|
76+
LL | forget(a2);
77+
| ^^
78+
79+
warning: calls to `std::mem::forget` with a reference instead of an owned value
80+
--> $DIR/forget_copy.rs:52:5
81+
|
82+
LL | forget(a3);
83+
| ^^^^^^^^^^
84+
|
85+
note: argument has type `&AnotherStruct`
86+
--> $DIR/forget_copy.rs:52:12
87+
|
88+
LL | forget(a3);
89+
| ^^
90+
91+
warning: calls to `std::mem::forget` with a reference instead of an owned value
92+
--> $DIR/forget_copy.rs:53:5
93+
|
94+
LL | forget(a4);
95+
| ^^^^^^^^^^
96+
|
97+
note: argument has type `&AnotherStruct`
98+
--> $DIR/forget_copy.rs:53:12
99+
|
100+
LL | forget(a4);
101+
| ^^
102+
103+
warning: 8 warnings emitted
104+

0 commit comments

Comments
 (0)