Skip to content

add c-variadic function definitions - #2177

Open
folkertdev wants to merge 8 commits into
rust-lang:masterfrom
folkertdev:c-variadic
Open

add c-variadic function definitions#2177
folkertdev wants to merge 8 commits into
rust-lang:masterfrom
folkertdev:c-variadic

Conversation

@folkertdev

@folkertdev folkertdev commented Feb 17, 2026

Copy link
Copy Markdown
Contributor

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

Stabilization:

@rustbot rustbot added the S-waiting-on-review Status: The marked PR is awaiting review from a maintainer label Feb 17, 2026
Comment thread src/items/functions.md Outdated
Comment thread src/items/functions.md Outdated
Comment on lines +347 to +348
> [!WARNING]
> Passing an unexpected number of arguments or arguments of unexpected type to a variadic function may lead to [undefined behavior][undefined].

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

copied from

https://doc.rust-lang.org/reference/items/external-blocks.html?highlight=variadic#r-items.extern.variadic

basically, the responsibility for passing valid arguments is on the caller.

Comment thread src/items/functions.md Outdated

@ehuss ehuss left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the rule items.fn.params.varargs will need to be updated, since it says it can only be used in an external block.

View changes since this review

Comment thread src/items/functions.md
Comment thread src/items/functions.md Outdated
Comment thread src/items/functions.md Outdated
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Apr 15, 2026
…-in-deps, r=mati865

report the `varargs_without_pattern` lint in deps

tracking issue: rust-lang#44930

After discussion in rust-lang/reference#2177 (comment).

Based on rust-lang#143619 (comment) there was only one actual impacted crate https://crates.io/crates/binrw. The issue was fixed in jam1garner/binrw#342, and has since been released jam1garner/binrw#342 (comment).

Hence we may as well report this loudly.

r? @ghost
jhpratt added a commit to jhpratt/rust that referenced this pull request Apr 16, 2026
…-in-deps, r=mati865

report the `varargs_without_pattern` lint in deps

tracking issue: rust-lang#44930

After discussion in rust-lang/reference#2177 (comment).

Based on rust-lang#143619 (comment) there was only one actual impacted crate https://crates.io/crates/binrw. The issue was fixed in jam1garner/binrw#342, and has since been released jam1garner/binrw#342 (comment).

Hence we may as well report this loudly.

r? @ghost
jhpratt added a commit to jhpratt/rust that referenced this pull request Apr 16, 2026
…-in-deps, r=mati865

report the `varargs_without_pattern` lint in deps

tracking issue: rust-lang#44930

After discussion in rust-lang/reference#2177 (comment).

Based on rust-lang#143619 (comment) there was only one actual impacted crate https://crates.io/crates/binrw. The issue was fixed in jam1garner/binrw#342, and has since been released jam1garner/binrw#342 (comment).

Hence we may as well report this loudly.

r? @ghost
rust-timer added a commit to rust-lang/rust that referenced this pull request Apr 16, 2026
Rollup merge of #154599 - folkertdev:varargs-without-pattern-in-deps, r=mati865

report the `varargs_without_pattern` lint in deps

tracking issue: #44930

After discussion in rust-lang/reference#2177 (comment).

Based on #143619 (comment) there was only one actual impacted crate https://crates.io/crates/binrw. The issue was fixed in jam1garner/binrw#342, and has since been released jam1garner/binrw#342 (comment).

Hence we may as well report this loudly.

r? @ghost
@folkertdev

Copy link
Copy Markdown
Contributor Author

The varargs_without_pattern is now reported in dependencies (on nightly).

I've pushed some tweaks, I'm now planning to submit a stabilization PR in coming days, so if you could look at this again that would be helpful.

@ehuss

ehuss commented Apr 30, 2026

Copy link
Copy Markdown
Contributor

It looks like from rust-lang/rust#155974 that there is an intent to make this unavailable on certain targets. I don't think we've ever done something like that, and I'm not sure how we're going to document that. I suppose there will be a rule. It will need to be careful to distinguish that it is a compile error during validation. Unfortunately we don't define that as a specific phase in the reference, so I'm not sure how we should approach that.

