Skip to content

Commit 6c38e46

Browse files
authored
Rollup merge of #152675 - folkertdev:va-list-docs, r=tgross35
Improve `VaList` stdlib docs tracking issue: #44930 Some improvements to the `VaList` documentation, at least adding an example. We should link to the reference for c-variadic functions once stable. I've tried to call out explicitly that the type is meant for sending over the FFI boundary. r? workingjubilee cc @tgross35
2 parents 76618e7 + 3b5874e commit 6c38e46

1 file changed

Lines changed: 43 additions & 9 deletions

File tree

library/core/src/ffi/va_list.rs

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,44 @@ crate::cfg_select! {
183183
}
184184
}
185185

186-
/// A variable argument list, equivalent to `va_list` in C.
186+
/// A variable argument list, ABI-compatible with `va_list` in C.
187+
///
188+
/// This type is created in c-variadic functions when `...` is desugared. A `VaList`
189+
/// is automatically initialized (equivalent to calling `va_start` in C).
190+
///
191+
/// ```
192+
/// #![feature(c_variadic)]
193+
///
194+
/// use std::ffi::VaList;
195+
///
196+
/// /// # Safety
197+
/// /// Must be passed at least `count` arguments of type `i32`.
198+
/// unsafe extern "C" fn my_func(count: u32, ap: ...) -> i32 {
199+
/// unsafe { vmy_func(count, ap) }
200+
/// }
201+
///
202+
/// /// # Safety
203+
/// /// Must be passed at least `count` arguments of type `i32`.
204+
/// unsafe fn vmy_func(count: u32, mut ap: VaList<'_>) -> i32 {
205+
/// let mut sum = 0;
206+
/// for _ in 0..count {
207+
/// sum += unsafe { ap.arg::<i32>() };
208+
/// }
209+
/// sum
210+
/// }
211+
///
212+
/// assert_eq!(unsafe { my_func(1, 42i32) }, 42);
213+
/// assert_eq!(unsafe { my_func(3, 42i32, -7i32, 20i32) }, 55);
214+
/// ```
215+
///
216+
/// The [`VaList::arg`] method can be used to read an argument from the list. This method
217+
/// automatically advances the `VaList` to the next argument. The C equivalent is `va_arg`.
218+
///
219+
/// Cloning a `VaList` performs the equivalent of C `va_copy`, producing an independent cursor
220+
/// that arguments can be read from without affecting the original. Dropping a `VaList` performs
221+
/// the equivalent of C `va_end`.
222+
///
223+
/// This can be used across an FFI boundary, and fully matches the platform's `va_list`.
187224
#[repr(transparent)]
188225
#[lang = "va_list"]
189226
pub struct VaList<'a> {
@@ -278,20 +315,17 @@ unsafe impl<T> VaArgSafe for *mut T {}
278315
unsafe impl<T> VaArgSafe for *const T {}
279316

280317
impl<'f> VaList<'f> {
281-
/// Advance to and read the next variable argument.
318+
/// Read an argument from the variable argument list, and advance to the next argument.
282319
///
283-
/// # Safety
320+
/// Only types that implement [`VaArgSafe`] can be read from a variable argument list.
284321
///
285-
/// This function is only sound to call when:
322+
/// # Safety
286323
///
287-
/// - there is a next variable argument available.
288-
/// - the next argument's type must be ABI-compatible with the type `T`.
289-
/// - the next argument must have a properly initialized value of type `T`.
324+
/// This function is only sound to call when there is another argument to read, and that
325+
/// argument is a properly initialized value of the type `T`.
290326
///
291327
/// Calling this function with an incompatible type, an invalid value, or when there
292328
/// are no more variable arguments, is unsound.
293-
///
294-
/// [valid]: https://doc.rust-lang.org/nightly/nomicon/what-unsafe-does.html
295329
#[inline]
296330
#[rustc_const_unstable(feature = "const_c_variadic", issue = "151787")]
297331
pub const unsafe fn arg<T: VaArgSafe>(&mut self) -> T {

0 commit comments

Comments
 (0)