@@ -185,36 +185,30 @@ impl<'a, 'f: 'a> DerefMut for VaList<'a, 'f> {
185
185
}
186
186
}
187
187
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`].
206
189
///
207
190
/// # Safety
208
191
///
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 */)]`).
210
204
///
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 .
214
208
///
215
209
/// [`c_int`]: core::ffi::c_int
216
210
/// [`c_double`]: core::ffi::c_double
217
- pub unsafe trait VaArgSafe : sealed :: Sealed { }
211
+ pub unsafe trait VaArgSafe { }
218
212
219
213
// i8 and i16 are implicitly promoted to c_int in C, and cannot implement `VaArgSafe`.
220
214
unsafe impl VaArgSafe for i32 { }
@@ -233,7 +227,19 @@ unsafe impl<T> VaArgSafe for *mut T {}
233
227
unsafe impl < T > VaArgSafe for * const T { }
234
228
235
229
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
237
243
#[ inline]
238
244
pub unsafe fn arg < T : VaArgSafe > ( & mut self ) -> T {
239
245
// SAFETY: the caller must uphold the safety contract for `va_arg`.
0 commit comments