Skip to content

Commit e69a5cb

Browse files
authored
Rollup merge of rust-lang#56425 - scottmcm:redo-vec-set_len-docs, r=Centril
Redo the docs for Vec::set_len Inspired by the [recent conversation on IRLO](https://internals.rust-lang.org/t/make-vec-set-len-enforce-the-len-cap-invariant/8927/23?u=scottmcm). This is just my first stab at this; suggestions welcome.
2 parents 0c91f3d + 986e49d commit e69a5cb

File tree

1 file changed

+62
-27
lines changed

1 file changed

+62
-27
lines changed

src/liballoc/vec.rs

+62-27
Original file line numberDiff line numberDiff line change
@@ -738,53 +738,88 @@ impl<T> Vec<T> {
738738
self
739739
}
740740

741-
/// Sets the length of a vector.
741+
/// Forces the length of the vector to `new_len`.
742742
///
743-
/// This will explicitly set the size of the vector, without actually
744-
/// modifying its buffers, so it is up to the caller to ensure that the
745-
/// vector is actually the specified size.
743+
/// This is a low-level operation that maintains none of the normal
744+
/// invariants of the type. Normally changing the length of a vector
745+
/// is done using one of the safe operations instead, such as
746+
/// [`truncate`], [`resize`], [`extend`], or [`clear`].
746747
///
747-
/// # Examples
748+
/// [`truncate`]: #method.truncate
749+
/// [`resize`]: #method.resize
750+
/// [`extend`]: #method.extend-1
751+
/// [`clear`]: #method.clear
748752
///
749-
/// ```
750-
/// use std::ptr;
753+
/// # Safety
751754
///
752-
/// let mut vec = vec!['r', 'u', 's', 't'];
755+
/// - `new_len` must be less than or equal to [`capacity()`].
756+
/// - The elements at `old_len..new_len` must be initialized.
753757
///
754-
/// unsafe {
755-
/// ptr::drop_in_place(&mut vec[3]);
756-
/// vec.set_len(3);
758+
/// [`capacity()`]: #method.capacity
759+
///
760+
/// # Examples
761+
///
762+
/// This method can be useful for situations in which the vector
763+
/// is serving as a buffer for other code, particularly over FFI:
764+
///
765+
/// ```no_run
766+
/// # #![allow(dead_code)]
767+
/// # // This is just a minimal skeleton for the doc example;
768+
/// # // don't use this as a starting point for a real library.
769+
/// # pub struct StreamWrapper { strm: *mut std::ffi::c_void }
770+
/// # const Z_OK: i32 = 0;
771+
/// # extern "C" {
772+
/// # fn deflateGetDictionary(
773+
/// # strm: *mut std::ffi::c_void,
774+
/// # dictionary: *mut u8,
775+
/// # dictLength: *mut usize,
776+
/// # ) -> i32;
777+
/// # }
778+
/// # impl StreamWrapper {
779+
/// pub fn get_dictionary(&self) -> Option<Vec<u8>> {
780+
/// // Per the FFI method's docs, "32768 bytes is always enough".
781+
/// let mut dict = Vec::with_capacity(32_768);
782+
/// let mut dict_length = 0;
783+
/// // SAFETY: When `deflateGetDictionary` returns `Z_OK`, it holds that:
784+
/// // 1. `dict_length` elements were initialized.
785+
/// // 2. `dict_length` <= the capacity (32_768)
786+
/// // which makes `set_len` safe to call.
787+
/// unsafe {
788+
/// // Make the FFI call...
789+
/// let r = deflateGetDictionary(self.strm, dict.as_mut_ptr(), &mut dict_length);
790+
/// if r == Z_OK {
791+
/// // ...and update the length to what was initialized.
792+
/// dict.set_len(dict_length);
793+
/// Some(dict)
794+
/// } else {
795+
/// None
796+
/// }
797+
/// }
757798
/// }
758-
/// assert_eq!(vec, ['r', 'u', 's']);
799+
/// # }
759800
/// ```
760801
///
761-
/// In this example, there is a memory leak since the memory locations
762-
/// owned by the inner vectors were not freed prior to the `set_len` call:
802+
/// While the following example is sound, there is a memory leak since
803+
/// the inner vectors were not freed prior to the `set_len` call:
763804
///
764805
/// ```
765806
/// let mut vec = vec![vec![1, 0, 0],
766807
/// vec![0, 1, 0],
767808
/// vec![0, 0, 1]];
809+
/// // SAFETY:
810+
/// // 1. `old_len..0` is empty so no elements need to be initialized.
811+
/// // 2. `0 <= capacity` always holds whatever `capacity` is.
768812
/// unsafe {
769813
/// vec.set_len(0);
770814
/// }
771815
/// ```
772816
///
773-
/// In this example, the vector gets expanded from zero to four items
774-
/// without any memory allocations occurring, resulting in vector
775-
/// values of unallocated memory:
776-
///
777-
/// ```
778-
/// let mut vec: Vec<char> = Vec::new();
779-
///
780-
/// unsafe {
781-
/// vec.set_len(4);
782-
/// }
783-
/// ```
817+
/// Normally, here, one would use [`clear`] instead to correctly drop
818+
/// the contents and thus not leak memory.
784819
#[inline]
785820
#[stable(feature = "rust1", since = "1.0.0")]
786-
pub unsafe fn set_len(&mut self, len: usize) {
787-
self.len = len;
821+
pub unsafe fn set_len(&mut self, new_len: usize) {
822+
self.len = new_len;
788823
}
789824

790825
/// Removes an element from the vector and returns it.

0 commit comments

Comments
 (0)