Skip to content

Commit dc14531

Browse files
committed
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)`
2 parents 61fd2a8 + 49319b4 commit dc14531

File tree

2 files changed

+22
-2
lines changed

2 files changed

+22
-2
lines changed

clippy_lints/src/uninit_vec.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
22
use clippy_utils::higher::{get_vec_init_kind, VecInitKind};
33
use clippy_utils::ty::{is_type_diagnostic_item, is_uninit_value_valid_for_ty};
44
use clippy_utils::{is_lint_allowed, path_to_local_id, peel_hir_expr_while, SpanlessEq};
5+
use rustc_ast::ast::LitKind;
56
use rustc_hir::{Block, Expr, ExprKind, HirId, PatKind, PathSegment, Stmt, StmtKind};
67
use rustc_lint::{LateContext, LateLintPass};
78
use rustc_middle::lint::in_external_macro;
@@ -211,9 +212,12 @@ fn extract_set_len_self<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'_>) -> Opt
211212
}
212213
});
213214
match expr.kind {
214-
ExprKind::MethodCall(path, self_expr, [_], _) => {
215+
ExprKind::MethodCall(path, self_expr, [arg], _) => {
215216
let self_type = cx.typeck_results().expr_ty(self_expr).peel_refs();
216-
if is_type_diagnostic_item(cx, self_type, sym::Vec) && path.ident.name.as_str() == "set_len" {
217+
if is_type_diagnostic_item(cx, self_type, sym::Vec)
218+
&& path.ident.name.as_str() == "set_len"
219+
&& !is_literal_zero(arg)
220+
{
217221
Some((self_expr, expr.span))
218222
} else {
219223
None
@@ -222,3 +226,13 @@ fn extract_set_len_self<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'_>) -> Opt
222226
_ => None,
223227
}
224228
}
229+
230+
fn is_literal_zero(arg: &Expr<'_>) -> bool {
231+
if let ExprKind::Lit(lit) = &arg.kind
232+
&& let LitKind::Int(0, _) = lit.node
233+
{
234+
true
235+
} else {
236+
false
237+
}
238+
}

tests/ui/uninit_vec.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,4 +91,10 @@ fn main() {
9191
vec1.set_len(200);
9292
vec2.set_len(200);
9393
}
94+
95+
// set_len(0) should not be detected
96+
let mut vec: Vec<u8> = Vec::with_capacity(1000);
97+
unsafe {
98+
vec.set_len(0);
99+
}
94100
}

0 commit comments

Comments
 (0)