@folkertdev

folkertdev commented Apr 30, 2026

Copy link
Copy Markdown
Contributor Author

I don't think this is very different from https://doc.rust-lang.org/beta/unstable-book/language-features/asm-experimental-arch.html. Consequently the page on inline assembly specifies https://doc.rust-lang.org/nightly/reference/inline-assembly.html?highlight=assemb#r-asm.stable-targets.

So we could have

Support for c-variadic function definitions is stable on the following architectures:

  • x86 and x86-64
  • arm
  • aarch64 and arm64ec
  • ...

The compiler will emit an error if ... is used in a function definition on an unsupported target.

Also spirv and bpf just fundamentally do not support this feature, so there you'd always get an error.

Comment thread src/items/functions.md Outdated
@rustbot

This comment has been minimized.

@rustbot

This comment has been minimized.

Comment thread src/items/functions.md Outdated
Comment thread src/items/functions.md Outdated
Comment thread src/items/functions.md Outdated
Comment thread src/items/functions.md Outdated
Comment on lines +352 to +365
- x86 and x86-64
- ARM
- AArch64 and Arm64EC
- RISC-V (except when using the ilp32e ABI)
- LoongArch
- s390x
- PowerPC and PowerPC64
- AmdGpu and Nvptx64
- wasm32 and wasm64
- csky
- xtensa
- hexagon
- sparc64
- mips

@tgross35 tgross35 Jul 10, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: This mixes lowercase with the arches' name casing (C-SKY, Xtensa, Hexagon, SPARC64, MIPS, Wasm). Also some platforms are explicit about both 32- and 64-bit (x86, ppc) while others aren't (loongarch, mips)

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is based on the list of stable architectures for asm!, I've tried to correct the names.

Comment thread src/items/functions.md
Comment thread src/items/functions.md Outdated

