Skip to content

Commit 1ef9c16

Browse files
committed
Uplift clippy::forget_ref to rustc
1 parent bbb24ce commit 1ef9c16

File tree

5 files changed

+193
-2
lines changed

5 files changed

+193
-2
lines changed

compiler/rustc_lint/messages.ftl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -526,3 +526,6 @@ lint_drop_ref = calls to `std::mem::drop` with a reference instead of an owned v
526526
527527
lint_drop_copy = calls to `std::mem::drop` with a value that implements `Copy`.
528528
.note = argument has type `{$arg_ty}`
529+
530+
lint_forget_ref = calls to `std::mem::forget` with a reference instead of an owned value
531+
.note = argument has type `{$arg_ty}`

compiler/rustc_lint/src/drop_forget_useless.rs

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

4-
use crate::{lints::{DropRefDiag, DropCopyDiag}, LateContext, LateLintPass, LintContext};
4+
use crate::{lints::{DropRefDiag, DropCopyDiag, ForgetRefDiag}, LateContext, LateLintPass, LintContext};
55

66
declare_lint! {
77
/// The `drop_ref` lint checks for calls to `std::mem::drop` with a reference
@@ -31,6 +31,29 @@ declare_lint! {
3131
"calls to `std::mem::drop` with a reference instead of an owned value"
3232
}
3333

34+
declare_lint! {
35+
/// The `forget_ref` lint checks for calls to `std::mem::forget` with a reference
36+
/// instead of an owned value.
37+
///
38+
/// ### Example
39+
///
40+
/// ```rust
41+
/// let x = Box::new(1);
42+
/// std::mem::forget(&x); // Should have been forget(x), x will still be dropped
43+
/// ```
44+
///
45+
/// {{produces}}
46+
///
47+
/// ### Explanation
48+
///
49+
/// Calling `forget` on a reference will only forget the
50+
/// reference itself, which is a no-op. It will not forget the underlying
51+
/// referenced value, which is likely what was intended.
52+
pub FORGET_REF,
53+
Warn,
54+
"calls to `std::mem::forget` with a reference instead of an owned value"
55+
}
56+
3457
declare_lint! {
3558
/// The `drop_copy` lint checks for calls to `std::mem::drop` with a value
3659
/// that derives the Copy trait.
@@ -55,7 +78,7 @@ declare_lint! {
5578
"calls to `std::mem::drop` with a value that implements Copy"
5679
}
5780

58-
declare_lint_pass!(DropForgetUseless => [DROP_REF, DROP_COPY]);
81+
declare_lint_pass!(DropForgetUseless => [DROP_REF, FORGET_REF, DROP_COPY]);
5982

6083
impl<'tcx> LateLintPass<'tcx> for DropForgetUseless {
6184
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
@@ -71,6 +94,9 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetUseless {
7194
sym::mem_drop if arg_ty.is_ref() && !drop_is_single_call_in_arm => {
7295
cx.emit_spanned_lint(DROP_REF, expr.span, DropRefDiag { arg_ty, note: arg.span });
7396
},
97+
sym::mem_forget if arg_ty.is_ref() => {
98+
cx.emit_spanned_lint(FORGET_REF, expr.span, ForgetRefDiag { arg_ty, note: arg.span });
99+
},
74100
sym::mem_drop if is_copy && !drop_is_single_call_in_arm => {
75101
cx.emit_spanned_lint(DROP_COPY, expr.span, DropCopyDiag { arg_ty, note: arg.span });
76102
}

compiler/rustc_lint/src/lints.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -679,6 +679,14 @@ pub struct DropCopyDiag<'a> {
679679
pub note: Span,
680680
}
681681

682+
#[derive(LintDiagnostic)]
683+
#[diag(lint_forget_ref)]
684+
pub struct ForgetRefDiag<'a> {
685+
pub arg_ty: Ty<'a>,
686+
#[note]
687+
pub note: Span,
688+
}
689+
682690
// hidden_unicode_codepoints.rs
683691
#[derive(LintDiagnostic)]
684692
#[diag(lint_hidden_unicode_codepoints)]

tests/ui/lint/forget_ref.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// check-pass
2+
3+
#![warn(forget_ref)]
4+
5+
use std::mem::forget;
6+
7+
struct SomeStruct;
8+
9+
fn main() {
10+
forget(&SomeStruct); //~ WARN calls to `std::mem::forget`
11+
12+
let mut owned = SomeStruct;
13+
forget(&owned); //~ WARN calls to `std::mem::forget`
14+
forget(&&owned); //~ WARN calls to `std::mem::forget`
15+
forget(&mut owned); //~ WARN calls to `std::mem::forget`
16+
forget(owned);
17+
18+
let reference1 = &SomeStruct;
19+
forget(&*reference1); //~ WARN calls to `std::mem::forget`
20+
21+
let reference2 = &mut SomeStruct;
22+
forget(reference2); //~ WARN calls to `std::mem::forget`
23+
24+
let ref reference3 = SomeStruct;
25+
forget(reference3); //~ WARN calls to `std::mem::forget`
26+
}
27+
28+
#[allow(dead_code)]
29+
fn test_generic_fn_forget<T>(val: T) {
30+
forget(&val); //~ WARN calls to `std::mem::forget`
31+
forget(val);
32+
}
33+
34+
#[allow(dead_code)]
35+
fn test_similarly_named_function() {
36+
fn forget<T>(_val: T) {}
37+
forget(&SomeStruct); //OK; call to unrelated function which happens to have the same name
38+
std::mem::forget(&SomeStruct); //~ WARN calls to `std::mem::forget`
39+
}

tests/ui/lint/forget_ref.stderr

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

0 commit comments

Comments
 (0)