Skip to content

Commit 3b5b2ed

Browse files
committed
Auto merge of rust-lang#10492 - schubart:collection_is_never_read_unit_type, r=Manishearth
`collection_is_never_read`: Handle unit type changelog: [`collection_is_never_read`]: Fix false negative fixes: rust-lang#10488
2 parents 5ec2e19 + 3d71145 commit 3b5b2ed

File tree

3 files changed

+44
-14
lines changed

3 files changed

+44
-14
lines changed

clippy_lints/src/collection_is_never_read.rs

+17-4
Original file line numberDiff line numberDiff line change
@@ -101,21 +101,34 @@ fn has_no_read_access<'tcx>(cx: &LateContext<'tcx>, id: HirId, block: &'tcx Bloc
101101
return ControlFlow::Continue(());
102102
}
103103

104-
// Method call on `id` in a statement ignores any return value, so it's not a read access:
104+
// Look for method call with receiver `id`. It might be a non-read access:
105105
//
106-
// id.foo(...); // Not reading `id`.
106+
// id.foo(args)
107107
//
108108
// Only assuming this for "official" methods defined on the type. For methods defined in extension
109109
// traits (identified as local, based on the orphan rule), pessimistically assume that they might
110110
// have side effects, so consider them a read.
111111
if let Some(Node::Expr(parent)) = get_parent_node(cx.tcx, expr.hir_id)
112112
&& let ExprKind::MethodCall(_, receiver, _, _) = parent.kind
113113
&& path_to_local_id(receiver, id)
114-
&& let Some(Node::Stmt(..)) = get_parent_node(cx.tcx, parent.hir_id)
115114
&& let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(parent.hir_id)
116115
&& !method_def_id.is_local()
117116
{
118-
return ControlFlow::Continue(());
117+
// The method call is a statement, so the return value is not used. That's not a read access:
118+
//
119+
// id.foo(args);
120+
if let Some(Node::Stmt(..)) = get_parent_node(cx.tcx, parent.hir_id) {
121+
return ControlFlow::Continue(());
122+
}
123+
124+
// The method call is not a statement, so its return value is used somehow but its type is the
125+
// unit type, so this is not a real read access. Examples:
126+
//
127+
// let y = x.clear();
128+
// println!("{:?}", x.clear());
129+
if cx.typeck_results().expr_ty(parent).is_unit() {
130+
return ControlFlow::Continue(());
131+
}
119132
}
120133

121134
// Any other access to `id` is a read access. Stop searching.

tests/ui/collection_is_never_read.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -84,13 +84,18 @@ fn shadowing_2() {
8484
}
8585

8686
#[allow(clippy::let_unit_value)]
87-
fn fake_read() {
88-
let mut x = vec![1, 2, 3]; // Ok
87+
fn fake_read_1() {
88+
let mut x = vec![1, 2, 3]; // WARNING
8989
x.reverse();
90-
// `collection_is_never_read` gets fooled, but other lints should catch this.
9190
let _: () = x.clear();
9291
}
9392

93+
fn fake_read_2() {
94+
let mut x = vec![1, 2, 3]; // WARNING
95+
x.reverse();
96+
println!("{:?}", x.push(5));
97+
}
98+
9499
fn assignment() {
95100
let mut x = vec![1, 2, 3]; // WARNING
96101
let y = vec![4, 5, 6]; // Ok

tests/ui/collection_is_never_read.stderr

+19-7
Original file line numberDiff line numberDiff line change
@@ -25,40 +25,52 @@ LL | let mut x = HashMap::new(); // WARNING
2525
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
2626

2727
error: collection is never read
28-
--> $DIR/collection_is_never_read.rs:95:5
28+
--> $DIR/collection_is_never_read.rs:88:5
2929
|
3030
LL | let mut x = vec![1, 2, 3]; // WARNING
3131
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
3232

3333
error: collection is never read
34-
--> $DIR/collection_is_never_read.rs:102:5
34+
--> $DIR/collection_is_never_read.rs:94:5
3535
|
3636
LL | let mut x = vec![1, 2, 3]; // WARNING
3737
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
3838

3939
error: collection is never read
40-
--> $DIR/collection_is_never_read.rs:119:5
40+
--> $DIR/collection_is_never_read.rs:100:5
41+
|
42+
LL | let mut x = vec![1, 2, 3]; // WARNING
43+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
44+
45+
error: collection is never read
46+
--> $DIR/collection_is_never_read.rs:107:5
47+
|
48+
LL | let mut x = vec![1, 2, 3]; // WARNING
49+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
50+
51+
error: collection is never read
52+
--> $DIR/collection_is_never_read.rs:124:5
4153
|
4254
LL | let mut x = HashSet::new(); // WARNING
4355
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
4456

4557
error: collection is never read
46-
--> $DIR/collection_is_never_read.rs:133:5
58+
--> $DIR/collection_is_never_read.rs:138:5
4759
|
4860
LL | let x = vec![1, 2, 3]; // WARNING
4961
| ^^^^^^^^^^^^^^^^^^^^^^
5062

5163
error: collection is never read
52-
--> $DIR/collection_is_never_read.rs:169:5
64+
--> $DIR/collection_is_never_read.rs:174:5
5365
|
5466
LL | let mut s = String::new();
5567
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
5668

5769
error: collection is never read
58-
--> $DIR/collection_is_never_read.rs:182:5
70+
--> $DIR/collection_is_never_read.rs:187:5
5971
|
6072
LL | let mut s = String::from("Hello, World!");
6173
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6274

63-
error: aborting due to 10 previous errors
75+
error: aborting due to 12 previous errors
6476

0 commit comments

Comments
 (0)