Skip to content

Commit 61a3593

Browse files
committed
c-variadic: document core::ffi::VaArgSafe
and document `VaList::arg`.
1 parent f4665ab commit 61a3593

File tree

1 file changed

+23
-6
lines changed

1 file changed

+23
-6
lines changed

library/core/src/ffi/va_list.rs

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -202,18 +202,23 @@ mod sealed {
202202
impl<T> Sealed for *const T {}
203203
}
204204

205-
/// Trait which permits the allowed types to be used with [`VaListImpl::arg`].
205+
/// Types that are valid to read using [`VaListImpl::arg`].
206206
///
207207
/// # Safety
208208
///
209-
/// This trait must only be implemented for types that C passes as varargs without implicit promotion.
209+
/// The standard library implements this trait for primitive types that are
210+
/// expected to have a variable argument application-binary interface (ABI) on all
211+
/// platforms.
210212
///
211-
/// In C varargs, integers smaller than [`c_int`] and floats smaller than [`c_double`]
212-
/// are implicitly promoted to [`c_int`] and [`c_double`] respectively. Implementing this trait for
213-
/// types that are subject to this promotion rule is invalid.
213+
/// When C passes variable arguments, integers smaller than [`c_int`] and floats smaller
214+
/// than [`c_double`] are implicitly promoted to [`c_int`] and [`c_double`] respectively.
215+
/// Implementing this trait for types that are subject to this promotion rule is invalid.
214216
///
215217
/// [`c_int`]: core::ffi::c_int
216218
/// [`c_double`]: core::ffi::c_double
219+
// We may unseal this trait in the future, but currently our `va_arg` implementations don't support
220+
// types with an alignment larger than 8, or with a non-scalar layout. Inline assembly can be used
221+
// to accept unsupported types in the meantime.
217222
pub unsafe trait VaArgSafe: sealed::Sealed {}
218223

219224
// i8 and i16 are implicitly promoted to c_int in C, and cannot implement `VaArgSafe`.
@@ -233,7 +238,19 @@ unsafe impl<T> VaArgSafe for *mut T {}
233238
unsafe impl<T> VaArgSafe for *const T {}
234239

235240
impl<'f> VaListImpl<'f> {
236-
/// Advance to the next arg.
241+
/// Advance to and read the next variable argument.
242+
///
243+
/// # Safety
244+
///
245+
/// This function is only sound to call when the next variable argument:
246+
///
247+
/// - has a type that is ABI-compatible with the type `T`
248+
/// - has a value that is a properly initialized value of type `T`
249+
///
250+
/// Calling this function with an incompatible type, an invalid value, or when there
251+
/// are no more variable arguments, is unsound.
252+
///
253+
/// [valid]: https://doc.rust-lang.org/nightly/nomicon/what-unsafe-does.html
237254
#[inline]
238255
pub unsafe fn arg<T: VaArgSafe>(&mut self) -> T {
239256
// SAFETY: the caller must uphold the safety contract for `va_arg`.

0 commit comments

Comments
 (0)