Skip to content

Commit 36b9646

Browse files
committed
c-variadic: unseal core::ffi::VaArgSafe
And update the safety documentation
1 parent f4665ab commit 36b9646

File tree

1 file changed

+30
-24
lines changed

1 file changed

+30
-24
lines changed

library/core/src/ffi/va_list.rs

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -185,36 +185,30 @@ impl<'a, 'f: 'a> DerefMut for VaList<'a, 'f> {
185185
}
186186
}
187187

188-
mod sealed {
189-
pub trait Sealed {}
190-
191-
impl Sealed for i32 {}
192-
impl Sealed for i64 {}
193-
impl Sealed for isize {}
194-
195-
impl Sealed for u32 {}
196-
impl Sealed for u64 {}
197-
impl Sealed for usize {}
198-
199-
impl Sealed for f64 {}
200-
201-
impl<T> Sealed for *mut T {}
202-
impl<T> Sealed for *const T {}
203-
}
204-
205-
/// Trait which permits the allowed types to be used with [`VaListImpl::arg`].
188+
/// Types that are valid to read using [`VaListImpl::arg`].
206189
///
207190
/// # Safety
208191
///
209-
/// This trait must only be implemented for types that C passes as varargs without implicit promotion.
192+
/// By default the standard library implements this trait for primitive types that are
193+
/// expected to have a variable argument application-binary interface (ABI) on all
194+
/// platforms.
195+
///
196+
/// When C passes variable arguments, integers smaller than [`c_int`] and floats smaller
197+
/// than [`c_double`] are implicitly promoted to [`c_int`] and [`c_double`] respectively.
198+
/// Implementing this trait for types that are subject to this promotion rule is invalid.
199+
///
200+
/// Other primitive types (e.g. 128-bit integers or SIMD vectors) have inconsistent
201+
/// platform support. This trait may be implemented on a wrapper around such types
202+
/// (the "newtype pattern"), when the implementation is only available on plaforms
203+
/// with support (e.g. using `#[cfg(/* some predicate */)]`).
210204
///
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.
205+
/// Composite data types (`struct`, `enum` and `union`) may implement this trait if their layout
206+
/// follows the C layout rules. This does not just mean that the type should use `#[repr(C)]` or
207+
/// similar, but additionally that all fields transitively also follow the C layout rules.
214208
///
215209
/// [`c_int`]: core::ffi::c_int
216210
/// [`c_double`]: core::ffi::c_double
217-
pub unsafe trait VaArgSafe: sealed::Sealed {}
211+
pub unsafe trait VaArgSafe {}
218212

219213
// i8 and i16 are implicitly promoted to c_int in C, and cannot implement `VaArgSafe`.
220214
unsafe impl VaArgSafe for i32 {}
@@ -233,7 +227,19 @@ unsafe impl<T> VaArgSafe for *mut T {}
233227
unsafe impl<T> VaArgSafe for *const T {}
234228

235229
impl<'f> VaListImpl<'f> {
236-
/// Advance to the next arg.
230+
/// Advance to and read the next variable argument.
231+
///
232+
/// # Safety
233+
///
234+
/// This function is only sound to call when the next variable argument:
235+
///
236+
/// - has a type that is ABI-compatible with the type `T`
237+
/// - has a value that is a properly initialized value of type `T`
238+
///
239+
/// Calling this function with an incompatible type, an invalid value, or when there
240+
/// are no more variable arguments, is unsound.
241+
///
242+
/// [valid]: https://doc.rust-lang.org/nightly/nomicon/what-unsafe-does.html
237243
#[inline]
238244
pub unsafe fn arg<T: VaArgSafe>(&mut self) -> T {
239245
// SAFETY: the caller must uphold the safety contract for `va_arg`.

0 commit comments

Comments
 (0)