add c-variadic function definitions#2177
add c-variadic function definitions#2177folkertdev wants to merge 2 commits intorust-lang:masterfrom
Conversation
| ## C-variadic functions | ||
|
|
||
| r[items.fn.c-variadic.intro] | ||
| A *c-variadic* function accepts a variable argument list `pat: ...` as its final parameter. |
There was a problem hiding this comment.
for c-variadic definitions only pat: ... is accepted semantically.
plain ... is currently parsed, the varargs_without_pattern lint is meant to eventually disallow it. This syntax can only be used as an input to macros, when a bare ... makes it past macro expansion, that will emit an error.
I didn't mention this here, but maybe we should: we follow C23 in that pat: ... may be the only argument. Earlier versions of C required at least one standard argument before the ....
There was a problem hiding this comment.
Is anything holding back changing varargs_without_pattern to report_in_deps: true?
| > [!WARNING] | ||
| > Passing an unexpected number of arguments or arguments of unexpected type to a variadic function may lead to [undefined behavior][undefined]. |
There was a problem hiding this comment.
copied from
basically, the responsibility for passing valid arguments is on the caller.
| unsafe extern "C" fn example() -> i32 { | ||
| let mut storage = MaybeUninit::<VaList<'_>>::uninit(); | ||
| va_start(storage.as_mut_ptr()); // Initializes the VaList. | ||
| let mut ap: &mut VaList<'_> = ap.assume_init_mut(); | ||
|
|
||
| unsafe { ap.arg::<i32>() } | ||
|
|
||
| va_end(ap) | ||
| } |
There was a problem hiding this comment.
va_start and va_end are C functions/concepts. We could instead handwave and say
let mut ap: VaList<'_> = /* ... */; // Initializes the VaList.the va_end is called by the VaList Drop implementation.
|
|
||
| > [!WARNING] | ||
| > Passing an unexpected number of arguments or arguments of unexpected type to a variadic function may lead to [undefined behavior][undefined]. | ||
|
|
There was a problem hiding this comment.
Maybe it would be good to have a rule near the top here that explains the type of the variadic parameter is a VaList?
| > Passing an unexpected number of arguments or arguments of unexpected type to a variadic function may lead to [undefined behavior][undefined]. | ||
|
|
||
| r[items.fn.async.desugar-brief] | ||
| A c-variadic function definition is roughly equivalent to a function operating on a [`VaList`]. |
There was a problem hiding this comment.
In how arguments are actually passed, these signatures are (very) different
fn foo(ap: ...) { /* ... */ }
fn bar(ap: VaList) { /* ... */ }Those two functions could have exactly the same body though.
| A *c-variadic* function accepts a variable argument list `pat: ...` as its final parameter. | ||
|
|
||
| ```rust | ||
| unsafe extern "C" fn example(arg0: i32, ap: ...) { } |
There was a problem hiding this comment.
It might be helpful for this initial example to show extracting a value from ap.
I think this has all of the raw material, but needs polishing.
Here is a draft of the stabilization report, for additional context: https://hackmd.io/@Q66MPiW4T7yNTKOCaEb-Lw/S1iI3WIwZg
Tracking issue: rust-lang/rust#44930