#![warn(clippy::uninit_vec)] use std::cell::UnsafeCell; use std::mem::MaybeUninit; #[derive(Default)] struct MyVec { vec: Vec, } union MyOwnMaybeUninit { value: u8, uninit: (), } // https://github.com/rust-lang/rust/issues/119620 unsafe fn requires_paramenv() { let mut vec = Vec::>::with_capacity(1); vec.set_len(1); } fn main() { // with_capacity() -> set_len() should be detected let mut vec: Vec = Vec::with_capacity(1000); //~^ ERROR: calling `set_len()` immediately after reserving a buffer creates uninitial unsafe { vec.set_len(200); } // reserve() -> set_len() should be detected vec.reserve(1000); //~^ ERROR: calling `set_len()` immediately after reserving a buffer creates uninitial unsafe { vec.set_len(200); } // new() -> set_len() should be detected let mut vec: Vec = Vec::new(); //~^ ERROR: calling `set_len()` on empty `Vec` creates out-of-bound values unsafe { vec.set_len(200); } // default() -> set_len() should be detected let mut vec: Vec = Default::default(); //~^ ERROR: calling `set_len()` on empty `Vec` creates out-of-bound values unsafe { vec.set_len(200); } let mut vec: Vec = Vec::default(); //~^ ERROR: calling `set_len()` on empty `Vec` creates out-of-bound values unsafe { vec.set_len(200); } // test when both calls are enclosed in the same unsafe block unsafe { let mut vec: Vec = Vec::with_capacity(1000); //~^ ERROR: calling `set_len()` immediately after reserving a buffer creates unini vec.set_len(200); vec.reserve(1000); //~^ ERROR: calling `set_len()` immediately after reserving a buffer creates unini vec.set_len(200); } let mut vec: Vec = Vec::with_capacity(1000); //~^ ERROR: calling `set_len()` immediately after reserving a buffer creates uninitial 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); //~^ ERROR: calling `set_len()` immediately after reserving a buffer creates uninitial unsafe { my_vec.vec.set_len(200); } my_vec.vec = Vec::with_capacity(1000); //~^ ERROR: calling `set_len()` immediately after reserving a buffer creates uninitial unsafe { my_vec.vec.set_len(200); } // Test `#[allow(...)]` attributes on inner unsafe block (shouldn't trigger) let mut vec: Vec = Vec::with_capacity(1000); #[allow(clippy::uninit_vec)] unsafe { vec.set_len(200); } // MaybeUninit-wrapped types should not be detected unsafe { let mut vec: Vec> = Vec::with_capacity(1000); vec.set_len(200); let mut vec: Vec<(MaybeUninit, MaybeUninit)> = Vec::with_capacity(1000); vec.set_len(200); let mut vec: Vec<(MaybeUninit, [MaybeUninit; 2])> = Vec::with_capacity(1000); vec.set_len(200); } // known false negative let mut vec1: Vec = Vec::with_capacity(1000); let mut vec2: Vec = Vec::with_capacity(1000); unsafe { vec1.set_len(200); vec2.set_len(200); } // set_len(0) should not be detected let mut vec: Vec = Vec::with_capacity(1000); unsafe { vec.set_len(0); } // ZSTs should not be detected let mut vec: Vec<()> = Vec::with_capacity(1000); unsafe { vec.set_len(10); } // unions should not be detected let mut vec: Vec = Vec::with_capacity(1000); unsafe { vec.set_len(10); } polymorphic::<()>(); fn polymorphic() { // We are conservative around polymorphic types. let mut vec: Vec = Vec::with_capacity(1000); //~^ ERROR: calling `set_len()` immediately after reserving a buffer creates unini unsafe { vec.set_len(10); } } fn poly_maybe_uninit() { // We are conservative around polymorphic types. let mut vec: Vec> = Vec::with_capacity(1000); unsafe { vec.set_len(10); } } fn nested_union() { let mut vec: Vec>> = Vec::with_capacity(1); unsafe { vec.set_len(1); } } struct Recursive(*const Recursive, MaybeUninit); fn recursive_union() { // Make sure we don't stack overflow on recursive types. // The pointer acts as the base case because it can't be uninit regardless of its pointee. let mut vec: Vec> = Vec::with_capacity(1); //~^ uninit_vec unsafe { vec.set_len(1); } } #[repr(u8)] enum Enum { Variant(T), } fn union_in_enum() { // Enums can have a discriminant that can't be uninit, so this should still warn let mut vec: Vec> = Vec::with_capacity(1); //~^ uninit_vec unsafe { vec.set_len(1); } } }