diff options
| author | bors <bors@rust-lang.org> | 2022-09-23 15:37:13 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2022-09-23 15:37:13 +0000 |
| commit | dc14531fe9fca306fa56ab38191e3aadfa4e85c6 (patch) | |
| tree | 12e29e6af047c72eccace0230ecac2f0e27cfecf | |
| parent | 61fd2a8c6f8336ea12fe5b6fd1051fcf5a7b915e (diff) | |
| parent | 49319b4206cbde83e0113c024b09275677ab8d74 (diff) | |
| download | rust-dc14531fe9fca306fa56ab38191e3aadfa4e85c6.tar.gz rust-dc14531fe9fca306fa56ab38191e3aadfa4e85c6.zip | |
Auto merge of #9519 - alessandrod:uninit-set-len-0, r=llogiq
uninit_vec: fix false positive with set_len(0)
`set_len(0)` does not create uninitialized elements. Fixes a false positive with the following pattern:
```rust
fn copy_slice_into_vec(dst: &mut Vec<u8>, src: &[u8]) {
dst.reserve(src.len().saturating_sub(dst.len()));
unsafe {
dst.set_len(0);
std::ptr::copy_nonoverlapping(src.as_ptr(), dst.as_mut_ptr(), src.len());
dst.set_len(src.len());
}
}
```
zulip thread: https://rust-lang.zulipchat.com/#narrow/stream/257328-clippy/topic/uninit_vec.20and.20set_len.280.29
changelog: FP: [`uninit_vec`]: No longer lints `Vec::set_len(0)`
| -rw-r--r-- | clippy_lints/src/uninit_vec.rs | 18 | ||||
| -rw-r--r-- | tests/ui/uninit_vec.rs | 6 |
2 files changed, 22 insertions, 2 deletions
diff --git a/clippy_lints/src/uninit_vec.rs b/clippy_lints/src/uninit_vec.rs index 3f99bd3f315..bde7c318f44 100644 --- a/clippy_lints/src/uninit_vec.rs +++ b/clippy_lints/src/uninit_vec.rs @@ -2,6 +2,7 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; use clippy_utils::higher::{get_vec_init_kind, VecInitKind}; use clippy_utils::ty::{is_type_diagnostic_item, is_uninit_value_valid_for_ty}; use clippy_utils::{is_lint_allowed, path_to_local_id, peel_hir_expr_while, SpanlessEq}; +use rustc_ast::ast::LitKind; use rustc_hir::{Block, Expr, ExprKind, HirId, PatKind, PathSegment, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::lint::in_external_macro; @@ -211,9 +212,12 @@ fn extract_set_len_self<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'_>) -> Opt } }); match expr.kind { - ExprKind::MethodCall(path, self_expr, [_], _) => { + ExprKind::MethodCall(path, self_expr, [arg], _) => { let self_type = cx.typeck_results().expr_ty(self_expr).peel_refs(); - if is_type_diagnostic_item(cx, self_type, sym::Vec) && path.ident.name.as_str() == "set_len" { + if is_type_diagnostic_item(cx, self_type, sym::Vec) + && path.ident.name.as_str() == "set_len" + && !is_literal_zero(arg) + { Some((self_expr, expr.span)) } else { None @@ -222,3 +226,13 @@ fn extract_set_len_self<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'_>) -> Opt _ => None, } } + +fn is_literal_zero(arg: &Expr<'_>) -> bool { + if let ExprKind::Lit(lit) = &arg.kind + && let LitKind::Int(0, _) = lit.node + { + true + } else { + false + } +} diff --git a/tests/ui/uninit_vec.rs b/tests/ui/uninit_vec.rs index dc150cf28f2..194e4fc157e 100644 --- a/tests/ui/uninit_vec.rs +++ b/tests/ui/uninit_vec.rs @@ -91,4 +91,10 @@ fn main() { vec1.set_len(200); vec2.set_len(200); } + + // set_len(0) should not be detected + let mut vec: Vec<u8> = Vec::with_capacity(1000); + unsafe { + vec.set_len(0); + } } |
