diff options
| author | Jacob Pratt <jacob@jhpratt.dev> | 2025-09-13 18:55:20 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-09-13 18:55:20 -0400 |
| commit | da1c27df16075d9ebb28a94cf9b400e89c476233 (patch) | |
| tree | 7a39a6ded2ce72835a7895dca51846c941ea3342 /library | |
| parent | 08db93806b2bb090fc8a8857c62a02aed521e39e (diff) | |
| parent | a107ea18af5274c3f7e82fa917f3bda6eeb591fe (diff) | |
| download | rust-da1c27df16075d9ebb28a94cf9b400e89c476233.tar.gz rust-da1c27df16075d9ebb28a94cf9b400e89c476233.zip | |
Rollup merge of #146521 - folkertdev:document-va-arg-safe, r=workingjubilee
document `core::ffi::VaArgSafe` tracking issue: https://github.com/rust-lang/rust/issues/44930 A modification of https://github.com/rust-lang/rust/pull/146454, keeping just the documentation changes, but not unsealing the trait. Although conceptually we'd want to unseal the trait, there are many edge cases to supporting arbitrary types. We'd need to exhaustively test that all targets/calling conventions support all types that rust might generate (or generate proper error messages for unsupported cases). At present, many of the `va_arg` implementations assume that the argument is a scalar, and has an alignment of at most 8. That is totally sufficient for an MVP (accepting all of the "standard" C types), but clearly does not cover all rust types. This PR also adds some various other tests for edge cases of c-variadic: - the `#[inline]` attribute in its various forms. At present, LLVM is unable to inline c-variadic functions, but the attribute should still be accepted. `#[rustc_force_inline]` already rejects c-variadic functions. - naked functions should accept and work with a C variable argument list. In the future we'd like to allow more ABIs with naked functions (basically, any ABI for which we accept defining foreign c-variadic functions), but for now only `"C"` and `"C-unwind` are supported - guaranteed tail calls: c-variadic functions cannot be tail-called. That was already rejected, but there was not test for it. r? `@workingjubilee`
Diffstat (limited to 'library')
| -rw-r--r-- | library/core/src/ffi/va_list.rs | 29 |
1 files changed, 23 insertions, 6 deletions
diff --git a/library/core/src/ffi/va_list.rs b/library/core/src/ffi/va_list.rs index 88ad1197777..643bd95df84 100644 --- a/library/core/src/ffi/va_list.rs +++ b/library/core/src/ffi/va_list.rs @@ -202,18 +202,23 @@ mod sealed { impl<T> Sealed for *const T {} } -/// Trait which permits the allowed types to be used with [`VaListImpl::arg`]. +/// Types that are valid to read using [`VaListImpl::arg`]. /// /// # Safety /// -/// This trait must only be implemented for types that C passes as varargs without implicit promotion. +/// The standard library implements this trait for primitive types that are +/// expected to have a variable argument application-binary interface (ABI) on all +/// platforms. /// -/// In C varargs, integers smaller than [`c_int`] and floats smaller than [`c_double`] -/// are implicitly promoted to [`c_int`] and [`c_double`] respectively. Implementing this trait for -/// types that are subject to this promotion rule is invalid. +/// When C passes variable arguments, integers smaller than [`c_int`] and floats smaller +/// than [`c_double`] are implicitly promoted to [`c_int`] and [`c_double`] respectively. +/// Implementing this trait for types that are subject to this promotion rule is invalid. /// /// [`c_int`]: core::ffi::c_int /// [`c_double`]: core::ffi::c_double +// We may unseal this trait in the future, but currently our `va_arg` implementations don't support +// types with an alignment larger than 8, or with a non-scalar layout. Inline assembly can be used +// to accept unsupported types in the meantime. pub unsafe trait VaArgSafe: sealed::Sealed {} // 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 {} unsafe impl<T> VaArgSafe for *const T {} impl<'f> VaListImpl<'f> { - /// Advance to the next arg. + /// Advance to and read the next variable argument. + /// + /// # Safety + /// + /// This function is only sound to call when the next variable argument: + /// + /// - has a type that is ABI-compatible with the type `T` + /// - has a value that is a properly initialized value of type `T` + /// + /// Calling this function with an incompatible type, an invalid value, or when there + /// are no more variable arguments, is unsound. + /// + /// [valid]: https://doc.rust-lang.org/nightly/nomicon/what-unsafe-does.html #[inline] pub unsafe fn arg<T: VaArgSafe>(&mut self) -> T { // SAFETY: the caller must uphold the safety contract for `va_arg`. |
