mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-23 21:23:56 +00:00
uninit_vec: special case set_len(0)
set_len(0) does not create uninitialized elements. Fixes a false positive with the following pattern: 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()); } }
This commit is contained in:
parent
61fd2a8c6f
commit
49319b4206
2 changed files with 22 additions and 2 deletions
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue