@@ -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`.
220214unsafe impl VaArgSafe for i32 { }
@@ -233,7 +227,19 @@ unsafe impl<T> VaArgSafe for *mut T {}
233227unsafe impl < T > VaArgSafe for * const T { }
234228
235229impl < ' 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