Skip to content

Tracking issue for RFC 2137: Support defining C-compatible variadic functions in Rust (c_variadic) #44930

Closed

Description

@aturon

View all comments

This is a tracking issue for the RFC "Support defining C-compatible variadic functions in Rust" (rust-lang/rfcs#2137).

Steps:

Unresolved questions

passing VaList to extern functions

On linux calling foo will pass a sysv64 VaList to an extern "win64" function, which might be confusing.

extern "win64" {
    fn foo(_: VaList);
}

Resolved questions

Miri support

Has been added in #150601.

Continuing bikeshed on the ... syntax

There has been no discussion of a different syntax in recent years.

When implementing this feature, we will need to determine whether the compiler can provide an appropriate lifetime that prevents a VaList from outliving its corresponding variadic function.

The compiler internally determines that lifetime, to make sure that a VaList<'_> does not outlive the function that created it.

Ensure that even when this gets stabilized for regular functions, it is still rejected on const fn.

This is tested in https://github.com/rust-lang/rust/blob/main/tests/ui/parser/variadic-ffi-semantic-restrictions.rs and gives the following error:

error: functions cannot be both `const` and C-variadic
  --> $DIR/variadic-ffi-semantic-restrictions.rs:33:1
   |
LL | const unsafe extern "C" fn f4_1(x: isize, _: ...) {}
   | ^^^^^ `const` because of this             ^^^^^^ C-variadic because of this

We reject c-variadic async functions in a similar way.

Issue #125431

The VaList definition introduced in #141980 circumvents this issue.

Issue #61275

This is an issue with c-variadic calls, not with c-variadic definitons.

Issue #141618

We have some forwards-compatible ideas for how to potentially add the ABI to the type in the future. That is only required if we want to allow calling c-variadic functions with a non-system ABI. Because C only allows using the system ABI for c-variadic calls, that is unlikely to come up in practice.

What exactly are the ABI requirements around variadic calls? What are the ABI compatibility rules? Do we have to be concerned about LLVM target features affecting variadic ABI?

Variadic calls using the system ABI do not impose any additional constraints. We already handle some ABI compatibility issues using target modifiers.

Implementation history

va_arg codegen

VaList and its layout

other

c-variadic adjacent

Activity

  1. added
    B-RFC-approvedBlocker: Approved by a merged RFC but not yet implemented.
    C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFC
    T-langRelevant to the language team
    on Sep 29, 2017
  2. plietar commented on Sep 29, 2017

    @plietar
    Contributor

    I'd like to work on this, I already have some prototype

  3. aturon commented on Sep 29, 2017

    @aturon
    ContributorAuthor

    Awesome @plietar! It'd probably be good to bring this up in the "middle-end" compiler working group channel, which would also be a good place to get any help you might need.

  4. joshtriplett commented on Nov 23, 2017

    @joshtriplett
    Member

    @plietar How goes the implementation? I remember you showing a mostly complete prototype on IRC.

  5. thedataking commented on Feb 14, 2018

    @thedataking

    @plietar any news to share? This is a blocker for teams working on C to Rust transpilers, so this addition would be very welcome. (I'm part of one such team).

  6. plietar commented on Feb 22, 2018

    @plietar
    Contributor

    Hey,
    Sorry I've been busy and then forgot about this. I'll get my prototype back in shape, hopefully by this weekend.

  7. harpocrates commented on Mar 16, 2018

    @harpocrates
    Contributor

    @plietar Any update on this? Do you have a WIP branch I can check out to try / fiddle with this?

  8. dlrobertson commented on Mar 20, 2018

    @dlrobertson
    Contributor

    Looks like I'm a little late to the party 😄 ... sorry about that

    A few questions:

    1. How would functions that use a va_list multiple times work without the ability to explicitly use va_start and va_end? Are they expected to use copy? E.g. execl typically loops through the arguments to to get argc, creats a array argv of size argc, loops through the list again populating argv, and finally call execv.

    2. The structure of a va_list varies greatly between the architectures. The intrinsic functions work with the architecture specific structure bitcast to an i8*, but AFAIK we'll still need to define the structure. Which architectures will be expected to be supported in the first iteration? Or am I mistaken that we'll have to define the structure?

    @plietar if you don't have the time to work on this any more or if there is any way I could help out, I'd be more than happy to do so. I haven't worked on rustc much, but I'd be happy to help however I can with the implementation of this.

  9. nikomatsakis commented on Mar 20, 2018

    @nikomatsakis
    Contributor

    @dlrobertson

    Seems likely that @plietar doesn't have much time, though they can speak for themselves.

    I've not really looked closely at what would be needed to implement this, but if you need any help, please ping me, or reach out on gitter/IRC.

  10. dlrobertson commented on Apr 4, 2018

    @dlrobertson
    Contributor

    I've been working on this for the past two week and have

    • Added va_list_kind to the target specification which closely mirrors clangs TargetInfo::BuiltinVaListKind
    • Added Type::va_list which builds the correct structure based on the targets va_list_kind

    I'm struggling a bit with understanding how to write something in libcore and link that to Type::va_list in trans. I'm currently attempting to add #[lang = "va_list"] so that I can check the def.did against the lang_items().va_list_impl() id. Does this seem correct?

    Also how would you like me to break this up into PRs? My current plan was to submit a PR once I got VaList implemented (meaning functions like vprintf could be defined and tested). Then submit a second PR for implementing support for functions like printf.

  11. 399 remaining items

  12. added 2 commits that reference this issue on Aug 4, 2026
  13. added a commit that references this issue on Aug 4, 2026
  14. added a commit that references this issue on Aug 4, 2026
  15. added 3 commits that reference this issue on Sep 18, 2026
  16. added a commit that references this issue on Sep 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-FFIArea: Foreign function interface (FFI)B-RFC-approvedBlocker: Approved by a merged RFC but not yet implemented.B-unstableBlocker: Implemented in the nightly compiler and unstable.C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCF-c_variadic`#![feature(c_variadic)]`I-lang-radarItems that are on lang's radar and will need eventual work or consideration.P-lang-drag-1Lang team prioritization drag level 1. https://rust-lang.zulipchat.com/#narrow/channel/410516-t-langS-tracking-ready-to-stabilizeStatus: This is ready to stabilize; it may need a stabilization report and a PRT-langRelevant to the language teamT-libs-api[DEPRECATED; DO NOT USE]disposition-mergeThis issue / PR is in PFCP or FCP with a disposition to merge it.finished-final-comment-periodThe final comment period is finished for this PR / Issue.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions