Skip to content

Commit 156f556

Browse files
committed
Uplift clippy::drop_copy to rustc
1 parent 3d1940d commit 156f556

File tree

5 files changed

+248
-2
lines changed

5 files changed

+248
-2
lines changed

compiler/rustc_lint/messages.ftl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,3 +523,6 @@ lint_opaque_hidden_inferred_bound_sugg = add this bound
523523
524524
lint_drop_ref = calls to `std::mem::drop` with a reference instead of an owned value
525525
.note = argument has type `{$arg_ty}`
526+
527+
lint_drop_copy = calls to `std::mem::drop` with a value that implements `Copy`.
528+
.note = argument has type `{$arg_ty}`

compiler/rustc_lint/src/drop_forget_useless.rs

Lines changed: 30 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, LateContext, LateLintPass, LintContext};
4+
use crate::{lints::{DropRefDiag, DropCopyDiag}, LateContext, LateLintPass, LintContext};
55

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

34-
declare_lint_pass!(DropForgetUseless => [DROP_REF]);
34+
declare_lint! {
35+
/// The `drop_copy` lint checks for calls to `std::mem::drop` with a value
36+
/// that derives the Copy trait.
37+
///
38+
/// ### Example
39+
///
40+
/// ```rust
41+
/// let x: i32 = 42; // i32 implements Copy
42+
/// std::mem::drop(x); // A copy of x is passed to the function, leaving the
43+
/// // original unaffected
44+
/// ```
45+
///
46+
/// {{produces}}
47+
///
48+
/// ### Explanation
49+
///
50+
/// Calling `std::mem::drop` [does nothing for types that
51+
/// implement Copy](https://doc.rust-lang.org/std/mem/fn.drop.html), since the
52+
/// value will be copied and moved into the function on invocation.
53+
pub DROP_COPY,
54+
Warn,
55+
"calls to `std::mem::drop` with a value that implements Copy"
56+
}
57+
58+
declare_lint_pass!(DropForgetUseless => [DROP_REF, DROP_COPY]);
3559

3660
impl<'tcx> LateLintPass<'tcx> for DropForgetUseless {
3761
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
@@ -41,11 +65,15 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetUseless {
4165
&& let Some(fn_name) = cx.tcx.get_diagnostic_name(def_id)
4266
{
4367
let arg_ty = cx.typeck_results().expr_ty(arg);
68+
let is_copy = arg_ty.is_copy_modulo_regions(cx.tcx, cx.param_env);
4469
let drop_is_single_call_in_arm = is_single_call_in_arm(cx, arg, expr);
4570
match fn_name {
4671
sym::mem_drop if arg_ty.is_ref() && !drop_is_single_call_in_arm => {
4772
cx.emit_spanned_lint(DROP_REF, expr.span, DropRefDiag { arg_ty, note: arg.span });
4873
},
74+
sym::mem_drop if is_copy && !drop_is_single_call_in_arm => {
75+
cx.emit_spanned_lint(DROP_COPY, expr.span, DropCopyDiag { arg_ty, note: arg.span });
76+
}
4977
_ => return,
5078
};
5179
}

compiler/rustc_lint/src/lints.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -671,6 +671,14 @@ pub struct DropRefDiag<'a> {
671671
pub note: Span,
672672
}
673673

674+
#[derive(LintDiagnostic)]
675+
#[diag(lint_drop_copy)]
676+
pub struct DropCopyDiag<'a> {
677+
pub arg_ty: Ty<'a>,
678+
#[note]
679+
pub note: Span,
680+
}
681+
674682
// hidden_unicode_codepoints.rs
675683
#[derive(LintDiagnostic)]
676684
#[diag(lint_hidden_unicode_codepoints)]

tests/ui/lint/drop_copy.rs

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// check-pass
2+
3+
#![warn(drop_copy)]
4+
5+
use std::mem::drop;
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+
drop(s1); //~ WARN calls to `std::mem::drop`
35+
drop(s2); //~ WARN calls to `std::mem::drop`
36+
drop(s3); //~ WARN calls to `std::mem::drop`
37+
drop(s4); //~ WARN calls to `std::mem::drop`
38+
drop(s5); //~ WARN calls to `std::mem::drop`
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+
drop(a2); //~ WARN calls to `std::mem::drop`
51+
drop(a3);
52+
drop(a4); //~ WARN calls to `std::mem::drop`
53+
drop(a5);
54+
}
55+
56+
#[allow(unused)]
57+
#[allow(clippy::unit_cmp)]
58+
fn issue9482(x: u8) {
59+
fn println_and<T>(t: T) -> T {
60+
println!("foo");
61+
t
62+
}
63+
64+
match x {
65+
// Don't lint (copy type), we only care about side-effects
66+
0 => drop(println_and(12)),
67+
// Don't lint (no copy type), we only care about side-effects
68+
1 => drop(println_and(String::new())),
69+
2 => {
70+
// Lint, even if we only care about the side-effect, it's already in a block
71+
drop(println_and(13)); //~ WARN calls to `std::mem::drop`
72+
},
73+
// Lint, idiomatic use is only in body of `Arm`
74+
3 if drop(println_and(14)) == () => (), //~ WARN calls to `std::mem::drop`
75+
// Lint, not a fn/method call
76+
4 => drop(2),//~ WARN calls to `std::mem::drop`
77+
_ => (),
78+
}
79+
}

tests/ui/lint/drop_copy.stderr

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

0 commit comments

Comments
 (0)