-
Notifications
You must be signed in to change notification settings - Fork 584
add c-variadic function definitions #2177
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
folkertdev
wants to merge
4
commits into
rust-lang:master
Choose a base branch
from
folkertdev:c-variadic
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+80
−2
Open
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -83,7 +83,7 @@ r[items.fn.params.self-restriction] | |
| Functions with a self parameter may only appear as an [associated function] in a [trait] or [implementation]. | ||
|
|
||
| r[items.fn.params.varargs] | ||
| A parameter with the `...` token indicates a [variadic function], and may only be used as the last parameter of an [external block] function. The variadic parameter may have an optional identifier, such as `args: ...`. | ||
| A parameter with the `...` token indicates a [c-variadic function], and may only be used as the last parameter. In an [`extern` block] the c-variadic parameter may have an optional identifier, such as `args: ...`, in a [c-variadic function definition] the identifier is mandatory. | ||
|
|
||
| r[items.fn.body] | ||
| ## Function body | ||
|
|
@@ -332,6 +332,82 @@ Note that this behavior is a consequence of the desugaring to a function that re | |
|
|
||
| Unsafe is used on an async function in precisely the same way that it is used on other functions: it indicates that the function imposes some additional obligations on its caller to ensure soundness. As in any other unsafe function, these conditions may extend beyond the initial call itself -- in the snippet above, for example, the `unsafe_example` function took a pointer `x` as argument, and then (when awaited) dereferenced that pointer. This implies that `x` would have to be valid until the future is finished executing, and it is the caller's responsibility to ensure that. | ||
|
|
||
| r[items.fn.c-variadic] | ||
| ## C-variadic functions | ||
|
|
||
| r[items.fn.c-variadic.intro] | ||
| A *c-variadic* function accepts a variable argument list `pat: ...` as its final parameter. | ||
|
|
||
| ```rust | ||
| unsafe extern "C" fn example(ap: ...) -> f64 { | ||
| unsafe { ap.next_arg::<f64>() } | ||
| } | ||
| ``` | ||
|
|
||
| This parameter stands in for an arbitrary number of arguments that may be passed by the caller. | ||
|
|
||
| > [!WARNING] | ||
| > Passing an unexpected number of arguments or arguments of unexpected type to a c-variadic function may lead to [undefined behavior][undefined]. | ||
|
|
||
| r[items.fn.c-variadic.c-variadic-parameter-type] | ||
| The type of `pat` in the function body is [`VaList`]. | ||
|
|
||
| r[items.fn.c-variadic.desugar-brief] | ||
| A c-variadic function definition is roughly equivalent to a function operating on a [`VaList`]. | ||
|
|
||
| ```rust | ||
| // Source | ||
| unsafe extern "C" fn example(mut ap: ...) -> i32 { | ||
| unsafe { ap.next_arg::<i32>() } | ||
| } | ||
| ``` | ||
|
|
||
| is roughly equivalent to: | ||
|
|
||
| ```rust | ||
| # use std::ffi::VaList; | ||
| // Desugared | ||
| unsafe extern "C" fn example() -> i32 { | ||
| let mut ap: VaList<'_> = /* compiler initializes the VaList */; | ||
|
|
||
| unsafe { ap.next_arg::<i32>() } | ||
|
|
||
| va_end(ap) | ||
| } | ||
|
Comment on lines
+370
to
+376
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
let mut ap: VaList<'_> = /* ... */; // Initializes the VaList.the |
||
| ``` | ||
|
|
||
| r[items.fn.c-variadic.lifetime] | ||
| The lifetime of a `VaList` is that of the function that created it. Hence, the `VaList` value can never outlive the function that created it. | ||
|
|
||
| r[items.fn.c-variadic.ffi-compatibility] | ||
| The rust [`VaList`] is ABI-compatible with the C `va_list` type. | ||
|
|
||
| r[items.fn.c-variadic.abi] | ||
| Only `extern "C"` and `extern "C-unwind"` function defintions can accept a variable argument list. | ||
|
|
||
| r[items.fn.c-variadic.safety] | ||
| Only `unsafe` functions can accept a variable argument list. | ||
|
|
||
| r[items.fn.c-variadic.async] | ||
| A c-variadic functions cannot be `async` | ||
|
|
||
| r[items.fn.c-variadic.const] | ||
| A c-variadic functions cannot be `const` | ||
|
|
||
| r[items.fn.c-variadic.platform-support] | ||
| Some ABIs do not support c-variadic function definitions. The compiler errors in this case. | ||
|
|
||
| ```text | ||
| error: the `bpfel` target does not support c-variadic functions | ||
| --> $DIR/not-supported.rs:23:31 | ||
| | | ||
| LL | unsafe extern "C" fn variadic(_: ...) {} | ||
| | ^^^^^^ | ||
| ``` | ||
|
|
||
| r[items.fn.c-variadic.dyn-compat] | ||
| When a trait method is c-variadic, the trait is no longer [dyn-compatible]. | ||
|
|
||
| r[items.fn.attributes] | ||
| ## Attributes on functions | ||
|
|
||
|
|
@@ -424,5 +500,7 @@ fn foo_oof(#[some_inert_attribute] arg: u8) { | |
| [associated function]: associated-items.md#associated-functions-and-methods | ||
| [implementation]: implementations.md | ||
| [value namespace]: ../names/namespaces.md | ||
| [variadic function]: external-blocks.md#variadic-functions | ||
| [c-variadic function]: external-blocks.md#variadic-functions | ||
| [`extern` block]: external-blocks.md | ||
| [`VaList`]: std::ffi::VaList | ||
| [dyn-compatible]: traits.md#dyn-compatibility | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for c-variadic definitions only
pat: ...is accepted semantically.plain
...is currently parsed, thevarargs_without_patternlint 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is anything holding back changing
varargs_without_patterntoreport_in_deps: true?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not as far as I know. I can make that change an nominate for T-lang.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Based on rust-lang/rust#143619 (comment) there was only one actual impacted crate https://crates.io/crates/binrw. The issue was fixed in jam1garner/binrw#342, however there has not been a release since.
So, if we made this warn in dependencies there would be nothing that users of that crate could do. I'll ping for a release with the fix.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like the releases happened: jam1garner/binrw#342 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, PR is up at rust-lang/rust#154599