Repository: rust-lang/rust
File: library/core/src/ffi/va_list.rs (Rust)

Code before:
        #[derive(Debug, Clone, Copy)]
        struct VaListInner {
            ptr: *const c_void,
        }
    }
}

/// A variable argument list, ABI-compatible with `va_list` in C.
///
/// This type is created in c-variadic functions when `...` is desugared. A `VaList`
/// is automatically initialized (equivalent to calling `va_start` in C).
///
/// ```
/// #![feature(c_variadic)]
///
/// use std::ffi::VaList;
///
/// unsafe extern "C" fn my_func(ap: ...) -> i32 {
///     unsafe { vmy_func(ap) }
/// }
///
/// unsafe fn vmy_func(mut ap: VaList<'_>) -> i32 {
///     unsafe { ap.arg::<i32>() }
/// }
///
/// assert_eq!(unsafe { my_func(42i32) }, 42);
/// ```
///
/// The [`VaList::arg`] method can be used to read an argument from the list. This method
/// automatically advances the `VaList` to the next argument. The C equivalent is `va_arg`.
///
/// Cloning a `VaList` performs the equivalent of C `va_copy`, producing an independent cursor
/// that arguments can be read from without affecting the original. Dropping a `VaList` performs
/// the equivalent of C `va_end`.
///
/// This can be used across an FFI boundary, and fully matches the platform's `va_list`.
#[repr(transparent)]
#[lang = "va_list"]
pub struct VaList<'a> {
    inner: VaListInner,
    _marker: PhantomCovariantLifetime<'a>,
}

impl fmt::Debug for VaList<'_> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        // No need to include `_marker` in debug output.
        f.debug_tuple("VaList").field(&self.inner).finish()
    }
}

impl VaList<'_> {

Review comment (suggestion):
It's probably worth documenting the preconditions. Maybe also worth expanding the example a bit?

```rust
/// # Safety
/// Must be passed at least `count` arguments of type `i32`.
unsafe fn vmy_func(count: u32, mut ap: VaList<'_>) -> i32 {
    let mut sum = 0;
    for _ in 0..=count {
        sum += unsafe { ap.arg::<i32>() };
    }
    sum
}

assert_eq!(unsafe { my_func(1, 42i32) }, 42);
assert_eq!(unsafe { my_func(3, 42i32, -7i32, 20i32) }, 55);
```

Code after:
        #[derive(Debug, Clone, Copy)]
        struct VaListInner {
            ptr: *const c_void,
        }
    }
}

/// A variable argument list, ABI-compatible with `va_list` in C.
///
/// This type is created in c-variadic functions when `...` is desugared. A `VaList`
/// is automatically initialized (equivalent to calling `va_start` in C).
///
/// ```
/// #![feature(c_variadic)]
///
/// use std::ffi::VaList;
///
/// /// # Safety
/// /// Must be passed at least `count` arguments of type `i32`.
/// unsafe extern "C" fn my_func(count: u32, ap: ...) -> i32 {
///     unsafe { vmy_func(count, ap) }
/// }
///
/// /// # Safety
/// /// Must be passed at least `count` arguments of type `i32`.
/// unsafe fn vmy_func(count: u32, mut ap: VaList<'_>) -> i32 {
///     let mut sum = 0;
///     for _ in 0..count {
///         sum += unsafe { ap.arg::<i32>() };
///     }
///     sum
/// }
///
/// assert_eq!(unsafe { my_func(1, 42i32) }, 42);
/// assert_eq!(unsafe { my_func(3, 42i32, -7i32, 20i32) }, 55);
/// ```
///
/// The [`VaList::arg`] method can be used to read an argument from the list. This method
/// automatically advances the `VaList` to the next argument. The C equivalent is `va_arg`.
///
/// Cloning a `VaList` performs the equivalent of C `va_copy`, producing an independent cursor
/// that arguments can be read from without affecting the original. Dropping a `VaList` performs
/// the equivalent of C `va_end`.
///
/// This can be used across an FFI boundary, and fully matches the platform's `va_list`.
#[repr(transparent)]
#[lang = "va_list"]
pub struct VaList<'a> {
    inner: VaListInner,
    _marker: PhantomCovariantLifetime<'a>,
}