Skip to content

Commit

Permalink
Improve error messages
Browse files Browse the repository at this point in the history
  • Loading branch information
Qwaz committed Oct 9, 2021
1 parent 759200b commit fdc06d9
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 27 deletions.
14 changes: 8 additions & 6 deletions clippy_lints/src/uninit_vec.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use clippy_utils::diagnostics::span_lint_and_note;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::{
match_def_path, path_to_local_id, paths, peel_hir_expr_while, ty::is_uninit_value_valid_for_ty, SpanlessEq,
Expand Down Expand Up @@ -71,13 +71,14 @@ fn handle_uninit_vec_pair(
// Check T of Vec<T>
if !is_uninit_value_valid_for_ty(cx, substs.type_at(0));
then {
span_lint_and_note(
span_lint_and_then(
cx,
UNINIT_VEC,
call_span,
vec![call_span, maybe_with_capacity_or_reserve.span],
"calling `set_len()` immediately after reserving a buffer creates uninitialized values",
Some(maybe_with_capacity_or_reserve.span),
"the buffer is reserved here"
|diag| {
diag.help("initialize the buffer or wrap the content in `MaybeUninit`");
},
);
}
}
Expand Down Expand Up @@ -155,9 +156,10 @@ fn extract_set_len_self(cx: &LateContext<'_>, expr: &'tcx Expr<'_>) -> Option<(&
// peel unsafe blocks in `unsafe { vec.set_len() }`
let expr = peel_hir_expr_while(expr, |e| {
if let ExprKind::Block(block, _) = e.kind {
// Extract the first statement/expression
match (block.stmts.get(0).map(|stmt| &stmt.kind), block.expr) {
(None, Some(expr)) => Some(expr),
(Some(StmtKind::Expr(expr) | StmtKind::Semi(expr)), None) => Some(expr),
(Some(StmtKind::Expr(expr) | StmtKind::Semi(expr)), _) => Some(expr),
_ => None,
}
} else {
Expand Down
32 changes: 32 additions & 0 deletions tests/ui/uninit_vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

use std::mem::MaybeUninit;

#[derive(Default)]
struct MyVec {
vec: Vec<u8>,
}

fn main() {
// with_capacity() -> set_len() should be detected
let mut vec: Vec<u8> = Vec::with_capacity(1000);
Expand All @@ -24,6 +29,25 @@ fn main() {
vec.set_len(200);
}

let mut vec: Vec<u8> = Vec::with_capacity(1000);
unsafe {
// test the case where there are other statements in the following unsafe block
vec.set_len(200);
assert!(vec.len() == 200);
}

// handle vec stored in the field of a struct
let mut my_vec = MyVec::default();
my_vec.vec.reserve(1000);
unsafe {
my_vec.vec.set_len(200);
}

my_vec.vec = Vec::with_capacity(1000);
unsafe {
my_vec.vec.set_len(200);
}

// MaybeUninit-wrapped types should not be detected
unsafe {
let mut vec: Vec<MaybeUninit<u8>> = Vec::with_capacity(1000);
Expand All @@ -35,4 +59,12 @@ fn main() {
let mut vec: Vec<(MaybeUninit<u8>, [MaybeUninit<bool>; 2])> = Vec::with_capacity(1000);
vec.set_len(200);
}

// known false negative
let mut vec1: Vec<u8> = Vec::with_capacity(1000);
let mut vec2: Vec<u8> = Vec::with_capacity(1000);
unsafe {
vec1.reserve(200);
vec2.reserve(200);
}
}
69 changes: 48 additions & 21 deletions tests/ui/uninit_vec.stderr
Original file line number Diff line number Diff line change
@@ -1,51 +1,78 @@
error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
--> $DIR/uninit_vec.rs:9:9
--> $DIR/uninit_vec.rs:12:5
|
LL | let mut vec: Vec<u8> = Vec::with_capacity(1000);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | unsafe {
LL | vec.set_len(200);
| ^^^^^^^^^^^^^^^^
|
= note: `-D clippy::uninit-vec` implied by `-D warnings`
note: the buffer is reserved here
--> $DIR/uninit_vec.rs:7:5
|
LL | let mut vec: Vec<u8> = Vec::with_capacity(1000);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= help: initialize the buffer or wrap the content in `MaybeUninit`

error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
--> $DIR/uninit_vec.rs:15:9
--> $DIR/uninit_vec.rs:18:5
|
LL | vec.reserve(1000);
| ^^^^^^^^^^^^^^^^^^
LL | unsafe {
LL | vec.set_len(200);
| ^^^^^^^^^^^^^^^^
|
note: the buffer is reserved here
--> $DIR/uninit_vec.rs:13:5
|
LL | vec.reserve(1000);
| ^^^^^^^^^^^^^^^^^^
= help: initialize the buffer or wrap the content in `MaybeUninit`

error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
--> $DIR/uninit_vec.rs:21:9
--> $DIR/uninit_vec.rs:32:5
|
LL | let mut vec: Vec<u8> = Vec::with_capacity(1000);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...
LL | vec.set_len(200);
| ^^^^^^^^^^^^^^^^
|
note: the buffer is reserved here
--> $DIR/uninit_vec.rs:20:9
= help: initialize the buffer or wrap the content in `MaybeUninit`

error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
--> $DIR/uninit_vec.rs:41:5
|
LL | my_vec.vec.reserve(1000);
| ^^^^^^^^^^^^^^^^^^^^^^^^^
LL | unsafe {
LL | my_vec.vec.set_len(200);
| ^^^^^^^^^^^^^^^^^^^^^^^
|
LL | let mut vec: Vec<u8> = Vec::with_capacity(1000);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= help: initialize the buffer or wrap the content in `MaybeUninit`

error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
--> $DIR/uninit_vec.rs:46:5
|
LL | my_vec.vec = Vec::with_capacity(1000);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | unsafe {
LL | my_vec.vec.set_len(200);
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= help: initialize the buffer or wrap the content in `MaybeUninit`

error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
--> $DIR/uninit_vec.rs:24:9
--> $DIR/uninit_vec.rs:25:9
|
LL | let mut vec: Vec<u8> = Vec::with_capacity(1000);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | vec.set_len(200);
| ^^^^^^^^^^^^^^^^
|
note: the buffer is reserved here
--> $DIR/uninit_vec.rs:23:9
= help: initialize the buffer or wrap the content in `MaybeUninit`

error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
--> $DIR/uninit_vec.rs:28:9
|
LL | vec.reserve(1000);
| ^^^^^^^^^^^^^^^^^^
LL | vec.set_len(200);
| ^^^^^^^^^^^^^^^^
|
= help: initialize the buffer or wrap the content in `MaybeUninit`

error: aborting due to 4 previous errors
error: aborting due to 7 previous errors

0 comments on commit fdc06d9

Please sign in to comment.