11use clippy_utils:: diagnostics:: span_lint_and_then;
2- use clippy_utils:: get_vec_init_kind;
3- use clippy_utils:: ty:: is_type_diagnostic_item;
4- use clippy_utils:: { path_to_local_id , peel_hir_expr_while , ty :: is_uninit_value_valid_for_ty , SpanlessEq } ;
2+ use clippy_utils:: higher :: get_vec_init_kind;
3+ use clippy_utils:: ty:: { is_type_diagnostic_item, is_uninit_value_valid_for_ty } ;
4+ use clippy_utils:: { is_lint_allowed , path_to_local_id , peel_hir_expr_while , SpanlessEq } ;
55use rustc_hir:: { Block , Expr , ExprKind , HirId , PatKind , PathSegment , Stmt , StmtKind } ;
66use rustc_lint:: { LateContext , LateLintPass } ;
7+ use rustc_middle:: lint:: in_external_macro;
78use rustc_middle:: ty;
89use rustc_session:: { declare_lint_pass, declare_tool_lint} ;
910use rustc_span:: { sym, Span } ;
@@ -16,10 +17,14 @@ declare_clippy_lint! {
1617 /// `with_capacity()` or `reserve()`.
1718 ///
1819 /// ### Why is this bad?
19- /// It creates a `Vec` with uninitialized data, which leads to an
20+ /// It creates a `Vec` with uninitialized data, which leads to
2021 /// undefined behavior with most safe operations.
22+ ///
2123 /// Notably, uninitialized `Vec<u8>` must not be used with generic `Read`.
2224 ///
25+ /// ### Known Problems
26+ /// This lint only checks directly adjacent statements.
27+ ///
2328 /// ### Example
2429 /// ```rust,ignore
2530 /// let mut vec: Vec<u8> = Vec::with_capacity(1000);
@@ -52,16 +57,20 @@ declare_clippy_lint! {
5257
5358declare_lint_pass ! ( UninitVec => [ UNINIT_VEC ] ) ;
5459
60+ // FIXME: update to a visitor-based implementation.
61+ // Threads: https://github.com/rust-lang/rust-clippy/pull/7682#discussion_r710998368
5562impl < ' tcx > LateLintPass < ' tcx > for UninitVec {
5663 fn check_block ( & mut self , cx : & LateContext < ' tcx > , block : & ' tcx Block < ' _ > ) {
57- for w in block. stmts . windows ( 2 ) {
58- if let StmtKind :: Expr ( expr) | StmtKind :: Semi ( expr) = w[ 1 ] . kind {
59- handle_uninit_vec_pair ( cx, & w[ 0 ] , expr) ;
64+ if !in_external_macro ( cx. tcx . sess , block. span ) {
65+ for w in block. stmts . windows ( 2 ) {
66+ if let StmtKind :: Expr ( expr) | StmtKind :: Semi ( expr) = w[ 1 ] . kind {
67+ handle_uninit_vec_pair ( cx, & w[ 0 ] , expr) ;
68+ }
6069 }
61- }
6270
63- if let ( Some ( stmt) , Some ( expr) ) = ( block. stmts . last ( ) , block. expr ) {
64- handle_uninit_vec_pair ( cx, stmt, expr) ;
71+ if let ( Some ( stmt) , Some ( expr) ) = ( block. stmts . last ( ) , block. expr ) {
72+ handle_uninit_vec_pair ( cx, stmt, expr) ;
73+ }
6574 }
6675 }
6776}
@@ -79,6 +88,8 @@ fn handle_uninit_vec_pair(
7988 if let ty:: Adt ( _, substs) = vec_ty. kind( ) ;
8089 // Check T of Vec<T>
8190 if !is_uninit_value_valid_for_ty( cx, substs. type_at( 0 ) ) ;
91+ // `#[allow(...)]` attribute can be set on enclosing unsafe block of `set_len()`
92+ if !is_lint_allowed( cx, UNINIT_VEC , maybe_set_len. hir_id) ;
8293 then {
8394 // FIXME: #7698, false positive of the internal lints
8495 #[ allow( clippy:: collapsible_span_lint_calls) ]
0 commit comments