Skip to content

Commit 0e36e59

Browse files
committed
Add examples to the C-variadic rules
We're moving in the direction of having one or more examples for each rule where possible. Let's add examples to the new rules where they were missing and make sense to have.
1 parent 7a88254 commit 0e36e59

1 file changed

Lines changed: 57 additions & 2 deletions

File tree

src/items/functions.md

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,13 @@ This parameter stands in for an arbitrary number of arguments that may be passed
349349
r[items.fn.c-variadic.parameter-type]
350350
The type of `pat` in the function body is [`VaList<'_>`].
351351

352+
```rust
353+
# use core::ffi::VaList;
354+
unsafe extern "C" fn f(ap: ...) {
355+
let _: VaList<'_> = ap;
356+
}
357+
```
358+
352359
r[items.fn.c-variadic.lifetime]
353360
A C-variadic function definition is implicitly generic over the lifetime of its variadic parameter, as if the parameter had type `VaList<'x>` for a fresh, unnameable lifetime `'x`. Because the function must be valid for any such lifetime, the `VaList` cannot be proved to outlive any caller-provided lifetime (and so cannot escape the call) and no caller-provided lifetime can be proved to outlive it.
354361

@@ -385,7 +392,7 @@ r[items.fn.c-variadic.desugar-brief]
385392
A C-variadic function definition is roughly equivalent to a function operating on a [`VaList`].
386393
387394
```rust
388-
unsafe extern "C" fn example(mut ap: ...) -> i32 {
395+
unsafe extern "C" fn f(mut ap: ...) -> i32 {
389396
unsafe { ap.next_arg::<i32>() }
390397
}
391398
```
@@ -401,7 +408,7 @@ Roughly desugars to:
401408
use core::intrinsics::{va_arg, va_end};
402409
// `va_start` is magic and has no intrinsic.
403410
fn va_start(ap: *mut VaList<'_>) { /* magic */ }
404-
unsafe extern "C" fn example() -> i32 {
411+
unsafe extern "C" fn f() -> i32 {
405412
unsafe {
406413
let mut ap: MaybeUninit<VaList<'_>> = MaybeUninit::uninit();
407414
va_start(ap.as_mut_ptr());
@@ -445,25 +452,73 @@ Examples of incompatible types are:
445452
r[items.fn.c-variadic.abi-compatibility]
446453
[`VaList`] is ABI compatible with the C `va_list` type.
447454

455+
```rust
456+
# use core::ffi::{c_char, c_int, VaList};
457+
unsafe extern "C" {
458+
// The C `vprintf` function is:
459+
//
460+
// int vprintf(const char *format, va_list ap);
461+
//
462+
unsafe fn vprintf(fmt: *const c_char, ap: VaList<'_>) -> c_int;
463+
}
464+
465+
unsafe extern "C" fn print(fmt: *const c_char, ap: ...) -> c_int {
466+
// The `VaList` is passed directly to the C function.
467+
unsafe { vprintf(fmt, ap) }
468+
}
469+
```
470+
448471
r[items.fn.c-variadic.abi]
449472
Only `extern "C"` and `extern "C-unwind"` function definitions can accept a variable argument list.
450473

474+
```rust,compile_fail
475+
unsafe fn f(ap: ...) {} // ERROR: Not supported.
476+
```
477+
478+
```rust,compile_fail
479+
unsafe extern "sysv64" fn f(ap: ...) {} // ERROR: Not supported.
480+
```
481+
451482
r[items.fn.c-variadic.safety]
452483
When a variable argument list is used in the signature:
453484

454485
- Function definitions must be `unsafe`.
455486
- Function declarations within trait definitions must be `unsafe`.
456487
- Function declarations in `extern` blocks may be `safe`.
457488

489+
```rust,compile_fail
490+
extern "C" fn f(ap: ...) {} // ERROR: Must be `unsafe`.
491+
```
492+
493+
```rust,compile_fail
494+
trait Tr {
495+
extern "C" fn f(ap: ...); // ERROR: Must be `unsafe`.
496+
}
497+
```
498+
499+
```rust
500+
unsafe extern "C" {
501+
safe fn f(ap: ...); // OK.
502+
}
503+
```
504+
458505
> [!NOTE]
459506
> For `safe` function declarations in an `extern` block, see the warning in [items.extern.variadic].
460507
461508
r[items.fn.c-variadic.async]
462509
A C-variadic function cannot be `async`.
463510

511+
```rust,compile_fail
512+
async unsafe extern "C" fn f(ap: ...) {} // ERROR: Cannot be `async`.
513+
```
514+
464515
r[items.fn.c-variadic.const]
465516
A C-variadic function cannot be `const`.
466517

518+
```rust,compile_fail,E0658
519+
const unsafe extern "C" fn f(ap: ...) {} // ERROR: Cannot be `const`.
520+
```
521+
467522
r[items.fn.c-variadic.stable-targets]
468523
Support for C-variadic function definitions is stable on the following target architectures:
469524

0 commit comments

Comments
 (0)