Skip to content

Commit 17d4ac5

Browse files
committed
Improve error messages
1 parent f8d170b commit 17d4ac5

File tree

3 files changed

+88
-27
lines changed

3 files changed

+88
-27
lines changed

clippy_lints/src/uninit_vec.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use clippy_utils::diagnostics::span_lint_and_note;
1+
use clippy_utils::diagnostics::span_lint_and_then;
22
use clippy_utils::ty::is_type_diagnostic_item;
33
use clippy_utils::{
44
match_def_path, path_to_local_id, paths, peel_hir_expr_while, ty::is_uninit_value_valid_for_ty, SpanlessEq,
@@ -71,13 +71,14 @@ fn handle_uninit_vec_pair(
7171
// Check T of Vec<T>
7272
if !is_uninit_value_valid_for_ty(cx, substs.type_at(0));
7373
then {
74-
span_lint_and_note(
74+
span_lint_and_then(
7575
cx,
7676
UNINIT_VEC,
77-
call_span,
77+
vec![call_span, maybe_with_capacity_or_reserve.span],
7878
"calling `set_len()` immediately after reserving a buffer creates uninitialized values",
79-
Some(maybe_with_capacity_or_reserve.span),
80-
"the buffer is reserved here"
79+
|diag| {
80+
diag.help("initialize the buffer or wrap the content in `MaybeUninit`");
81+
},
8182
);
8283
}
8384
}
@@ -155,9 +156,10 @@ fn extract_set_len_self(cx: &LateContext<'_>, expr: &'tcx Expr<'_>) -> Option<(&
155156
// peel unsafe blocks in `unsafe { vec.set_len() }`
156157
let expr = peel_hir_expr_while(expr, |e| {
157158
if let ExprKind::Block(block, _) = e.kind {
159+
// Extract the first statement/expression
158160
match (block.stmts.get(0).map(|stmt| &stmt.kind), block.expr) {
159161
(None, Some(expr)) => Some(expr),
160-
(Some(StmtKind::Expr(expr) | StmtKind::Semi(expr)), None) => Some(expr),
162+
(Some(StmtKind::Expr(expr) | StmtKind::Semi(expr)), _) => Some(expr),
161163
_ => None,
162164
}
163165
} else {

tests/ui/uninit_vec.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22

33
use std::mem::MaybeUninit;
44

5+
#[derive(Default)]
6+
struct MyVec {
7+
vec: Vec<u8>,
8+
}
9+
510
fn main() {
611
// with_capacity() -> set_len() should be detected
712
let mut vec: Vec<u8> = Vec::with_capacity(1000);
@@ -24,6 +29,25 @@ fn main() {
2429
vec.set_len(200);
2530
}
2631

32+
let mut vec: Vec<u8> = Vec::with_capacity(1000);
33+
unsafe {
34+
// test the case where there are other statements in the following unsafe block
35+
vec.set_len(200);
36+
assert!(vec.len() == 200);
37+
}
38+
39+
// handle vec stored in the field of a struct
40+
let mut my_vec = MyVec::default();
41+
my_vec.vec.reserve(1000);
42+
unsafe {
43+
my_vec.vec.set_len(200);
44+
}
45+
46+
my_vec.vec = Vec::with_capacity(1000);
47+
unsafe {
48+
my_vec.vec.set_len(200);
49+
}
50+
2751
// MaybeUninit-wrapped types should not be detected
2852
unsafe {
2953
let mut vec: Vec<MaybeUninit<u8>> = Vec::with_capacity(1000);
@@ -35,4 +59,12 @@ fn main() {
3559
let mut vec: Vec<(MaybeUninit<u8>, [MaybeUninit<bool>; 2])> = Vec::with_capacity(1000);
3660
vec.set_len(200);
3761
}
62+
63+
// known false negative
64+
let mut vec1: Vec<u8> = Vec::with_capacity(1000);
65+
let mut vec2: Vec<u8> = Vec::with_capacity(1000);
66+
unsafe {
67+
vec1.reserve(200);
68+
vec2.reserve(200);
69+
}
3870
}

tests/ui/uninit_vec.stderr

Lines changed: 48 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,78 @@
11
error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
2-
--> $DIR/uninit_vec.rs:9:9
2+
--> $DIR/uninit_vec.rs:12:5
33
|
4+
LL | let mut vec: Vec<u8> = Vec::with_capacity(1000);
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
LL | unsafe {
47
LL | vec.set_len(200);
58
| ^^^^^^^^^^^^^^^^
69
|
710
= note: `-D clippy::uninit-vec` implied by `-D warnings`
8-
note: the buffer is reserved here
9-
--> $DIR/uninit_vec.rs:7:5
10-
|
11-
LL | let mut vec: Vec<u8> = Vec::with_capacity(1000);
12-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
11+
= help: initialize the buffer or wrap the content in `MaybeUninit`
1312

1413
error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
15-
--> $DIR/uninit_vec.rs:15:9
14+
--> $DIR/uninit_vec.rs:18:5
1615
|
16+
LL | vec.reserve(1000);
17+
| ^^^^^^^^^^^^^^^^^^
18+
LL | unsafe {
1719
LL | vec.set_len(200);
1820
| ^^^^^^^^^^^^^^^^
1921
|
20-
note: the buffer is reserved here
21-
--> $DIR/uninit_vec.rs:13:5
22-
|
23-
LL | vec.reserve(1000);
24-
| ^^^^^^^^^^^^^^^^^^
22+
= help: initialize the buffer or wrap the content in `MaybeUninit`
2523

2624
error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
27-
--> $DIR/uninit_vec.rs:21:9
25+
--> $DIR/uninit_vec.rs:32:5
2826
|
27+
LL | let mut vec: Vec<u8> = Vec::with_capacity(1000);
28+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
29+
...
2930
LL | vec.set_len(200);
3031
| ^^^^^^^^^^^^^^^^
3132
|
32-
note: the buffer is reserved here
33-
--> $DIR/uninit_vec.rs:20:9
33+
= help: initialize the buffer or wrap the content in `MaybeUninit`
34+
35+
error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
36+
--> $DIR/uninit_vec.rs:41:5
37+
|
38+
LL | my_vec.vec.reserve(1000);
39+
| ^^^^^^^^^^^^^^^^^^^^^^^^^
40+
LL | unsafe {
41+
LL | my_vec.vec.set_len(200);
42+
| ^^^^^^^^^^^^^^^^^^^^^^^
3443
|
35-
LL | let mut vec: Vec<u8> = Vec::with_capacity(1000);
36-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
44+
= help: initialize the buffer or wrap the content in `MaybeUninit`
45+
46+
error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
47+
--> $DIR/uninit_vec.rs:46:5
48+
|
49+
LL | my_vec.vec = Vec::with_capacity(1000);
50+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
51+
LL | unsafe {
52+
LL | my_vec.vec.set_len(200);
53+
| ^^^^^^^^^^^^^^^^^^^^^^^
54+
|
55+
= help: initialize the buffer or wrap the content in `MaybeUninit`
3756

3857
error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
39-
--> $DIR/uninit_vec.rs:24:9
58+
--> $DIR/uninit_vec.rs:25:9
4059
|
60+
LL | let mut vec: Vec<u8> = Vec::with_capacity(1000);
61+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4162
LL | vec.set_len(200);
4263
| ^^^^^^^^^^^^^^^^
4364
|
44-
note: the buffer is reserved here
45-
--> $DIR/uninit_vec.rs:23:9
65+
= help: initialize the buffer or wrap the content in `MaybeUninit`
66+
67+
error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
68+
--> $DIR/uninit_vec.rs:28:9
4669
|
4770
LL | vec.reserve(1000);
4871
| ^^^^^^^^^^^^^^^^^^
72+
LL | vec.set_len(200);
73+
| ^^^^^^^^^^^^^^^^
74+
|
75+
= help: initialize the buffer or wrap the content in `MaybeUninit`
4976

50-
error: aborting due to 4 previous errors
77+
error: aborting due to 7 previous errors
5178

0 commit comments

Comments
 (0)