@folkertdev folkertdev left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The merge of the stabilization PR is now only blocked on the additions to the reference here (I'm not sure that is really needed, previously features have been merged with a reference PR that was "far enough along").

I've tried to address comments here as much possible now.

I'd be happy to look at this together in the reference office hours if they are at a somewhat european-friendly time.

View changes since this review

Comment thread src/items/functions.md Outdated
Comment thread src/items/functions.md Outdated
Comment on lines +352 to +365
- x86 and x86-64
- ARM
- AArch64 and Arm64EC
- RISC-V (except when using the ilp32e ABI)
- LoongArch
- s390x
- PowerPC and PowerPC64
- AmdGpu and Nvptx64
- wasm32 and wasm64
- csky
- xtensa
- hexagon
- sparc64
- mips

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is based on the list of stable architectures for asm!, I've tried to correct the names.

Comment thread src/items/functions.md Outdated
Comment thread src/items/functions.md Outdated
Comment thread src/items/functions.md Outdated
@traviscross traviscross added the S-waiting-on-stabilization Waiting for a stabilization PR to be merged in the main Rust repository label Jul 21, 2026
Comment thread src/items/functions.md Outdated
Comment thread src/items/functions.md Outdated
Comment thread src/items/functions.md Outdated

@ehuss ehuss left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment thread src/items/functions.md Outdated
Comment thread src/items/functions.md Outdated
Comment thread src/special-types-and-traits.md Outdated
@traviscross traviscross removed the S-waiting-on-review Status: The marked PR is awaiting review from a maintainer label Jul 21, 2026
It's a bit complicated which declarations are required to be `unsafe`
when using variadic argument lists; let's enumerate the cases.
@traviscross
traviscross force-pushed the c-variadic branch 2 times, most recently from 88338f3 to d8b62a8 Compare July 23, 2026 18:47
The statement that the "lifetime of a `VaList` is that of the function
(call) that created it" feels a bit loose to me.  Let's pin that down
more precisely.
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.
The pattern is required when the variadic parameter appears either on
a function definition or on a function declaration in a trait
definition.  Let's say that and add examples.
Though we document that function definitions and associated function
declarations in trait definitions must have a pattern, that's only
true due to an FCW.  Let's add an admonition about that.
Comment thread src/items/functions.md
Comment on lines +101 to +124
```rust,compile_fail
unsafe extern "C" fn f(...) {} // ERROR: Missing pattern.
```

```rust,compile_fail
trait Tr {
unsafe extern "C" fn f(...); // ERROR: Missing pattern.
}
```

> [!NOTE]
> `rustc` currently accepts `...` without a pattern in function definitions and associated function declarations in trait definitions while linting against it. This will become an error in the future.
>
> ```rust
> #![allow(varargs_without_pattern)]
> unsafe extern "C" fn f(...) {} // OK.
> ```
>
> ```rust
> #![allow(varargs_without_pattern)]
> trait Tr {
> unsafe extern "C" fn f(...); // OK.
> }
> ```

@traviscross traviscross Jul 24, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In adding these examples, I realized that the rule here is only enforced by a lint. Is that intended? Since C-variadic function definitions were not previously accepted on stable Rust, it would be more ordinary to give a hard error here rather than stabilizing something and immediately linting against it.

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, we could maybe deny it later in the pipeline (so in hir validation)? The goal of the FCW is to eventually deny ... in that position pre-expansion, which would be a breaking change.

We semantically did not accept c-variadic definitions so far, but syntactically we actually did, and macros could (and did) make use of that syntactic freedom.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is my inclination. Filed as rust-lang/rust#160109.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Discussed in the lang meeting, this will be resolved by rust-lang/rust#160165.

Comment thread src/items/functions.md
Comment thread src/items/functions.md Outdated
Comment thread src/items/functions.md
@DanielEScherzer

Copy link
Copy Markdown
Contributor

@rustbot label -S-waiting-on-stabilization

Stabilization merged in rust-lang/rust#155697

@rustbot rustbot removed the S-waiting-on-stabilization Waiting for a stabilization PR to be merged in the main Rust repository label Jul 28, 2026
@traviscross traviscross added the I-lang-nominated Nominated for discussion during a lang team meeting. label Jul 28, 2026
@traviscross traviscross added I-lang-nominated Nominated for discussion during a lang team meeting. and removed I-lang-nominated Nominated for discussion during a lang team meeting. labels Jul 28, 2026
Co-authored-by: Daniel Scherzer <daniel.e.scherzer@gmail.com>
Comment thread src/items/functions.md
Comment on lines +513 to +522
r[items.fn.c-variadic.abi]
Only `extern "C"` and `extern "C-unwind"` function definitions can accept a variable argument list.

```rust,compile_fail
unsafe fn f(ap: ...) {} // ERROR: Not supported.
```

```rust,compile_fail
unsafe extern "sysv64" fn f(ap: ...) {} // ERROR: Not supported.
```

@folkertdev folkertdev Jul 29, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that c_variadic_naked_functions (rust-lang/rust#159746) is in FCP, this section needs to be extended. Do we just do that now, wait for FCP to be over, or do it in a separate PR?

I was thinking of something like this:

A variable argument list is only accepted on [naked functions] for the ABI strings that are listed in [items.extern.variadic.conventions].

```rust
#[unsafe(naked)]
unsafe extern "win64" fn variadic_win64(_: u32, _: ...) -> u32 {
    core::arch::naked_asm!(
        r#"
        push    rax
        mov     qword ptr [rsp + 40], r9
        mov     qword ptr [rsp + 24], rdx
        mov     qword ptr [rsp + 32], r8
        lea     rax, [rsp + 40]
        mov     qword ptr [rsp], rax
        lea     eax, [rdx + rcx]
        add     eax, r8d
        pop     rcx
        ret
    "#,
    )
}
```

[items.extern.variadic.conventions]: ../items/external-blocks.md#items.extern.variadic.conventions
[naked functions]: ../attributes.md#attributes.codegen.naked

View changes since the review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.