c_variadic: impl va_copy and va_end as Rust intrinsics - #150436

Merged
rust-bors[bot] merged 2 commits into
rust-lang:mainfrom
folkertdev:va-list-copy
Jan 21, 2026
Merged

c_variadic: impl va_copy and va_end as Rust intrinsics#150436
rust-bors[bot] merged 2 commits into
rust-lang:mainfrom
folkertdev:va-list-copy

Conversation

@folkertdev

@folkertdevfolkertdev commented Dec 27, 2025

Copy link
Copy Markdown
Contributor

tracking issue: #44930

Implement va_copy as (the rust equivalent of) memcpy, which is the behavior of all current LLVM targets. By providing our own implementation, we can guarantee its behavior. These guarantees are important for implementing c-variadics in e.g. const-eval.

Discussed in #t-compiler/const-eval > c-variadics in const-eval.

I've also updated the comment for Drop a bit. The background here is that the C standard requires that va_end is used in the same function (and really, in the same scope) as the corresponding va_start or va_copy. That is because historically va_start would start a scope, which va_end would then close. e.g.

https://softwarepreservation.computerhistory.org/c_plus_plus/cfront/release_3.0.3/source/incl-master/proto-headers/stdarg.sol

#defineva_start(ap, parmN) {\
va_buf _va;\
_vastart(ap = (va_list)_va, (char *)&parmN + sizeof parmN)
#defineva_end(ap) }
#defineva_arg(ap, mode) *((mode *)_vaarg(ap, sizeof (mode)))

The C standard still has to consider such implementations, but for Rust they are irrelevant. Hence we can use Clone for va_copy and Drop for va_end.

@rustbotrustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Dec 27, 2025
Comment on lines 158 to 163
/// Basic implementation of a `va_list`.
#[repr(transparent)]
#[derive(Debug)]
#[derive(Debug, Clone, Copy)]
struct VaListInner {
ptr: *const c_void,
}

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

/// https://github.com/llvm/llvm-project/blob/0cdc1b6dd4a870fc41d4b15ad97e0001882aba58/clang/lib/CodeGen/Targets/Hexagon.cpp#L407-L417
#[repr(C)]
#[derive(Debug)]
#[derive(Debug, Clone, Copy)]

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

/// https://github.com/llvm/llvm-project/blob/af9a4263a1a209953a1d339ef781a954e31268ff/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp#L1211-L1215
#[repr(C)]
#[derive(Debug)]
#[derive(Debug, Clone, Copy)]

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

/// https://docs.google.com/gview?embedded=true&url=https://github.com/IBM/s390x-abi/releases/download/v1.7/lzsabi_s390x.pdf
#[repr(C)]
#[derive(Debug)]
#[derive(Debug, Clone, Copy)]

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

/// [GCC header]: https://web.mit.edu/darwin/src/modules/gcc/gcc/ginclude/va-ppc.h
#[repr(C)]
#[derive(Debug)]
#[derive(Debug, Clone, Copy)]

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Comment threadlibrary/core/src/ffi/va_list.rs
@folkertdevfolkertdev added the F-c_variadic `#![feature(c_variadic)]` label Dec 27, 2025
@rust-log-analyzer

This comment has been minimized.

@folkertdev
folkertdevforce-pushed the va-list-copy branch 3 times, most recently from 7a78640 to 8e09112CompareJanuary 2, 2026 21:02
@rustbotrustbot added the A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. label Jan 2, 2026
@folkertdev

Copy link
Copy Markdown
ContributorAuthor

r? @workingjubilee

The codegen of VaList::clone is target-specific now, and because minicore does not define VaList it is hard to test. I think it's fine to just test the behavior, and have LLVM use a memcpy when VaList is a struct, or just re-use the pointer value if it's just a pointer.

@folkertdev
folkertdev marked this pull request as ready for review January 2, 2026 21:04
@rustbot

Copy link
Copy Markdown
Collaborator

workingjubilee is currently at their maximum review capacity.
They may take a while to respond.

@rustbotrustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jan 2, 2026
@rustbot

Copy link
Copy Markdown
Collaborator

Some changes occurred in compiler/rustc_codegen_cranelift

cc @bjorn3

Some changes occurred to the intrinsics. Make sure the CTFE / Miri interpreter
gets adapted for the changes, if necessary.

cc @rust-lang/miri, @RalfJung, @oli-obk, @lcnr

Some changes occurred in compiler/rustc_codegen_gcc

cc @antoyo, @GuillaumeGomez

@rustbotrustbot removed the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Jan 2, 2026
@RalfJung

Copy link
Copy Markdown
Member

Implement va_copy as (the rust equivalent of) memcpy, which is the behavior of all current LLVM targets. By providing our own implementation, we can guarantee its behavior.

Didn't we say we would avoid that assumption and also support implementations that do malloc/free in va_copy / va_end? See #t-compiler/const-eval > c-variadics in const-eval @ 💬.

@folkertdev

Copy link
Copy Markdown
ContributorAuthor

That's right, we don't actually impl Copy for VaList, so that a future target could implement a meaningful Clone and Drop. It's just that in practice for all current targets Clone happens to be a memcpy and Drop a no-op

@workingjubileeworkingjubilee left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Offering a suggested historical note.

Please feel free to trim it or move it into the PR description itself, down to the amounts you find worthwhile or just amusing to keep (including 0 lines).

r=me after

Thanks!

View changes since this review

Comment threadlibrary/core/src/ffi/va_list.rs
@workingjubileeworkingjubilee added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jan 6, 2026
@RalfJung

Copy link
Copy Markdown
Member

@folkertdev what is your plan for va_copy regarding the const-eval support for this?
ISTM that without the intrinsic, it'll not be possible to catch a bunch of the UB that we had planned to catch?

Comment threadlibrary/core/src/intrinsics/mod.rs
@folkertdevfolkertdev changed the title c_variadic: use Clone instead of va_copyc_variadic: use Clone instead of LLVM va_copyJan 7, 2026
@rustbot

This comment has been minimized.

@folkertdev

Copy link
Copy Markdown
ContributorAuthor

Based on further discussion in #t-compiler/const-eval > c-variadics in const-eval, a slight change of plans

  • we still no longer call LLVM's va_copy
  • we do still have our own va_copy intrinsic that serves as a hook for const evaluation
  • va_copy has a fallback body, code generation backends should not provide their own implementation

I've changed the signature of the intrinsic to be more ergonomic, and made it safe because while the hook is used to detect UB, the intrinsic itself is completely safe.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rustbotrustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jan 19, 2026
@rust-log-analyzer

This comment has been minimized.

Comment threadlibrary/core/src/ffi/va_list.rs Outdated
///
/// See the [LLVM source] and [GCC header] for more details.
///
/// `va_copy` is `memcpy`: <https://github.com/llvm/llvm-project/blob/5aee01a3df011e660f26660bc30a8c94a1651d8e/llvm/lib/Target/PowerPC/PPCISelLowering.h#L713>

@RalfJungRalfJungJan 19, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is also just a header, not the implementation? (same for some of the other ones)

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Ah now I understand what happened: i copied these links from a github search result page. I manually looked them all up now, so all links should be correct.

@folkertdev
folkertdevforce-pushed the va-list-copy branch 2 times, most recently from 94ce7b4 to 6011fa6CompareJanuary 19, 2026 20:55
@RalfJung

Copy link
Copy Markdown
Member

Sounds great, thanks! r=workingjubilee,RalfJung with the last commit squashed away.

@bors delegate+

@rust-bors

rust-borsBot commented Jan 20, 2026

Copy link
Copy Markdown
Contributor

✌️ @folkertdev, you can now approve this pull request!

If @RalfJung told you to "r=me" after making some further change, then please make that change and post @bors r=RalfJung.

@folkertdev

Copy link
Copy Markdown
ContributorAuthor

@bors r=workingjubilee,RalfJung

@rust-bors

rust-borsBot commented Jan 20, 2026

Copy link
Copy Markdown
Contributor

📌 Commit 922057c has been approved by workingjubilee,RalfJung

It is now in the queue for this repository.

@rust-borsrust-borsBot added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jan 20, 2026
@jhprattjhpratt mentioned this pull request Jan 21, 2026
rust-borsBot pushed a commit that referenced this pull request Jan 21, 2026
Rollup of 6 pull requests
Successful merges:
- #150436 (`c_variadic`: impl `va_copy` and `va_end` as Rust intrinsics)
- #151340 (Port `#[patchable_function_entry]` to attr parser)
- #151351 (Deduplicate diagnostics for const trait supertraits)
- #151424 (missing colon after the compile-flags directive)
- #151428 (Port variance attrs to attr parser.)
- #151429 (s390x: Support aligned stack datalayout)
Failed merges:
- #151343 (Port some crate level attrs to the attribute parser)
r? @ghost
@rust-bors
rust-borsBot merged commit 43d2006 into rust-lang:mainJan 21, 2026
11 checks passed
@rustbotrustbot added this to the 1.95.0 milestone Jan 21, 2026
rust-timer added a commit that referenced this pull request Jan 21, 2026
Rollup merge of #150436 - va-list-copy, r=workingjubilee,RalfJung
`c_variadic`: impl `va_copy` and `va_end` as Rust intrinsics
tracking issue: #44930
Implement `va_copy` as (the rust equivalent of) `memcpy`, which is the behavior of all current LLVM targets. By providing our own implementation, we can guarantee its behavior. These guarantees are important for implementing c-variadics in e.g. const-eval.
Discussed in [#t-compiler/const-eval > c-variadics in const-eval](https://rust-lang.zulipchat.com/#narrow/channel/146212-t-compiler.2Fconst-eval/topic/c-variadics.20in.20const-eval/with/565509704).
I've also updated the comment for `Drop` a bit. The background here is that the C standard requires that `va_end` is used in the same function (and really, in the same scope) as the corresponding `va_start` or `va_copy`. That is because historically `va_start` would start a scope, which `va_end` would then close. e.g.
https://softwarepreservation.computerhistory.org/c_plus_plus/cfront/release_3.0.3/source/incl-master/proto-headers/stdarg.sol
```c
#define va_start(ap, parmN) {\
va_buf _va;\
_vastart(ap = (va_list)_va, (char *)&parmN + sizeof parmN)
#define va_end(ap) }
#define va_arg(ap, mode) *((mode *)_vaarg(ap, sizeof (mode)))
```
The C standard still has to consider such implementations, but for Rust they are irrelevant. Hence we can use `Clone` for `va_copy` and `Drop` for `va_end`.
christian-schilling pushed a commit to christian-schilling/rustc_codegen_cranelift that referenced this pull request Jan 27, 2026
Rollup of 6 pull requests
Successful merges:
- rust-lang/rust#150436 (`c_variadic`: impl `va_copy` and `va_end` as Rust intrinsics)
- rust-lang/rust#151340 (Port `#[patchable_function_entry]` to attr parser)
- rust-lang/rust#151351 (Deduplicate diagnostics for const trait supertraits)
- rust-lang/rust#151424 (missing colon after the compile-flags directive)
- rust-lang/rust#151428 (Port variance attrs to attr parser.)
- rust-lang/rust#151429 (s390x: Support aligned stack datalayout)
Failed merges:
- rust-lang/rust#151343 (Port some crate level attrs to the attribute parser)
r? @ghost
christian-schilling pushed a commit to christian-schilling/rustc_codegen_cranelift that referenced this pull request Jan 27, 2026
Rollup of 6 pull requests
Successful merges:
- rust-lang/rust#150436 (`c_variadic`: impl `va_copy` and `va_end` as Rust intrinsics)
- rust-lang/rust#151340 (Port `#[patchable_function_entry]` to attr parser)
- rust-lang/rust#151351 (Deduplicate diagnostics for const trait supertraits)
- rust-lang/rust#151424 (missing colon after the compile-flags directive)
- rust-lang/rust#151428 (Port variance attrs to attr parser.)
- rust-lang/rust#151429 (s390x: Support aligned stack datalayout)
Failed merges:
- rust-lang/rust#151343 (Port some crate level attrs to the attribute parser)
r? @ghost
bjorn3 pushed a commit to bjorn3/rust that referenced this pull request Feb 18, 2026
…fJung
`c_variadic`: impl `va_copy` and `va_end` as Rust intrinsics
tracking issue: rust-lang#44930
Implement `va_copy` as (the rust equivalent of) `memcpy`, which is the behavior of all current LLVM targets. By providing our own implementation, we can guarantee its behavior. These guarantees are important for implementing c-variadics in e.g. const-eval.
Discussed in [#t-compiler/const-eval > c-variadics in const-eval](https://rust-lang.zulipchat.com/#narrow/channel/146212-t-compiler.2Fconst-eval/topic/c-variadics.20in.20const-eval/with/565509704).
I've also updated the comment for `Drop` a bit. The background here is that the C standard requires that `va_end` is used in the same function (and really, in the same scope) as the corresponding `va_start` or `va_copy`. That is because historically `va_start` would start a scope, which `va_end` would then close. e.g.
https://softwarepreservation.computerhistory.org/c_plus_plus/cfront/release_3.0.3/source/incl-master/proto-headers/stdarg.sol
```c
#define va_start(ap, parmN) {\
va_buf _va;\
_vastart(ap = (va_list)_va, (char *)&parmN + sizeof parmN)
#define va_end(ap) }
#define va_arg(ap, mode) *((mode *)_vaarg(ap, sizeof (mode)))
```
The C standard still has to consider such implementations, but for Rust they are irrelevant. Hence we can use `Clone` for `va_copy` and `Drop` for `va_end`.
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Jul 31, 2026
…comments, r=folkertdev
Remove outdated comments from `va_list.rs`
Since rust-lang#150436 codegen backends haven't needed to implement `va_copy` or `va_end` as they are implemented using intrinsic fallback bodies, so the comments on the `#[inline]` annotations are no longer relevant. I've left the `#[inline]` annotations themselves as they seem worthwhile since `va_copy` and `va_end` are a memcpy and a no-op respectively.
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Jul 31, 2026
…comments, r=folkertdev
Remove outdated comments from `va_list.rs`
Since rust-lang#150436 codegen backends haven't needed to implement `va_copy` or `va_end` as they are implemented using intrinsic fallback bodies, so the comments on the `#[inline]` annotations are no longer relevant. I've left the `#[inline]` annotations themselves as they seem worthwhile since `va_copy` and `va_end` are a memcpy and a no-op respectively.
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Jul 31, 2026
…comments, r=folkertdev
Remove outdated comments from `va_list.rs`
Since rust-lang#150436 codegen backends haven't needed to implement `va_copy` or `va_end` as they are implemented using intrinsic fallback bodies, so the comments on the `#[inline]` annotations are no longer relevant. I've left the `#[inline]` annotations themselves as they seem worthwhile since `va_copy` and `va_end` are a memcpy and a no-op respectively.
rust-timer added a commit that referenced this pull request Jul 31, 2026
Rollup merge of #160157 - beetrees:va-list-outdated-backend-comments, r=folkertdev
Remove outdated comments from `va_list.rs`
Since #150436 codegen backends haven't needed to implement `va_copy` or `va_end` as they are implemented using intrinsic fallback bodies, so the comments on the `#[inline]` annotations are no longer relevant. I've left the `#[inline]` annotations themselves as they seem worthwhile since `va_copy` and `va_end` are a memcpy and a no-op respectively.
github-actionsBot pushed a commit to rust-lang/rustc-dev-guide that referenced this pull request Aug 3, 2026
… r=folkertdev
Remove outdated comments from `va_list.rs`
Since rust-lang/rust#150436 codegen backends haven't needed to implement `va_copy` or `va_end` as they are implemented using intrinsic fallback bodies, so the comments on the `#[inline]` annotations are no longer relevant. I've left the `#[inline]` annotations themselves as they seem worthwhile since `va_copy` and `va_end` are a memcpy and a no-op respectively.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.F-c_variadic`#![feature(c_variadic)]`S-waiting-on-borsStatus: Waiting on bors to run and complete tests. Bors will change the label on completion.T-libsRelevant to the library team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@folkertdev@rust-log-analyzer@rustbot@RalfJung@workingjubilee
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

c_variadic: impl va_copy and va_end as Rust intrinsics - #150436

Merged
rust-bors[bot] merged 2 commits into
rust-lang:mainfrom
folkertdev:va-list-copy
Jan 21, 2026
Merged

c_variadic: impl va_copy and va_end as Rust intrinsics#150436
rust-bors[bot] merged 2 commits into
rust-lang:mainfrom
folkertdev:va-list-copy

Conversation

@folkertdev

@folkertdevfolkertdev commented Dec 27, 2025

Copy link
Copy Markdown
Contributor

tracking issue: #44930

Implement va_copy as (the rust equivalent of) memcpy, which is the behavior of all current LLVM targets. By providing our own implementation, we can guarantee its behavior. These guarantees are important for implementing c-variadics in e.g. const-eval.

Discussed in #t-compiler/const-eval > c-variadics in const-eval.

I've also updated the comment for Drop a bit. The background here is that the C standard requires that va_end is used in the same function (and really, in the same scope) as the corresponding va_start or va_copy. That is because historically va_start would start a scope, which va_end would then close. e.g.

https://softwarepreservation.computerhistory.org/c_plus_plus/cfront/release_3.0.3/source/incl-master/proto-headers/stdarg.sol

#defineva_start(ap, parmN) {\
va_buf _va;\
_vastart(ap = (va_list)_va, (char *)&parmN + sizeof parmN)
#defineva_end(ap) }
#defineva_arg(ap, mode) *((mode *)_vaarg(ap, sizeof (mode)))

The C standard still has to consider such implementations, but for Rust they are irrelevant. Hence we can use Clone for va_copy and Drop for va_end.

@rustbotrustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Dec 27, 2025
Comment on lines 158 to 163
/// Basic implementation of a `va_list`.
#[repr(transparent)]
#[derive(Debug)]
#[derive(Debug, Clone, Copy)]
struct VaListInner {
ptr: *const c_void,
}

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

/// https://github.com/llvm/llvm-project/blob/0cdc1b6dd4a870fc41d4b15ad97e0001882aba58/clang/lib/CodeGen/Targets/Hexagon.cpp#L407-L417
#[repr(C)]
#[derive(Debug)]
#[derive(Debug, Clone, Copy)]

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

/// https://github.com/llvm/llvm-project/blob/af9a4263a1a209953a1d339ef781a954e31268ff/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp#L1211-L1215
#[repr(C)]
#[derive(Debug)]
#[derive(Debug, Clone, Copy)]

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

/// https://docs.google.com/gview?embedded=true&url=https://github.com/IBM/s390x-abi/releases/download/v1.7/lzsabi_s390x.pdf
#[repr(C)]
#[derive(Debug)]
#[derive(Debug, Clone, Copy)]

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

/// [GCC header]: https://web.mit.edu/darwin/src/modules/gcc/gcc/ginclude/va-ppc.h
#[repr(C)]
#[derive(Debug)]
#[derive(Debug, Clone, Copy)]

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Comment threadlibrary/core/src/ffi/va_list.rs
@folkertdevfolkertdev added the F-c_variadic `#![feature(c_variadic)]` label Dec 27, 2025
@rust-log-analyzer

This comment has been minimized.

@folkertdev
folkertdevforce-pushed the va-list-copy branch 3 times, most recently from 7a78640 to 8e09112CompareJanuary 2, 2026 21:02
@rustbotrustbot added the A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. label Jan 2, 2026
@folkertdev

Copy link
Copy Markdown
ContributorAuthor

r? @workingjubilee

The codegen of VaList::clone is target-specific now, and because minicore does not define VaList it is hard to test. I think it's fine to just test the behavior, and have LLVM use a memcpy when VaList is a struct, or just re-use the pointer value if it's just a pointer.

@folkertdev
folkertdev marked this pull request as ready for review January 2, 2026 21:04
@rustbot

Copy link
Copy Markdown
Collaborator

workingjubilee is currently at their maximum review capacity.
They may take a while to respond.

@rustbotrustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jan 2, 2026
@rustbot

Copy link
Copy Markdown
Collaborator

Some changes occurred in compiler/rustc_codegen_cranelift

cc @bjorn3

Some changes occurred to the intrinsics. Make sure the CTFE / Miri interpreter
gets adapted for the changes, if necessary.

cc @rust-lang/miri, @RalfJung, @oli-obk, @lcnr

Some changes occurred in compiler/rustc_codegen_gcc

cc @antoyo, @GuillaumeGomez

@rustbotrustbot removed the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Jan 2, 2026
@RalfJung

Copy link
Copy Markdown
Member

Implement va_copy as (the rust equivalent of) memcpy, which is the behavior of all current LLVM targets. By providing our own implementation, we can guarantee its behavior.

Didn't we say we would avoid that assumption and also support implementations that do malloc/free in va_copy / va_end? See #t-compiler/const-eval > c-variadics in const-eval @ 💬.

@folkertdev

Copy link
Copy Markdown
ContributorAuthor

That's right, we don't actually impl Copy for VaList, so that a future target could implement a meaningful Clone and Drop. It's just that in practice for all current targets Clone happens to be a memcpy and Drop a no-op

@workingjubileeworkingjubilee left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Offering a suggested historical note.

Please feel free to trim it or move it into the PR description itself, down to the amounts you find worthwhile or just amusing to keep (including 0 lines).

r=me after

Thanks!

View changes since this review

Comment threadlibrary/core/src/ffi/va_list.rs
@workingjubileeworkingjubilee added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jan 6, 2026
@RalfJung

Copy link
Copy Markdown
Member

@folkertdev what is your plan for va_copy regarding the const-eval support for this?
ISTM that without the intrinsic, it'll not be possible to catch a bunch of the UB that we had planned to catch?

Comment threadlibrary/core/src/intrinsics/mod.rs
@folkertdevfolkertdev changed the title c_variadic: use Clone instead of va_copyc_variadic: use Clone instead of LLVM va_copyJan 7, 2026
@rustbot

This comment has been minimized.

@folkertdev

Copy link
Copy Markdown
ContributorAuthor

Based on further discussion in #t-compiler/const-eval > c-variadics in const-eval, a slight change of plans

  • we still no longer call LLVM's va_copy
  • we do still have our own va_copy intrinsic that serves as a hook for const evaluation
  • va_copy has a fallback body, code generation backends should not provide their own implementation

I've changed the signature of the intrinsic to be more ergonomic, and made it safe because while the hook is used to detect UB, the intrinsic itself is completely safe.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rustbotrustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jan 19, 2026
@rust-log-analyzer

This comment has been minimized.

Comment threadlibrary/core/src/ffi/va_list.rs Outdated
///
/// See the [LLVM source] and [GCC header] for more details.
///
/// `va_copy` is `memcpy`: <https://github.com/llvm/llvm-project/blob/5aee01a3df011e660f26660bc30a8c94a1651d8e/llvm/lib/Target/PowerPC/PPCISelLowering.h#L713>

@RalfJungRalfJungJan 19, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is also just a header, not the implementation? (same for some of the other ones)

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Ah now I understand what happened: i copied these links from a github search result page. I manually looked them all up now, so all links should be correct.

@folkertdev
folkertdevforce-pushed the va-list-copy branch 2 times, most recently from 94ce7b4 to 6011fa6CompareJanuary 19, 2026 20:55
@RalfJung

Copy link
Copy Markdown
Member

Sounds great, thanks! r=workingjubilee,RalfJung with the last commit squashed away.

@bors delegate+

@rust-bors

rust-borsBot commented Jan 20, 2026

Copy link
Copy Markdown
Contributor

✌️ @folkertdev, you can now approve this pull request!

If @RalfJung told you to "r=me" after making some further change, then please make that change and post @bors r=RalfJung.

@folkertdev

Copy link
Copy Markdown
ContributorAuthor

@bors r=workingjubilee,RalfJung

@rust-bors

rust-borsBot commented Jan 20, 2026

Copy link
Copy Markdown
Contributor

📌 Commit 922057c has been approved by workingjubilee,RalfJung

It is now in the queue for this repository.

@rust-borsrust-borsBot added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jan 20, 2026
@jhprattjhpratt mentioned this pull request Jan 21, 2026
rust-borsBot pushed a commit that referenced this pull request Jan 21, 2026
Rollup of 6 pull requests
Successful merges:
- #150436 (`c_variadic`: impl `va_copy` and `va_end` as Rust intrinsics)
- #151340 (Port `#[patchable_function_entry]` to attr parser)
- #151351 (Deduplicate diagnostics for const trait supertraits)
- #151424 (missing colon after the compile-flags directive)
- #151428 (Port variance attrs to attr parser.)
- #151429 (s390x: Support aligned stack datalayout)
Failed merges:
- #151343 (Port some crate level attrs to the attribute parser)
r? @ghost
@rust-bors
rust-borsBot merged commit 43d2006 into rust-lang:mainJan 21, 2026
11 checks passed
@rustbotrustbot added this to the 1.95.0 milestone Jan 21, 2026
rust-timer added a commit that referenced this pull request Jan 21, 2026
Rollup merge of #150436 - va-list-copy, r=workingjubilee,RalfJung
`c_variadic`: impl `va_copy` and `va_end` as Rust intrinsics
tracking issue: #44930
Implement `va_copy` as (the rust equivalent of) `memcpy`, which is the behavior of all current LLVM targets. By providing our own implementation, we can guarantee its behavior. These guarantees are important for implementing c-variadics in e.g. const-eval.
Discussed in [#t-compiler/const-eval > c-variadics in const-eval](https://rust-lang.zulipchat.com/#narrow/channel/146212-t-compiler.2Fconst-eval/topic/c-variadics.20in.20const-eval/with/565509704).
I've also updated the comment for `Drop` a bit. The background here is that the C standard requires that `va_end` is used in the same function (and really, in the same scope) as the corresponding `va_start` or `va_copy`. That is because historically `va_start` would start a scope, which `va_end` would then close. e.g.
https://softwarepreservation.computerhistory.org/c_plus_plus/cfront/release_3.0.3/source/incl-master/proto-headers/stdarg.sol
```c
#define va_start(ap, parmN) {\
va_buf _va;\
_vastart(ap = (va_list)_va, (char *)&parmN + sizeof parmN)
#define va_end(ap) }
#define va_arg(ap, mode) *((mode *)_vaarg(ap, sizeof (mode)))
```
The C standard still has to consider such implementations, but for Rust they are irrelevant. Hence we can use `Clone` for `va_copy` and `Drop` for `va_end`.
christian-schilling pushed a commit to christian-schilling/rustc_codegen_cranelift that referenced this pull request Jan 27, 2026
Rollup of 6 pull requests
Successful merges:
- rust-lang/rust#150436 (`c_variadic`: impl `va_copy` and `va_end` as Rust intrinsics)
- rust-lang/rust#151340 (Port `#[patchable_function_entry]` to attr parser)
- rust-lang/rust#151351 (Deduplicate diagnostics for const trait supertraits)
- rust-lang/rust#151424 (missing colon after the compile-flags directive)
- rust-lang/rust#151428 (Port variance attrs to attr parser.)
- rust-lang/rust#151429 (s390x: Support aligned stack datalayout)
Failed merges:
- rust-lang/rust#151343 (Port some crate level attrs to the attribute parser)
r? @ghost
christian-schilling pushed a commit to christian-schilling/rustc_codegen_cranelift that referenced this pull request Jan 27, 2026
Rollup of 6 pull requests
Successful merges:
- rust-lang/rust#150436 (`c_variadic`: impl `va_copy` and `va_end` as Rust intrinsics)
- rust-lang/rust#151340 (Port `#[patchable_function_entry]` to attr parser)
- rust-lang/rust#151351 (Deduplicate diagnostics for const trait supertraits)
- rust-lang/rust#151424 (missing colon after the compile-flags directive)
- rust-lang/rust#151428 (Port variance attrs to attr parser.)
- rust-lang/rust#151429 (s390x: Support aligned stack datalayout)
Failed merges:
- rust-lang/rust#151343 (Port some crate level attrs to the attribute parser)
r? @ghost
bjorn3 pushed a commit to bjorn3/rust that referenced this pull request Feb 18, 2026
…fJung
`c_variadic`: impl `va_copy` and `va_end` as Rust intrinsics
tracking issue: rust-lang#44930
Implement `va_copy` as (the rust equivalent of) `memcpy`, which is the behavior of all current LLVM targets. By providing our own implementation, we can guarantee its behavior. These guarantees are important for implementing c-variadics in e.g. const-eval.
Discussed in [#t-compiler/const-eval > c-variadics in const-eval](https://rust-lang.zulipchat.com/#narrow/channel/146212-t-compiler.2Fconst-eval/topic/c-variadics.20in.20const-eval/with/565509704).
I've also updated the comment for `Drop` a bit. The background here is that the C standard requires that `va_end` is used in the same function (and really, in the same scope) as the corresponding `va_start` or `va_copy`. That is because historically `va_start` would start a scope, which `va_end` would then close. e.g.
https://softwarepreservation.computerhistory.org/c_plus_plus/cfront/release_3.0.3/source/incl-master/proto-headers/stdarg.sol
```c
#define va_start(ap, parmN) {\
va_buf _va;\
_vastart(ap = (va_list)_va, (char *)&parmN + sizeof parmN)
#define va_end(ap) }
#define va_arg(ap, mode) *((mode *)_vaarg(ap, sizeof (mode)))
```
The C standard still has to consider such implementations, but for Rust they are irrelevant. Hence we can use `Clone` for `va_copy` and `Drop` for `va_end`.
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Jul 31, 2026
…comments, r=folkertdev
Remove outdated comments from `va_list.rs`
Since rust-lang#150436 codegen backends haven't needed to implement `va_copy` or `va_end` as they are implemented using intrinsic fallback bodies, so the comments on the `#[inline]` annotations are no longer relevant. I've left the `#[inline]` annotations themselves as they seem worthwhile since `va_copy` and `va_end` are a memcpy and a no-op respectively.
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Jul 31, 2026
…comments, r=folkertdev
Remove outdated comments from `va_list.rs`
Since rust-lang#150436 codegen backends haven't needed to implement `va_copy` or `va_end` as they are implemented using intrinsic fallback bodies, so the comments on the `#[inline]` annotations are no longer relevant. I've left the `#[inline]` annotations themselves as they seem worthwhile since `va_copy` and `va_end` are a memcpy and a no-op respectively.
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Jul 31, 2026
…comments, r=folkertdev
Remove outdated comments from `va_list.rs`
Since rust-lang#150436 codegen backends haven't needed to implement `va_copy` or `va_end` as they are implemented using intrinsic fallback bodies, so the comments on the `#[inline]` annotations are no longer relevant. I've left the `#[inline]` annotations themselves as they seem worthwhile since `va_copy` and `va_end` are a memcpy and a no-op respectively.
rust-timer added a commit that referenced this pull request Jul 31, 2026
Rollup merge of #160157 - beetrees:va-list-outdated-backend-comments, r=folkertdev
Remove outdated comments from `va_list.rs`
Since #150436 codegen backends haven't needed to implement `va_copy` or `va_end` as they are implemented using intrinsic fallback bodies, so the comments on the `#[inline]` annotations are no longer relevant. I've left the `#[inline]` annotations themselves as they seem worthwhile since `va_copy` and `va_end` are a memcpy and a no-op respectively.
github-actionsBot pushed a commit to rust-lang/rustc-dev-guide that referenced this pull request Aug 3, 2026
… r=folkertdev
Remove outdated comments from `va_list.rs`
Since rust-lang/rust#150436 codegen backends haven't needed to implement `va_copy` or `va_end` as they are implemented using intrinsic fallback bodies, so the comments on the `#[inline]` annotations are no longer relevant. I've left the `#[inline]` annotations themselves as they seem worthwhile since `va_copy` and `va_end` are a memcpy and a no-op respectively.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.F-c_variadic`#![feature(c_variadic)]`S-waiting-on-borsStatus: Waiting on bors to run and complete tests. Bors will change the label on completion.T-libsRelevant to the library team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@folkertdev@rust-log-analyzer@rustbot@RalfJung@workingjubilee
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

c_variadic: impl va_copy and va_end as Rust intrinsics - #150436

Merged
rust-bors[bot] merged 2 commits into
rust-lang:mainfrom
folkertdev:va-list-copy
Jan 21, 2026
Merged

c_variadic: impl va_copy and va_end as Rust intrinsics#150436
rust-bors[bot] merged 2 commits into
rust-lang:mainfrom
folkertdev:va-list-copy

Conversation

@folkertdev

@folkertdevfolkertdev commented Dec 27, 2025

Copy link
Copy Markdown
Contributor

tracking issue: #44930

Implement va_copy as (the rust equivalent of) memcpy, which is the behavior of all current LLVM targets. By providing our own implementation, we can guarantee its behavior. These guarantees are important for implementing c-variadics in e.g. const-eval.

Discussed in #t-compiler/const-eval > c-variadics in const-eval.

I've also updated the comment for Drop a bit. The background here is that the C standard requires that va_end is used in the same function (and really, in the same scope) as the corresponding va_start or va_copy. That is because historically va_start would start a scope, which va_end would then close. e.g.

https://softwarepreservation.computerhistory.org/c_plus_plus/cfront/release_3.0.3/source/incl-master/proto-headers/stdarg.sol

#defineva_start(ap, parmN) {\
va_buf _va;\
_vastart(ap = (va_list)_va, (char *)&parmN + sizeof parmN)
#defineva_end(ap) }
#defineva_arg(ap, mode) *((mode *)_vaarg(ap, sizeof (mode)))

The C standard still has to consider such implementations, but for Rust they are irrelevant. Hence we can use Clone for va_copy and Drop for va_end.

@rustbotrustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Dec 27, 2025
Comment on lines 158 to 163
/// Basic implementation of a `va_list`.
#[repr(transparent)]
#[derive(Debug)]
#[derive(Debug, Clone, Copy)]
struct VaListInner {
ptr: *const c_void,
}

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

/// https://github.com/llvm/llvm-project/blob/0cdc1b6dd4a870fc41d4b15ad97e0001882aba58/clang/lib/CodeGen/Targets/Hexagon.cpp#L407-L417
#[repr(C)]
#[derive(Debug)]
#[derive(Debug, Clone, Copy)]

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

/// https://github.com/llvm/llvm-project/blob/af9a4263a1a209953a1d339ef781a954e31268ff/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp#L1211-L1215
#[repr(C)]
#[derive(Debug)]
#[derive(Debug, Clone, Copy)]

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

/// https://docs.google.com/gview?embedded=true&url=https://github.com/IBM/s390x-abi/releases/download/v1.7/lzsabi_s390x.pdf
#[repr(C)]
#[derive(Debug)]
#[derive(Debug, Clone, Copy)]

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

/// [GCC header]: https://web.mit.edu/darwin/src/modules/gcc/gcc/ginclude/va-ppc.h
#[repr(C)]
#[derive(Debug)]
#[derive(Debug, Clone, Copy)]

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Comment threadlibrary/core/src/ffi/va_list.rs
@folkertdevfolkertdev added the F-c_variadic `#![feature(c_variadic)]` label Dec 27, 2025
@rust-log-analyzer

This comment has been minimized.

@folkertdev
folkertdevforce-pushed the va-list-copy branch 3 times, most recently from 7a78640 to 8e09112CompareJanuary 2, 2026 21:02
@rustbotrustbot added the A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. label Jan 2, 2026
@folkertdev

Copy link
Copy Markdown
ContributorAuthor

r? @workingjubilee

The codegen of VaList::clone is target-specific now, and because minicore does not define VaList it is hard to test. I think it's fine to just test the behavior, and have LLVM use a memcpy when VaList is a struct, or just re-use the pointer value if it's just a pointer.

@folkertdev
folkertdev marked this pull request as ready for review January 2, 2026 21:04
@rustbot

Copy link
Copy Markdown
Collaborator

workingjubilee is currently at their maximum review capacity.
They may take a while to respond.

@rustbotrustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jan 2, 2026
@rustbot

Copy link
Copy Markdown
Collaborator

Some changes occurred in compiler/rustc_codegen_cranelift

cc @bjorn3

Some changes occurred to the intrinsics. Make sure the CTFE / Miri interpreter
gets adapted for the changes, if necessary.

cc @rust-lang/miri, @RalfJung, @oli-obk, @lcnr

Some changes occurred in compiler/rustc_codegen_gcc

cc @antoyo, @GuillaumeGomez

@rustbotrustbot removed the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Jan 2, 2026
@RalfJung

Copy link
Copy Markdown
Member

Implement va_copy as (the rust equivalent of) memcpy, which is the behavior of all current LLVM targets. By providing our own implementation, we can guarantee its behavior.

Didn't we say we would avoid that assumption and also support implementations that do malloc/free in va_copy / va_end? See #t-compiler/const-eval > c-variadics in const-eval @ 💬.

@folkertdev

Copy link
Copy Markdown
ContributorAuthor

That's right, we don't actually impl Copy for VaList, so that a future target could implement a meaningful Clone and Drop. It's just that in practice for all current targets Clone happens to be a memcpy and Drop a no-op

@workingjubileeworkingjubilee left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Offering a suggested historical note.

Please feel free to trim it or move it into the PR description itself, down to the amounts you find worthwhile or just amusing to keep (including 0 lines).

r=me after

Thanks!

View changes since this review

Comment threadlibrary/core/src/ffi/va_list.rs
@workingjubileeworkingjubilee added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jan 6, 2026
@RalfJung

Copy link
Copy Markdown
Member

@folkertdev what is your plan for va_copy regarding the const-eval support for this?
ISTM that without the intrinsic, it'll not be possible to catch a bunch of the UB that we had planned to catch?

Comment threadlibrary/core/src/intrinsics/mod.rs
@folkertdevfolkertdev changed the title c_variadic: use Clone instead of va_copyc_variadic: use Clone instead of LLVM va_copyJan 7, 2026
@rustbot

This comment has been minimized.

@folkertdev

Copy link
Copy Markdown
ContributorAuthor

Based on further discussion in #t-compiler/const-eval > c-variadics in const-eval, a slight change of plans

  • we still no longer call LLVM's va_copy
  • we do still have our own va_copy intrinsic that serves as a hook for const evaluation
  • va_copy has a fallback body, code generation backends should not provide their own implementation

I've changed the signature of the intrinsic to be more ergonomic, and made it safe because while the hook is used to detect UB, the intrinsic itself is completely safe.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rustbotrustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jan 19, 2026
@rust-log-analyzer

This comment has been minimized.

Comment threadlibrary/core/src/ffi/va_list.rs Outdated
///
/// See the [LLVM source] and [GCC header] for more details.
///
/// `va_copy` is `memcpy`: <https://github.com/llvm/llvm-project/blob/5aee01a3df011e660f26660bc30a8c94a1651d8e/llvm/lib/Target/PowerPC/PPCISelLowering.h#L713>

@RalfJungRalfJungJan 19, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is also just a header, not the implementation? (same for some of the other ones)

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Ah now I understand what happened: i copied these links from a github search result page. I manually looked them all up now, so all links should be correct.

@folkertdev
folkertdevforce-pushed the va-list-copy branch 2 times, most recently from 94ce7b4 to 6011fa6CompareJanuary 19, 2026 20:55
@RalfJung

Copy link
Copy Markdown
Member

Sounds great, thanks! r=workingjubilee,RalfJung with the last commit squashed away.

@bors delegate+

@rust-bors

rust-borsBot commented Jan 20, 2026

Copy link
Copy Markdown
Contributor

✌️ @folkertdev, you can now approve this pull request!

If @RalfJung told you to "r=me" after making some further change, then please make that change and post @bors r=RalfJung.

@folkertdev

Copy link
Copy Markdown
ContributorAuthor

@bors r=workingjubilee,RalfJung

@rust-bors

rust-borsBot commented Jan 20, 2026

Copy link
Copy Markdown
Contributor

📌 Commit 922057c has been approved by workingjubilee,RalfJung

It is now in the queue for this repository.

@rust-borsrust-borsBot added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jan 20, 2026
@jhprattjhpratt mentioned this pull request Jan 21, 2026
rust-borsBot pushed a commit that referenced this pull request Jan 21, 2026
Rollup of 6 pull requests
Successful merges:
- #150436 (`c_variadic`: impl `va_copy` and `va_end` as Rust intrinsics)
- #151340 (Port `#[patchable_function_entry]` to attr parser)
- #151351 (Deduplicate diagnostics for const trait supertraits)
- #151424 (missing colon after the compile-flags directive)
- #151428 (Port variance attrs to attr parser.)
- #151429 (s390x: Support aligned stack datalayout)
Failed merges:
- #151343 (Port some crate level attrs to the attribute parser)
r? @ghost
@rust-bors
rust-borsBot merged commit 43d2006 into rust-lang:mainJan 21, 2026
11 checks passed
@rustbotrustbot added this to the 1.95.0 milestone Jan 21, 2026
rust-timer added a commit that referenced this pull request Jan 21, 2026
Rollup merge of #150436 - va-list-copy, r=workingjubilee,RalfJung
`c_variadic`: impl `va_copy` and `va_end` as Rust intrinsics
tracking issue: #44930
Implement `va_copy` as (the rust equivalent of) `memcpy`, which is the behavior of all current LLVM targets. By providing our own implementation, we can guarantee its behavior. These guarantees are important for implementing c-variadics in e.g. const-eval.
Discussed in [#t-compiler/const-eval > c-variadics in const-eval](https://rust-lang.zulipchat.com/#narrow/channel/146212-t-compiler.2Fconst-eval/topic/c-variadics.20in.20const-eval/with/565509704).
I've also updated the comment for `Drop` a bit. The background here is that the C standard requires that `va_end` is used in the same function (and really, in the same scope) as the corresponding `va_start` or `va_copy`. That is because historically `va_start` would start a scope, which `va_end` would then close. e.g.
https://softwarepreservation.computerhistory.org/c_plus_plus/cfront/release_3.0.3/source/incl-master/proto-headers/stdarg.sol
```c
#define va_start(ap, parmN) {\
va_buf _va;\
_vastart(ap = (va_list)_va, (char *)&parmN + sizeof parmN)
#define va_end(ap) }
#define va_arg(ap, mode) *((mode *)_vaarg(ap, sizeof (mode)))
```
The C standard still has to consider such implementations, but for Rust they are irrelevant. Hence we can use `Clone` for `va_copy` and `Drop` for `va_end`.
christian-schilling pushed a commit to christian-schilling/rustc_codegen_cranelift that referenced this pull request Jan 27, 2026
Rollup of 6 pull requests
Successful merges:
- rust-lang/rust#150436 (`c_variadic`: impl `va_copy` and `va_end` as Rust intrinsics)
- rust-lang/rust#151340 (Port `#[patchable_function_entry]` to attr parser)
- rust-lang/rust#151351 (Deduplicate diagnostics for const trait supertraits)
- rust-lang/rust#151424 (missing colon after the compile-flags directive)
- rust-lang/rust#151428 (Port variance attrs to attr parser.)
- rust-lang/rust#151429 (s390x: Support aligned stack datalayout)
Failed merges:
- rust-lang/rust#151343 (Port some crate level attrs to the attribute parser)
r? @ghost
christian-schilling pushed a commit to christian-schilling/rustc_codegen_cranelift that referenced this pull request Jan 27, 2026
Rollup of 6 pull requests
Successful merges:
- rust-lang/rust#150436 (`c_variadic`: impl `va_copy` and `va_end` as Rust intrinsics)
- rust-lang/rust#151340 (Port `#[patchable_function_entry]` to attr parser)
- rust-lang/rust#151351 (Deduplicate diagnostics for const trait supertraits)
- rust-lang/rust#151424 (missing colon after the compile-flags directive)
- rust-lang/rust#151428 (Port variance attrs to attr parser.)
- rust-lang/rust#151429 (s390x: Support aligned stack datalayout)
Failed merges:
- rust-lang/rust#151343 (Port some crate level attrs to the attribute parser)
r? @ghost
bjorn3 pushed a commit to bjorn3/rust that referenced this pull request Feb 18, 2026
…fJung
`c_variadic`: impl `va_copy` and `va_end` as Rust intrinsics
tracking issue: rust-lang#44930
Implement `va_copy` as (the rust equivalent of) `memcpy`, which is the behavior of all current LLVM targets. By providing our own implementation, we can guarantee its behavior. These guarantees are important for implementing c-variadics in e.g. const-eval.
Discussed in [#t-compiler/const-eval > c-variadics in const-eval](https://rust-lang.zulipchat.com/#narrow/channel/146212-t-compiler.2Fconst-eval/topic/c-variadics.20in.20const-eval/with/565509704).
I've also updated the comment for `Drop` a bit. The background here is that the C standard requires that `va_end` is used in the same function (and really, in the same scope) as the corresponding `va_start` or `va_copy`. That is because historically `va_start` would start a scope, which `va_end` would then close. e.g.
https://softwarepreservation.computerhistory.org/c_plus_plus/cfront/release_3.0.3/source/incl-master/proto-headers/stdarg.sol
```c
#define va_start(ap, parmN) {\
va_buf _va;\
_vastart(ap = (va_list)_va, (char *)&parmN + sizeof parmN)
#define va_end(ap) }
#define va_arg(ap, mode) *((mode *)_vaarg(ap, sizeof (mode)))
```
The C standard still has to consider such implementations, but for Rust they are irrelevant. Hence we can use `Clone` for `va_copy` and `Drop` for `va_end`.
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Jul 31, 2026
…comments, r=folkertdev
Remove outdated comments from `va_list.rs`
Since rust-lang#150436 codegen backends haven't needed to implement `va_copy` or `va_end` as they are implemented using intrinsic fallback bodies, so the comments on the `#[inline]` annotations are no longer relevant. I've left the `#[inline]` annotations themselves as they seem worthwhile since `va_copy` and `va_end` are a memcpy and a no-op respectively.
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Jul 31, 2026
…comments, r=folkertdev
Remove outdated comments from `va_list.rs`
Since rust-lang#150436 codegen backends haven't needed to implement `va_copy` or `va_end` as they are implemented using intrinsic fallback bodies, so the comments on the `#[inline]` annotations are no longer relevant. I've left the `#[inline]` annotations themselves as they seem worthwhile since `va_copy` and `va_end` are a memcpy and a no-op respectively.
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Jul 31, 2026
…comments, r=folkertdev
Remove outdated comments from `va_list.rs`
Since rust-lang#150436 codegen backends haven't needed to implement `va_copy` or `va_end` as they are implemented using intrinsic fallback bodies, so the comments on the `#[inline]` annotations are no longer relevant. I've left the `#[inline]` annotations themselves as they seem worthwhile since `va_copy` and `va_end` are a memcpy and a no-op respectively.
rust-timer added a commit that referenced this pull request Jul 31, 2026
Rollup merge of #160157 - beetrees:va-list-outdated-backend-comments, r=folkertdev
Remove outdated comments from `va_list.rs`
Since #150436 codegen backends haven't needed to implement `va_copy` or `va_end` as they are implemented using intrinsic fallback bodies, so the comments on the `#[inline]` annotations are no longer relevant. I've left the `#[inline]` annotations themselves as they seem worthwhile since `va_copy` and `va_end` are a memcpy and a no-op respectively.
github-actionsBot pushed a commit to rust-lang/rustc-dev-guide that referenced this pull request Aug 3, 2026
… r=folkertdev
Remove outdated comments from `va_list.rs`
Since rust-lang/rust#150436 codegen backends haven't needed to implement `va_copy` or `va_end` as they are implemented using intrinsic fallback bodies, so the comments on the `#[inline]` annotations are no longer relevant. I've left the `#[inline]` annotations themselves as they seem worthwhile since `va_copy` and `va_end` are a memcpy and a no-op respectively.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.F-c_variadic`#![feature(c_variadic)]`S-waiting-on-borsStatus: Waiting on bors to run and complete tests. Bors will change the label on completion.T-libsRelevant to the library team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@folkertdev@rust-log-analyzer@rustbot@RalfJung@workingjubilee
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

c_variadic: impl va_copy and va_end as Rust intrinsics - #150436

Merged
rust-bors[bot] merged 2 commits into
rust-lang:mainfrom
folkertdev:va-list-copy
Jan 21, 2026
Merged

c_variadic: impl va_copy and va_end as Rust intrinsics#150436
rust-bors[bot] merged 2 commits into
rust-lang:mainfrom
folkertdev:va-list-copy

Conversation

@folkertdev

@folkertdevfolkertdev commented Dec 27, 2025

Copy link
Copy Markdown
Contributor

tracking issue: #44930

Implement va_copy as (the rust equivalent of) memcpy, which is the behavior of all current LLVM targets. By providing our own implementation, we can guarantee its behavior. These guarantees are important for implementing c-variadics in e.g. const-eval.

Discussed in #t-compiler/const-eval > c-variadics in const-eval.

I've also updated the comment for Drop a bit. The background here is that the C standard requires that va_end is used in the same function (and really, in the same scope) as the corresponding va_start or va_copy. That is because historically va_start would start a scope, which va_end would then close. e.g.

https://softwarepreservation.computerhistory.org/c_plus_plus/cfront/release_3.0.3/source/incl-master/proto-headers/stdarg.sol

#defineva_start(ap, parmN) {\
va_buf _va;\
_vastart(ap = (va_list)_va, (char *)&parmN + sizeof parmN)
#defineva_end(ap) }
#defineva_arg(ap, mode) *((mode *)_vaarg(ap, sizeof (mode)))

The C standard still has to consider such implementations, but for Rust they are irrelevant. Hence we can use Clone for va_copy and Drop for va_end.

@rustbotrustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Dec 27, 2025
Comment on lines 158 to 163
/// Basic implementation of a `va_list`.
#[repr(transparent)]
#[derive(Debug)]
#[derive(Debug, Clone, Copy)]
struct VaListInner {
ptr: *const c_void,
}

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

/// https://github.com/llvm/llvm-project/blob/0cdc1b6dd4a870fc41d4b15ad97e0001882aba58/clang/lib/CodeGen/Targets/Hexagon.cpp#L407-L417
#[repr(C)]
#[derive(Debug)]
#[derive(Debug, Clone, Copy)]

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

/// https://github.com/llvm/llvm-project/blob/af9a4263a1a209953a1d339ef781a954e31268ff/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp#L1211-L1215
#[repr(C)]
#[derive(Debug)]
#[derive(Debug, Clone, Copy)]

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

/// https://docs.google.com/gview?embedded=true&url=https://github.com/IBM/s390x-abi/releases/download/v1.7/lzsabi_s390x.pdf
#[repr(C)]
#[derive(Debug)]
#[derive(Debug, Clone, Copy)]

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

/// [GCC header]: https://web.mit.edu/darwin/src/modules/gcc/gcc/ginclude/va-ppc.h
#[repr(C)]
#[derive(Debug)]
#[derive(Debug, Clone, Copy)]

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Comment threadlibrary/core/src/ffi/va_list.rs
@folkertdevfolkertdev added the F-c_variadic `#![feature(c_variadic)]` label Dec 27, 2025
@rust-log-analyzer

This comment has been minimized.

@folkertdev
folkertdevforce-pushed the va-list-copy branch 3 times, most recently from 7a78640 to 8e09112CompareJanuary 2, 2026 21:02
@rustbotrustbot added the A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. label Jan 2, 2026
@folkertdev

Copy link
Copy Markdown
ContributorAuthor

r? @workingjubilee

The codegen of VaList::clone is target-specific now, and because minicore does not define VaList it is hard to test. I think it's fine to just test the behavior, and have LLVM use a memcpy when VaList is a struct, or just re-use the pointer value if it's just a pointer.

@folkertdev
folkertdev marked this pull request as ready for review January 2, 2026 21:04
@rustbot

Copy link
Copy Markdown
Collaborator

workingjubilee is currently at their maximum review capacity.
They may take a while to respond.

@rustbotrustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jan 2, 2026
@rustbot

Copy link
Copy Markdown
Collaborator

Some changes occurred in compiler/rustc_codegen_cranelift

cc @bjorn3

Some changes occurred to the intrinsics. Make sure the CTFE / Miri interpreter
gets adapted for the changes, if necessary.

cc @rust-lang/miri, @RalfJung, @oli-obk, @lcnr

Some changes occurred in compiler/rustc_codegen_gcc

cc @antoyo, @GuillaumeGomez

@rustbotrustbot removed the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Jan 2, 2026
@RalfJung

Copy link
Copy Markdown
Member

Implement va_copy as (the rust equivalent of) memcpy, which is the behavior of all current LLVM targets. By providing our own implementation, we can guarantee its behavior.

Didn't we say we would avoid that assumption and also support implementations that do malloc/free in va_copy / va_end? See #t-compiler/const-eval > c-variadics in const-eval @ 💬.

@folkertdev

Copy link
Copy Markdown
ContributorAuthor

That's right, we don't actually impl Copy for VaList, so that a future target could implement a meaningful Clone and Drop. It's just that in practice for all current targets Clone happens to be a memcpy and Drop a no-op

@workingjubileeworkingjubilee left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Offering a suggested historical note.

Please feel free to trim it or move it into the PR description itself, down to the amounts you find worthwhile or just amusing to keep (including 0 lines).

r=me after

Thanks!

View changes since this review

Comment threadlibrary/core/src/ffi/va_list.rs
@workingjubileeworkingjubilee added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jan 6, 2026
@RalfJung

Copy link
Copy Markdown
Member

@folkertdev what is your plan for va_copy regarding the const-eval support for this?
ISTM that without the intrinsic, it'll not be possible to catch a bunch of the UB that we had planned to catch?

Comment threadlibrary/core/src/intrinsics/mod.rs
@folkertdevfolkertdev changed the title c_variadic: use Clone instead of va_copyc_variadic: use Clone instead of LLVM va_copyJan 7, 2026
@rustbot

This comment has been minimized.

@folkertdev

Copy link
Copy Markdown
ContributorAuthor

Based on further discussion in #t-compiler/const-eval > c-variadics in const-eval, a slight change of plans

  • we still no longer call LLVM's va_copy
  • we do still have our own va_copy intrinsic that serves as a hook for const evaluation
  • va_copy has a fallback body, code generation backends should not provide their own implementation

I've changed the signature of the intrinsic to be more ergonomic, and made it safe because while the hook is used to detect UB, the intrinsic itself is completely safe.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rustbotrustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jan 19, 2026
@rust-log-analyzer

This comment has been minimized.

Comment threadlibrary/core/src/ffi/va_list.rs Outdated
///
/// See the [LLVM source] and [GCC header] for more details.
///
/// `va_copy` is `memcpy`: <https://github.com/llvm/llvm-project/blob/5aee01a3df011e660f26660bc30a8c94a1651d8e/llvm/lib/Target/PowerPC/PPCISelLowering.h#L713>

@RalfJungRalfJungJan 19, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is also just a header, not the implementation? (same for some of the other ones)

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Ah now I understand what happened: i copied these links from a github search result page. I manually looked them all up now, so all links should be correct.

@folkertdev
folkertdevforce-pushed the va-list-copy branch 2 times, most recently from 94ce7b4 to 6011fa6CompareJanuary 19, 2026 20:55
@RalfJung

Copy link
Copy Markdown
Member

Sounds great, thanks! r=workingjubilee,RalfJung with the last commit squashed away.

@bors delegate+

@rust-bors

rust-borsBot commented Jan 20, 2026

Copy link
Copy Markdown
Contributor

✌️ @folkertdev, you can now approve this pull request!

If @RalfJung told you to "r=me" after making some further change, then please make that change and post @bors r=RalfJung.

@folkertdev

Copy link
Copy Markdown
ContributorAuthor

@bors r=workingjubilee,RalfJung

@rust-bors

rust-borsBot commented Jan 20, 2026

Copy link
Copy Markdown
Contributor

📌 Commit 922057c has been approved by workingjubilee,RalfJung

It is now in the queue for this repository.

@rust-borsrust-borsBot added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jan 20, 2026
@jhprattjhpratt mentioned this pull request Jan 21, 2026
rust-borsBot pushed a commit that referenced this pull request Jan 21, 2026
Rollup of 6 pull requests
Successful merges:
- #150436 (`c_variadic`: impl `va_copy` and `va_end` as Rust intrinsics)
- #151340 (Port `#[patchable_function_entry]` to attr parser)
- #151351 (Deduplicate diagnostics for const trait supertraits)
- #151424 (missing colon after the compile-flags directive)
- #151428 (Port variance attrs to attr parser.)
- #151429 (s390x: Support aligned stack datalayout)
Failed merges:
- #151343 (Port some crate level attrs to the attribute parser)
r? @ghost
@rust-bors
rust-borsBot merged commit 43d2006 into rust-lang:mainJan 21, 2026
11 checks passed
@rustbotrustbot added this to the 1.95.0 milestone Jan 21, 2026
rust-timer added a commit that referenced this pull request Jan 21, 2026
Rollup merge of #150436 - va-list-copy, r=workingjubilee,RalfJung
`c_variadic`: impl `va_copy` and `va_end` as Rust intrinsics
tracking issue: #44930
Implement `va_copy` as (the rust equivalent of) `memcpy`, which is the behavior of all current LLVM targets. By providing our own implementation, we can guarantee its behavior. These guarantees are important for implementing c-variadics in e.g. const-eval.
Discussed in [#t-compiler/const-eval > c-variadics in const-eval](https://rust-lang.zulipchat.com/#narrow/channel/146212-t-compiler.2Fconst-eval/topic/c-variadics.20in.20const-eval/with/565509704).
I've also updated the comment for `Drop` a bit. The background here is that the C standard requires that `va_end` is used in the same function (and really, in the same scope) as the corresponding `va_start` or `va_copy`. That is because historically `va_start` would start a scope, which `va_end` would then close. e.g.
https://softwarepreservation.computerhistory.org/c_plus_plus/cfront/release_3.0.3/source/incl-master/proto-headers/stdarg.sol
```c
#define va_start(ap, parmN) {\
va_buf _va;\
_vastart(ap = (va_list)_va, (char *)&parmN + sizeof parmN)
#define va_end(ap) }
#define va_arg(ap, mode) *((mode *)_vaarg(ap, sizeof (mode)))
```
The C standard still has to consider such implementations, but for Rust they are irrelevant. Hence we can use `Clone` for `va_copy` and `Drop` for `va_end`.
christian-schilling pushed a commit to christian-schilling/rustc_codegen_cranelift that referenced this pull request Jan 27, 2026
Rollup of 6 pull requests
Successful merges:
- rust-lang/rust#150436 (`c_variadic`: impl `va_copy` and `va_end` as Rust intrinsics)
- rust-lang/rust#151340 (Port `#[patchable_function_entry]` to attr parser)
- rust-lang/rust#151351 (Deduplicate diagnostics for const trait supertraits)
- rust-lang/rust#151424 (missing colon after the compile-flags directive)
- rust-lang/rust#151428 (Port variance attrs to attr parser.)
- rust-lang/rust#151429 (s390x: Support aligned stack datalayout)
Failed merges:
- rust-lang/rust#151343 (Port some crate level attrs to the attribute parser)
r? @ghost
christian-schilling pushed a commit to christian-schilling/rustc_codegen_cranelift that referenced this pull request Jan 27, 2026
Rollup of 6 pull requests
Successful merges:
- rust-lang/rust#150436 (`c_variadic`: impl `va_copy` and `va_end` as Rust intrinsics)
- rust-lang/rust#151340 (Port `#[patchable_function_entry]` to attr parser)
- rust-lang/rust#151351 (Deduplicate diagnostics for const trait supertraits)
- rust-lang/rust#151424 (missing colon after the compile-flags directive)
- rust-lang/rust#151428 (Port variance attrs to attr parser.)
- rust-lang/rust#151429 (s390x: Support aligned stack datalayout)
Failed merges:
- rust-lang/rust#151343 (Port some crate level attrs to the attribute parser)
r? @ghost
bjorn3 pushed a commit to bjorn3/rust that referenced this pull request Feb 18, 2026
…fJung
`c_variadic`: impl `va_copy` and `va_end` as Rust intrinsics
tracking issue: rust-lang#44930
Implement `va_copy` as (the rust equivalent of) `memcpy`, which is the behavior of all current LLVM targets. By providing our own implementation, we can guarantee its behavior. These guarantees are important for implementing c-variadics in e.g. const-eval.
Discussed in [#t-compiler/const-eval > c-variadics in const-eval](https://rust-lang.zulipchat.com/#narrow/channel/146212-t-compiler.2Fconst-eval/topic/c-variadics.20in.20const-eval/with/565509704).
I've also updated the comment for `Drop` a bit. The background here is that the C standard requires that `va_end` is used in the same function (and really, in the same scope) as the corresponding `va_start` or `va_copy`. That is because historically `va_start` would start a scope, which `va_end` would then close. e.g.
https://softwarepreservation.computerhistory.org/c_plus_plus/cfront/release_3.0.3/source/incl-master/proto-headers/stdarg.sol
```c
#define va_start(ap, parmN) {\
va_buf _va;\
_vastart(ap = (va_list)_va, (char *)&parmN + sizeof parmN)
#define va_end(ap) }
#define va_arg(ap, mode) *((mode *)_vaarg(ap, sizeof (mode)))
```
The C standard still has to consider such implementations, but for Rust they are irrelevant. Hence we can use `Clone` for `va_copy` and `Drop` for `va_end`.
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Jul 31, 2026
…comments, r=folkertdev
Remove outdated comments from `va_list.rs`
Since rust-lang#150436 codegen backends haven't needed to implement `va_copy` or `va_end` as they are implemented using intrinsic fallback bodies, so the comments on the `#[inline]` annotations are no longer relevant. I've left the `#[inline]` annotations themselves as they seem worthwhile since `va_copy` and `va_end` are a memcpy and a no-op respectively.
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Jul 31, 2026
…comments, r=folkertdev
Remove outdated comments from `va_list.rs`
Since rust-lang#150436 codegen backends haven't needed to implement `va_copy` or `va_end` as they are implemented using intrinsic fallback bodies, so the comments on the `#[inline]` annotations are no longer relevant. I've left the `#[inline]` annotations themselves as they seem worthwhile since `va_copy` and `va_end` are a memcpy and a no-op respectively.
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Jul 31, 2026
…comments, r=folkertdev
Remove outdated comments from `va_list.rs`
Since rust-lang#150436 codegen backends haven't needed to implement `va_copy` or `va_end` as they are implemented using intrinsic fallback bodies, so the comments on the `#[inline]` annotations are no longer relevant. I've left the `#[inline]` annotations themselves as they seem worthwhile since `va_copy` and `va_end` are a memcpy and a no-op respectively.
rust-timer added a commit that referenced this pull request Jul 31, 2026
Rollup merge of #160157 - beetrees:va-list-outdated-backend-comments, r=folkertdev
Remove outdated comments from `va_list.rs`
Since #150436 codegen backends haven't needed to implement `va_copy` or `va_end` as they are implemented using intrinsic fallback bodies, so the comments on the `#[inline]` annotations are no longer relevant. I've left the `#[inline]` annotations themselves as they seem worthwhile since `va_copy` and `va_end` are a memcpy and a no-op respectively.
github-actionsBot pushed a commit to rust-lang/rustc-dev-guide that referenced this pull request Aug 3, 2026
… r=folkertdev
Remove outdated comments from `va_list.rs`
Since rust-lang/rust#150436 codegen backends haven't needed to implement `va_copy` or `va_end` as they are implemented using intrinsic fallback bodies, so the comments on the `#[inline]` annotations are no longer relevant. I've left the `#[inline]` annotations themselves as they seem worthwhile since `va_copy` and `va_end` are a memcpy and a no-op respectively.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.F-c_variadic`#![feature(c_variadic)]`S-waiting-on-borsStatus: Waiting on bors to run and complete tests. Bors will change the label on completion.T-libsRelevant to the library team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@folkertdev@rust-log-analyzer@rustbot@RalfJung@workingjubilee
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

c_variadic: impl va_copy and va_end as Rust intrinsics - #150436

Merged
rust-bors[bot] merged 2 commits into
rust-lang:mainfrom
folkertdev:va-list-copy
Jan 21, 2026
Merged

c_variadic: impl va_copy and va_end as Rust intrinsics#150436
rust-bors[bot] merged 2 commits into
rust-lang:mainfrom
folkertdev:va-list-copy

Conversation

@folkertdev

@folkertdevfolkertdev commented Dec 27, 2025

Copy link
Copy Markdown
Contributor

tracking issue: #44930

Implement va_copy as (the rust equivalent of) memcpy, which is the behavior of all current LLVM targets. By providing our own implementation, we can guarantee its behavior. These guarantees are important for implementing c-variadics in e.g. const-eval.

Discussed in #t-compiler/const-eval > c-variadics in const-eval.

I've also updated the comment for Drop a bit. The background here is that the C standard requires that va_end is used in the same function (and really, in the same scope) as the corresponding va_start or va_copy. That is because historically va_start would start a scope, which va_end would then close. e.g.

https://softwarepreservation.computerhistory.org/c_plus_plus/cfront/release_3.0.3/source/incl-master/proto-headers/stdarg.sol

#defineva_start(ap, parmN) {\
va_buf _va;\
_vastart(ap = (va_list)_va, (char *)&parmN + sizeof parmN)
#defineva_end(ap) }
#defineva_arg(ap, mode) *((mode *)_vaarg(ap, sizeof (mode)))

The C standard still has to consider such implementations, but for Rust they are irrelevant. Hence we can use Clone for va_copy and Drop for va_end.

@rustbotrustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Dec 27, 2025
Comment on lines 158 to 163
/// Basic implementation of a `va_list`.
#[repr(transparent)]
#[derive(Debug)]
#[derive(Debug, Clone, Copy)]
struct VaListInner {
ptr: *const c_void,
}

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

/// https://github.com/llvm/llvm-project/blob/0cdc1b6dd4a870fc41d4b15ad97e0001882aba58/clang/lib/CodeGen/Targets/Hexagon.cpp#L407-L417
#[repr(C)]
#[derive(Debug)]
#[derive(Debug, Clone, Copy)]

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

/// https://github.com/llvm/llvm-project/blob/af9a4263a1a209953a1d339ef781a954e31268ff/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp#L1211-L1215
#[repr(C)]
#[derive(Debug)]
#[derive(Debug, Clone, Copy)]

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

/// https://docs.google.com/gview?embedded=true&url=https://github.com/IBM/s390x-abi/releases/download/v1.7/lzsabi_s390x.pdf
#[repr(C)]
#[derive(Debug)]
#[derive(Debug, Clone, Copy)]

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

/// [GCC header]: https://web.mit.edu/darwin/src/modules/gcc/gcc/ginclude/va-ppc.h
#[repr(C)]
#[derive(Debug)]
#[derive(Debug, Clone, Copy)]

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Comment threadlibrary/core/src/ffi/va_list.rs
@folkertdevfolkertdev added the F-c_variadic `#![feature(c_variadic)]` label Dec 27, 2025
@rust-log-analyzer

This comment has been minimized.

@folkertdev
folkertdevforce-pushed the va-list-copy branch 3 times, most recently from 7a78640 to 8e09112CompareJanuary 2, 2026 21:02
@rustbotrustbot added the A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. label Jan 2, 2026
@folkertdev

Copy link
Copy Markdown
ContributorAuthor

r? @workingjubilee

The codegen of VaList::clone is target-specific now, and because minicore does not define VaList it is hard to test. I think it's fine to just test the behavior, and have LLVM use a memcpy when VaList is a struct, or just re-use the pointer value if it's just a pointer.

@folkertdev
folkertdev marked this pull request as ready for review January 2, 2026 21:04
@rustbot

Copy link
Copy Markdown
Collaborator

workingjubilee is currently at their maximum review capacity.
They may take a while to respond.

@rustbotrustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jan 2, 2026
@rustbot

Copy link
Copy Markdown
Collaborator

Some changes occurred in compiler/rustc_codegen_cranelift

cc @bjorn3

Some changes occurred to the intrinsics. Make sure the CTFE / Miri interpreter
gets adapted for the changes, if necessary.

cc @rust-lang/miri, @RalfJung, @oli-obk, @lcnr

Some changes occurred in compiler/rustc_codegen_gcc

cc @antoyo, @GuillaumeGomez

@rustbotrustbot removed the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Jan 2, 2026
@RalfJung

Copy link
Copy Markdown
Member

Implement va_copy as (the rust equivalent of) memcpy, which is the behavior of all current LLVM targets. By providing our own implementation, we can guarantee its behavior.

Didn't we say we would avoid that assumption and also support implementations that do malloc/free in va_copy / va_end? See #t-compiler/const-eval > c-variadics in const-eval @ 💬.

@folkertdev

Copy link
Copy Markdown
ContributorAuthor

That's right, we don't actually impl Copy for VaList, so that a future target could implement a meaningful Clone and Drop. It's just that in practice for all current targets Clone happens to be a memcpy and Drop a no-op

@workingjubileeworkingjubilee left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Offering a suggested historical note.

Please feel free to trim it or move it into the PR description itself, down to the amounts you find worthwhile or just amusing to keep (including 0 lines).

r=me after

Thanks!

View changes since this review

Comment threadlibrary/core/src/ffi/va_list.rs
@workingjubileeworkingjubilee added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jan 6, 2026
@RalfJung

Copy link
Copy Markdown
Member

@folkertdev what is your plan for va_copy regarding the const-eval support for this?
ISTM that without the intrinsic, it'll not be possible to catch a bunch of the UB that we had planned to catch?

Comment threadlibrary/core/src/intrinsics/mod.rs
@folkertdevfolkertdev changed the title c_variadic: use Clone instead of va_copyc_variadic: use Clone instead of LLVM va_copyJan 7, 2026
@rustbot

This comment has been minimized.

@folkertdev

Copy link
Copy Markdown
ContributorAuthor

Based on further discussion in #t-compiler/const-eval > c-variadics in const-eval, a slight change of plans

  • we still no longer call LLVM's va_copy
  • we do still have our own va_copy intrinsic that serves as a hook for const evaluation
  • va_copy has a fallback body, code generation backends should not provide their own implementation

I've changed the signature of the intrinsic to be more ergonomic, and made it safe because while the hook is used to detect UB, the intrinsic itself is completely safe.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rustbotrustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jan 19, 2026
@rust-log-analyzer

This comment has been minimized.

Comment threadlibrary/core/src/ffi/va_list.rs Outdated
///
/// See the [LLVM source] and [GCC header] for more details.
///
/// `va_copy` is `memcpy`: <https://github.com/llvm/llvm-project/blob/5aee01a3df011e660f26660bc30a8c94a1651d8e/llvm/lib/Target/PowerPC/PPCISelLowering.h#L713>

@RalfJungRalfJungJan 19, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is also just a header, not the implementation? (same for some of the other ones)

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Ah now I understand what happened: i copied these links from a github search result page. I manually looked them all up now, so all links should be correct.

@folkertdev
folkertdevforce-pushed the va-list-copy branch 2 times, most recently from 94ce7b4 to 6011fa6CompareJanuary 19, 2026 20:55
@RalfJung

Copy link
Copy Markdown
Member

Sounds great, thanks! r=workingjubilee,RalfJung with the last commit squashed away.

@bors delegate+

@rust-bors

rust-borsBot commented Jan 20, 2026

Copy link
Copy Markdown
Contributor

✌️ @folkertdev, you can now approve this pull request!

If @RalfJung told you to "r=me" after making some further change, then please make that change and post @bors r=RalfJung.

@folkertdev

Copy link
Copy Markdown
ContributorAuthor

@bors r=workingjubilee,RalfJung

@rust-bors

rust-borsBot commented Jan 20, 2026

Copy link
Copy Markdown
Contributor

📌 Commit 922057c has been approved by workingjubilee,RalfJung

It is now in the queue for this repository.

@rust-borsrust-borsBot added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jan 20, 2026
@jhprattjhpratt mentioned this pull request Jan 21, 2026
rust-borsBot pushed a commit that referenced this pull request Jan 21, 2026
Rollup of 6 pull requests
Successful merges:
- #150436 (`c_variadic`: impl `va_copy` and `va_end` as Rust intrinsics)
- #151340 (Port `#[patchable_function_entry]` to attr parser)
- #151351 (Deduplicate diagnostics for const trait supertraits)
- #151424 (missing colon after the compile-flags directive)
- #151428 (Port variance attrs to attr parser.)
- #151429 (s390x: Support aligned stack datalayout)
Failed merges:
- #151343 (Port some crate level attrs to the attribute parser)
r? @ghost
@rust-bors
rust-borsBot merged commit 43d2006 into rust-lang:mainJan 21, 2026
11 checks passed
@rustbotrustbot added this to the 1.95.0 milestone Jan 21, 2026
rust-timer added a commit that referenced this pull request Jan 21, 2026
Rollup merge of #150436 - va-list-copy, r=workingjubilee,RalfJung
`c_variadic`: impl `va_copy` and `va_end` as Rust intrinsics
tracking issue: #44930
Implement `va_copy` as (the rust equivalent of) `memcpy`, which is the behavior of all current LLVM targets. By providing our own implementation, we can guarantee its behavior. These guarantees are important for implementing c-variadics in e.g. const-eval.
Discussed in [#t-compiler/const-eval > c-variadics in const-eval](https://rust-lang.zulipchat.com/#narrow/channel/146212-t-compiler.2Fconst-eval/topic/c-variadics.20in.20const-eval/with/565509704).
I've also updated the comment for `Drop` a bit. The background here is that the C standard requires that `va_end` is used in the same function (and really, in the same scope) as the corresponding `va_start` or `va_copy`. That is because historically `va_start` would start a scope, which `va_end` would then close. e.g.
https://softwarepreservation.computerhistory.org/c_plus_plus/cfront/release_3.0.3/source/incl-master/proto-headers/stdarg.sol
```c
#define va_start(ap, parmN) {\
va_buf _va;\
_vastart(ap = (va_list)_va, (char *)&parmN + sizeof parmN)
#define va_end(ap) }
#define va_arg(ap, mode) *((mode *)_vaarg(ap, sizeof (mode)))
```
The C standard still has to consider such implementations, but for Rust they are irrelevant. Hence we can use `Clone` for `va_copy` and `Drop` for `va_end`.
christian-schilling pushed a commit to christian-schilling/rustc_codegen_cranelift that referenced this pull request Jan 27, 2026
Rollup of 6 pull requests
Successful merges:
- rust-lang/rust#150436 (`c_variadic`: impl `va_copy` and `va_end` as Rust intrinsics)
- rust-lang/rust#151340 (Port `#[patchable_function_entry]` to attr parser)
- rust-lang/rust#151351 (Deduplicate diagnostics for const trait supertraits)
- rust-lang/rust#151424 (missing colon after the compile-flags directive)
- rust-lang/rust#151428 (Port variance attrs to attr parser.)
- rust-lang/rust#151429 (s390x: Support aligned stack datalayout)
Failed merges:
- rust-lang/rust#151343 (Port some crate level attrs to the attribute parser)
r? @ghost
christian-schilling pushed a commit to christian-schilling/rustc_codegen_cranelift that referenced this pull request Jan 27, 2026
Rollup of 6 pull requests
Successful merges:
- rust-lang/rust#150436 (`c_variadic`: impl `va_copy` and `va_end` as Rust intrinsics)
- rust-lang/rust#151340 (Port `#[patchable_function_entry]` to attr parser)
- rust-lang/rust#151351 (Deduplicate diagnostics for const trait supertraits)
- rust-lang/rust#151424 (missing colon after the compile-flags directive)
- rust-lang/rust#151428 (Port variance attrs to attr parser.)
- rust-lang/rust#151429 (s390x: Support aligned stack datalayout)
Failed merges:
- rust-lang/rust#151343 (Port some crate level attrs to the attribute parser)
r? @ghost
bjorn3 pushed a commit to bjorn3/rust that referenced this pull request Feb 18, 2026
…fJung
`c_variadic`: impl `va_copy` and `va_end` as Rust intrinsics
tracking issue: rust-lang#44930
Implement `va_copy` as (the rust equivalent of) `memcpy`, which is the behavior of all current LLVM targets. By providing our own implementation, we can guarantee its behavior. These guarantees are important for implementing c-variadics in e.g. const-eval.
Discussed in [#t-compiler/const-eval > c-variadics in const-eval](https://rust-lang.zulipchat.com/#narrow/channel/146212-t-compiler.2Fconst-eval/topic/c-variadics.20in.20const-eval/with/565509704).
I've also updated the comment for `Drop` a bit. The background here is that the C standard requires that `va_end` is used in the same function (and really, in the same scope) as the corresponding `va_start` or `va_copy`. That is because historically `va_start` would start a scope, which `va_end` would then close. e.g.
https://softwarepreservation.computerhistory.org/c_plus_plus/cfront/release_3.0.3/source/incl-master/proto-headers/stdarg.sol
```c
#define va_start(ap, parmN) {\
va_buf _va;\
_vastart(ap = (va_list)_va, (char *)&parmN + sizeof parmN)
#define va_end(ap) }
#define va_arg(ap, mode) *((mode *)_vaarg(ap, sizeof (mode)))
```
The C standard still has to consider such implementations, but for Rust they are irrelevant. Hence we can use `Clone` for `va_copy` and `Drop` for `va_end`.
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Jul 31, 2026
…comments, r=folkertdev
Remove outdated comments from `va_list.rs`
Since rust-lang#150436 codegen backends haven't needed to implement `va_copy` or `va_end` as they are implemented using intrinsic fallback bodies, so the comments on the `#[inline]` annotations are no longer relevant. I've left the `#[inline]` annotations themselves as they seem worthwhile since `va_copy` and `va_end` are a memcpy and a no-op respectively.
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Jul 31, 2026
…comments, r=folkertdev
Remove outdated comments from `va_list.rs`
Since rust-lang#150436 codegen backends haven't needed to implement `va_copy` or `va_end` as they are implemented using intrinsic fallback bodies, so the comments on the `#[inline]` annotations are no longer relevant. I've left the `#[inline]` annotations themselves as they seem worthwhile since `va_copy` and `va_end` are a memcpy and a no-op respectively.
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Jul 31, 2026
…comments, r=folkertdev
Remove outdated comments from `va_list.rs`
Since rust-lang#150436 codegen backends haven't needed to implement `va_copy` or `va_end` as they are implemented using intrinsic fallback bodies, so the comments on the `#[inline]` annotations are no longer relevant. I've left the `#[inline]` annotations themselves as they seem worthwhile since `va_copy` and `va_end` are a memcpy and a no-op respectively.
rust-timer added a commit that referenced this pull request Jul 31, 2026
Rollup merge of #160157 - beetrees:va-list-outdated-backend-comments, r=folkertdev
Remove outdated comments from `va_list.rs`
Since #150436 codegen backends haven't needed to implement `va_copy` or `va_end` as they are implemented using intrinsic fallback bodies, so the comments on the `#[inline]` annotations are no longer relevant. I've left the `#[inline]` annotations themselves as they seem worthwhile since `va_copy` and `va_end` are a memcpy and a no-op respectively.
github-actionsBot pushed a commit to rust-lang/rustc-dev-guide that referenced this pull request Aug 3, 2026
… r=folkertdev
Remove outdated comments from `va_list.rs`
Since rust-lang/rust#150436 codegen backends haven't needed to implement `va_copy` or `va_end` as they are implemented using intrinsic fallback bodies, so the comments on the `#[inline]` annotations are no longer relevant. I've left the `#[inline]` annotations themselves as they seem worthwhile since `va_copy` and `va_end` are a memcpy and a no-op respectively.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.F-c_variadic`#![feature(c_variadic)]`S-waiting-on-borsStatus: Waiting on bors to run and complete tests. Bors will change the label on completion.T-libsRelevant to the library team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@folkertdev@rust-log-analyzer@rustbot@RalfJung@workingjubilee
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

c_variadic: impl va_copy and va_end as Rust intrinsics - #150436

Merged
rust-bors[bot] merged 2 commits into
rust-lang:mainfrom
folkertdev:va-list-copy
Jan 21, 2026
Merged

c_variadic: impl va_copy and va_end as Rust intrinsics#150436
rust-bors[bot] merged 2 commits into
rust-lang:mainfrom
folkertdev:va-list-copy

Conversation

@folkertdev

@folkertdevfolkertdev commented Dec 27, 2025

Copy link
Copy Markdown
Contributor

tracking issue: #44930

Implement va_copy as (the rust equivalent of) memcpy, which is the behavior of all current LLVM targets. By providing our own implementation, we can guarantee its behavior. These guarantees are important for implementing c-variadics in e.g. const-eval.

Discussed in #t-compiler/const-eval > c-variadics in const-eval.

I've also updated the comment for Drop a bit. The background here is that the C standard requires that va_end is used in the same function (and really, in the same scope) as the corresponding va_start or va_copy. That is because historically va_start would start a scope, which va_end would then close. e.g.

https://softwarepreservation.computerhistory.org/c_plus_plus/cfront/release_3.0.3/source/incl-master/proto-headers/stdarg.sol

#defineva_start(ap, parmN) {\
va_buf _va;\
_vastart(ap = (va_list)_va, (char *)&parmN + sizeof parmN)
#defineva_end(ap) }
#defineva_arg(ap, mode) *((mode *)_vaarg(ap, sizeof (mode)))

The C standard still has to consider such implementations, but for Rust they are irrelevant. Hence we can use Clone for va_copy and Drop for va_end.

@rustbotrustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Dec 27, 2025
Comment on lines 158 to 163
/// Basic implementation of a `va_list`.
#[repr(transparent)]
#[derive(Debug)]
#[derive(Debug, Clone, Copy)]
struct VaListInner {
ptr: *const c_void,
}

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

/// https://github.com/llvm/llvm-project/blob/0cdc1b6dd4a870fc41d4b15ad97e0001882aba58/clang/lib/CodeGen/Targets/Hexagon.cpp#L407-L417
#[repr(C)]
#[derive(Debug)]
#[derive(Debug, Clone, Copy)]

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

/// https://github.com/llvm/llvm-project/blob/af9a4263a1a209953a1d339ef781a954e31268ff/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp#L1211-L1215
#[repr(C)]
#[derive(Debug)]
#[derive(Debug, Clone, Copy)]

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

/// https://docs.google.com/gview?embedded=true&url=https://github.com/IBM/s390x-abi/releases/download/v1.7/lzsabi_s390x.pdf
#[repr(C)]
#[derive(Debug)]
#[derive(Debug, Clone, Copy)]

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

/// [GCC header]: https://web.mit.edu/darwin/src/modules/gcc/gcc/ginclude/va-ppc.h
#[repr(C)]
#[derive(Debug)]
#[derive(Debug, Clone, Copy)]

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Comment threadlibrary/core/src/ffi/va_list.rs
@folkertdevfolkertdev added the F-c_variadic `#![feature(c_variadic)]` label Dec 27, 2025
@rust-log-analyzer

This comment has been minimized.

@folkertdev
folkertdevforce-pushed the va-list-copy branch 3 times, most recently from 7a78640 to 8e09112CompareJanuary 2, 2026 21:02
@rustbotrustbot added the A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. label Jan 2, 2026
@folkertdev

Copy link
Copy Markdown
ContributorAuthor

r? @workingjubilee

The codegen of VaList::clone is target-specific now, and because minicore does not define VaList it is hard to test. I think it's fine to just test the behavior, and have LLVM use a memcpy when VaList is a struct, or just re-use the pointer value if it's just a pointer.

@folkertdev
folkertdev marked this pull request as ready for review January 2, 2026 21:04
@rustbot

Copy link
Copy Markdown
Collaborator

workingjubilee is currently at their maximum review capacity.
They may take a while to respond.

@rustbotrustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jan 2, 2026
@rustbot

Copy link
Copy Markdown
Collaborator

Some changes occurred in compiler/rustc_codegen_cranelift

cc @bjorn3

Some changes occurred to the intrinsics. Make sure the CTFE / Miri interpreter
gets adapted for the changes, if necessary.

cc @rust-lang/miri, @RalfJung, @oli-obk, @lcnr

Some changes occurred in compiler/rustc_codegen_gcc

cc @antoyo, @GuillaumeGomez

@rustbotrustbot removed the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Jan 2, 2026
@RalfJung

Copy link
Copy Markdown
Member

Implement va_copy as (the rust equivalent of) memcpy, which is the behavior of all current LLVM targets. By providing our own implementation, we can guarantee its behavior.

Didn't we say we would avoid that assumption and also support implementations that do malloc/free in va_copy / va_end? See #t-compiler/const-eval > c-variadics in const-eval @ 💬.

@folkertdev

Copy link
Copy Markdown
ContributorAuthor

That's right, we don't actually impl Copy for VaList, so that a future target could implement a meaningful Clone and Drop. It's just that in practice for all current targets Clone happens to be a memcpy and Drop a no-op

@workingjubileeworkingjubilee left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Offering a suggested historical note.

Please feel free to trim it or move it into the PR description itself, down to the amounts you find worthwhile or just amusing to keep (including 0 lines).

r=me after

Thanks!

View changes since this review

Comment threadlibrary/core/src/ffi/va_list.rs
@workingjubileeworkingjubilee added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jan 6, 2026
@RalfJung

Copy link
Copy Markdown
Member

@folkertdev what is your plan for va_copy regarding the const-eval support for this?
ISTM that without the intrinsic, it'll not be possible to catch a bunch of the UB that we had planned to catch?

Comment threadlibrary/core/src/intrinsics/mod.rs
@folkertdevfolkertdev changed the title c_variadic: use Clone instead of va_copyc_variadic: use Clone instead of LLVM va_copyJan 7, 2026
@rustbot

This comment has been minimized.

@folkertdev

Copy link
Copy Markdown
ContributorAuthor

Based on further discussion in #t-compiler/const-eval > c-variadics in const-eval, a slight change of plans

  • we still no longer call LLVM's va_copy
  • we do still have our own va_copy intrinsic that serves as a hook for const evaluation
  • va_copy has a fallback body, code generation backends should not provide their own implementation

I've changed the signature of the intrinsic to be more ergonomic, and made it safe because while the hook is used to detect UB, the intrinsic itself is completely safe.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rustbotrustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jan 19, 2026
@rust-log-analyzer

This comment has been minimized.

Comment threadlibrary/core/src/ffi/va_list.rs Outdated
///
/// See the [LLVM source] and [GCC header] for more details.
///
/// `va_copy` is `memcpy`: <https://github.com/llvm/llvm-project/blob/5aee01a3df011e660f26660bc30a8c94a1651d8e/llvm/lib/Target/PowerPC/PPCISelLowering.h#L713>

@RalfJungRalfJungJan 19, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is also just a header, not the implementation? (same for some of the other ones)

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Ah now I understand what happened: i copied these links from a github search result page. I manually looked them all up now, so all links should be correct.

@folkertdev
folkertdevforce-pushed the va-list-copy branch 2 times, most recently from 94ce7b4 to 6011fa6CompareJanuary 19, 2026 20:55
@RalfJung

Copy link
Copy Markdown
Member

Sounds great, thanks! r=workingjubilee,RalfJung with the last commit squashed away.

@bors delegate+

@rust-bors

rust-borsBot commented Jan 20, 2026

Copy link
Copy Markdown
Contributor

✌️ @folkertdev, you can now approve this pull request!

If @RalfJung told you to "r=me" after making some further change, then please make that change and post @bors r=RalfJung.

@folkertdev

Copy link
Copy Markdown
ContributorAuthor

@bors r=workingjubilee,RalfJung

@rust-bors

rust-borsBot commented Jan 20, 2026

Copy link
Copy Markdown
Contributor

📌 Commit 922057c has been approved by workingjubilee,RalfJung

It is now in the queue for this repository.

@rust-borsrust-borsBot added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jan 20, 2026
@jhprattjhpratt mentioned this pull request Jan 21, 2026
rust-borsBot pushed a commit that referenced this pull request Jan 21, 2026
Rollup of 6 pull requests
Successful merges:
- #150436 (`c_variadic`: impl `va_copy` and `va_end` as Rust intrinsics)
- #151340 (Port `#[patchable_function_entry]` to attr parser)
- #151351 (Deduplicate diagnostics for const trait supertraits)
- #151424 (missing colon after the compile-flags directive)
- #151428 (Port variance attrs to attr parser.)
- #151429 (s390x: Support aligned stack datalayout)
Failed merges:
- #151343 (Port some crate level attrs to the attribute parser)
r? @ghost
@rust-bors
rust-borsBot merged commit 43d2006 into rust-lang:mainJan 21, 2026
11 checks passed
@rustbotrustbot added this to the 1.95.0 milestone Jan 21, 2026
rust-timer added a commit that referenced this pull request Jan 21, 2026
Rollup merge of #150436 - va-list-copy, r=workingjubilee,RalfJung
`c_variadic`: impl `va_copy` and `va_end` as Rust intrinsics
tracking issue: #44930
Implement `va_copy` as (the rust equivalent of) `memcpy`, which is the behavior of all current LLVM targets. By providing our own implementation, we can guarantee its behavior. These guarantees are important for implementing c-variadics in e.g. const-eval.
Discussed in [#t-compiler/const-eval > c-variadics in const-eval](https://rust-lang.zulipchat.com/#narrow/channel/146212-t-compiler.2Fconst-eval/topic/c-variadics.20in.20const-eval/with/565509704).
I've also updated the comment for `Drop` a bit. The background here is that the C standard requires that `va_end` is used in the same function (and really, in the same scope) as the corresponding `va_start` or `va_copy`. That is because historically `va_start` would start a scope, which `va_end` would then close. e.g.
https://softwarepreservation.computerhistory.org/c_plus_plus/cfront/release_3.0.3/source/incl-master/proto-headers/stdarg.sol
```c
#define va_start(ap, parmN) {\
va_buf _va;\
_vastart(ap = (va_list)_va, (char *)&parmN + sizeof parmN)
#define va_end(ap) }
#define va_arg(ap, mode) *((mode *)_vaarg(ap, sizeof (mode)))
```
The C standard still has to consider such implementations, but for Rust they are irrelevant. Hence we can use `Clone` for `va_copy` and `Drop` for `va_end`.
christian-schilling pushed a commit to christian-schilling/rustc_codegen_cranelift that referenced this pull request Jan 27, 2026
Rollup of 6 pull requests
Successful merges:
- rust-lang/rust#150436 (`c_variadic`: impl `va_copy` and `va_end` as Rust intrinsics)
- rust-lang/rust#151340 (Port `#[patchable_function_entry]` to attr parser)
- rust-lang/rust#151351 (Deduplicate diagnostics for const trait supertraits)
- rust-lang/rust#151424 (missing colon after the compile-flags directive)
- rust-lang/rust#151428 (Port variance attrs to attr parser.)
- rust-lang/rust#151429 (s390x: Support aligned stack datalayout)
Failed merges:
- rust-lang/rust#151343 (Port some crate level attrs to the attribute parser)
r? @ghost
christian-schilling pushed a commit to christian-schilling/rustc_codegen_cranelift that referenced this pull request Jan 27, 2026
Rollup of 6 pull requests
Successful merges:
- rust-lang/rust#150436 (`c_variadic`: impl `va_copy` and `va_end` as Rust intrinsics)
- rust-lang/rust#151340 (Port `#[patchable_function_entry]` to attr parser)
- rust-lang/rust#151351 (Deduplicate diagnostics for const trait supertraits)
- rust-lang/rust#151424 (missing colon after the compile-flags directive)
- rust-lang/rust#151428 (Port variance attrs to attr parser.)
- rust-lang/rust#151429 (s390x: Support aligned stack datalayout)
Failed merges:
- rust-lang/rust#151343 (Port some crate level attrs to the attribute parser)
r? @ghost
bjorn3 pushed a commit to bjorn3/rust that referenced this pull request Feb 18, 2026
…fJung
`c_variadic`: impl `va_copy` and `va_end` as Rust intrinsics
tracking issue: rust-lang#44930
Implement `va_copy` as (the rust equivalent of) `memcpy`, which is the behavior of all current LLVM targets. By providing our own implementation, we can guarantee its behavior. These guarantees are important for implementing c-variadics in e.g. const-eval.
Discussed in [#t-compiler/const-eval > c-variadics in const-eval](https://rust-lang.zulipchat.com/#narrow/channel/146212-t-compiler.2Fconst-eval/topic/c-variadics.20in.20const-eval/with/565509704).
I've also updated the comment for `Drop` a bit. The background here is that the C standard requires that `va_end` is used in the same function (and really, in the same scope) as the corresponding `va_start` or `va_copy`. That is because historically `va_start` would start a scope, which `va_end` would then close. e.g.
https://softwarepreservation.computerhistory.org/c_plus_plus/cfront/release_3.0.3/source/incl-master/proto-headers/stdarg.sol
```c
#define va_start(ap, parmN) {\
va_buf _va;\
_vastart(ap = (va_list)_va, (char *)&parmN + sizeof parmN)
#define va_end(ap) }
#define va_arg(ap, mode) *((mode *)_vaarg(ap, sizeof (mode)))
```
The C standard still has to consider such implementations, but for Rust they are irrelevant. Hence we can use `Clone` for `va_copy` and `Drop` for `va_end`.
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Jul 31, 2026
…comments, r=folkertdev
Remove outdated comments from `va_list.rs`
Since rust-lang#150436 codegen backends haven't needed to implement `va_copy` or `va_end` as they are implemented using intrinsic fallback bodies, so the comments on the `#[inline]` annotations are no longer relevant. I've left the `#[inline]` annotations themselves as they seem worthwhile since `va_copy` and `va_end` are a memcpy and a no-op respectively.
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Jul 31, 2026
…comments, r=folkertdev
Remove outdated comments from `va_list.rs`
Since rust-lang#150436 codegen backends haven't needed to implement `va_copy` or `va_end` as they are implemented using intrinsic fallback bodies, so the comments on the `#[inline]` annotations are no longer relevant. I've left the `#[inline]` annotations themselves as they seem worthwhile since `va_copy` and `va_end` are a memcpy and a no-op respectively.
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Jul 31, 2026
…comments, r=folkertdev
Remove outdated comments from `va_list.rs`
Since rust-lang#150436 codegen backends haven't needed to implement `va_copy` or `va_end` as they are implemented using intrinsic fallback bodies, so the comments on the `#[inline]` annotations are no longer relevant. I've left the `#[inline]` annotations themselves as they seem worthwhile since `va_copy` and `va_end` are a memcpy and a no-op respectively.
rust-timer added a commit that referenced this pull request Jul 31, 2026
Rollup merge of #160157 - beetrees:va-list-outdated-backend-comments, r=folkertdev
Remove outdated comments from `va_list.rs`
Since #150436 codegen backends haven't needed to implement `va_copy` or `va_end` as they are implemented using intrinsic fallback bodies, so the comments on the `#[inline]` annotations are no longer relevant. I've left the `#[inline]` annotations themselves as they seem worthwhile since `va_copy` and `va_end` are a memcpy and a no-op respectively.
github-actionsBot pushed a commit to rust-lang/rustc-dev-guide that referenced this pull request Aug 3, 2026
… r=folkertdev
Remove outdated comments from `va_list.rs`
Since rust-lang/rust#150436 codegen backends haven't needed to implement `va_copy` or `va_end` as they are implemented using intrinsic fallback bodies, so the comments on the `#[inline]` annotations are no longer relevant. I've left the `#[inline]` annotations themselves as they seem worthwhile since `va_copy` and `va_end` are a memcpy and a no-op respectively.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.F-c_variadic`#![feature(c_variadic)]`S-waiting-on-borsStatus: Waiting on bors to run and complete tests. Bors will change the label on completion.T-libsRelevant to the library team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@folkertdev@rust-log-analyzer@rustbot@RalfJung@workingjubilee
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

c_variadic: impl va_copy and va_end as Rust intrinsics - #150436

Merged
rust-bors[bot] merged 2 commits into
rust-lang:mainfrom
folkertdev:va-list-copy
Jan 21, 2026
Merged

c_variadic: impl va_copy and va_end as Rust intrinsics#150436
rust-bors[bot] merged 2 commits into
rust-lang:mainfrom
folkertdev:va-list-copy

Conversation

@folkertdev

@folkertdevfolkertdev commented Dec 27, 2025

Copy link
Copy Markdown
Contributor

tracking issue: #44930

Implement va_copy as (the rust equivalent of) memcpy, which is the behavior of all current LLVM targets. By providing our own implementation, we can guarantee its behavior. These guarantees are important for implementing c-variadics in e.g. const-eval.

Discussed in #t-compiler/const-eval > c-variadics in const-eval.

I've also updated the comment for Drop a bit. The background here is that the C standard requires that va_end is used in the same function (and really, in the same scope) as the corresponding va_start or va_copy. That is because historically va_start would start a scope, which va_end would then close. e.g.

https://softwarepreservation.computerhistory.org/c_plus_plus/cfront/release_3.0.3/source/incl-master/proto-headers/stdarg.sol

#defineva_start(ap, parmN) {\
va_buf _va;\
_vastart(ap = (va_list)_va, (char *)&parmN + sizeof parmN)
#defineva_end(ap) }
#defineva_arg(ap, mode) *((mode *)_vaarg(ap, sizeof (mode)))

The C standard still has to consider such implementations, but for Rust they are irrelevant. Hence we can use Clone for va_copy and Drop for va_end.

@rustbotrustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Dec 27, 2025
Comment on lines 158 to 163
/// Basic implementation of a `va_list`.
#[repr(transparent)]
#[derive(Debug)]
#[derive(Debug, Clone, Copy)]
struct VaListInner {
ptr: *const c_void,
}

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

/// https://github.com/llvm/llvm-project/blob/0cdc1b6dd4a870fc41d4b15ad97e0001882aba58/clang/lib/CodeGen/Targets/Hexagon.cpp#L407-L417
#[repr(C)]
#[derive(Debug)]
#[derive(Debug, Clone, Copy)]

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

/// https://github.com/llvm/llvm-project/blob/af9a4263a1a209953a1d339ef781a954e31268ff/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp#L1211-L1215
#[repr(C)]
#[derive(Debug)]
#[derive(Debug, Clone, Copy)]

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

/// https://docs.google.com/gview?embedded=true&url=https://github.com/IBM/s390x-abi/releases/download/v1.7/lzsabi_s390x.pdf
#[repr(C)]
#[derive(Debug)]
#[derive(Debug, Clone, Copy)]

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

/// [GCC header]: https://web.mit.edu/darwin/src/modules/gcc/gcc/ginclude/va-ppc.h
#[repr(C)]
#[derive(Debug)]
#[derive(Debug, Clone, Copy)]

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Comment threadlibrary/core/src/ffi/va_list.rs
@folkertdevfolkertdev added the F-c_variadic `#![feature(c_variadic)]` label Dec 27, 2025
@rust-log-analyzer

This comment has been minimized.

@folkertdev
folkertdevforce-pushed the va-list-copy branch 3 times, most recently from 7a78640 to 8e09112CompareJanuary 2, 2026 21:02
@rustbotrustbot added the A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. label Jan 2, 2026
@folkertdev

Copy link
Copy Markdown
ContributorAuthor

r? @workingjubilee

The codegen of VaList::clone is target-specific now, and because minicore does not define VaList it is hard to test. I think it's fine to just test the behavior, and have LLVM use a memcpy when VaList is a struct, or just re-use the pointer value if it's just a pointer.

@folkertdev
folkertdev marked this pull request as ready for review January 2, 2026 21:04
@rustbot

Copy link
Copy Markdown
Collaborator

workingjubilee is currently at their maximum review capacity.
They may take a while to respond.

@rustbotrustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jan 2, 2026
@rustbot

Copy link
Copy Markdown
Collaborator

Some changes occurred in compiler/rustc_codegen_cranelift

cc @bjorn3

Some changes occurred to the intrinsics. Make sure the CTFE / Miri interpreter
gets adapted for the changes, if necessary.

cc @rust-lang/miri, @RalfJung, @oli-obk, @lcnr

Some changes occurred in compiler/rustc_codegen_gcc

cc @antoyo, @GuillaumeGomez

@rustbotrustbot removed the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Jan 2, 2026
@RalfJung

Copy link
Copy Markdown
Member

Implement va_copy as (the rust equivalent of) memcpy, which is the behavior of all current LLVM targets. By providing our own implementation, we can guarantee its behavior.

Didn't we say we would avoid that assumption and also support implementations that do malloc/free in va_copy / va_end? See #t-compiler/const-eval > c-variadics in const-eval @ 💬.

@folkertdev

Copy link
Copy Markdown
ContributorAuthor

That's right, we don't actually impl Copy for VaList, so that a future target could implement a meaningful Clone and Drop. It's just that in practice for all current targets Clone happens to be a memcpy and Drop a no-op

@workingjubileeworkingjubilee left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Offering a suggested historical note.

Please feel free to trim it or move it into the PR description itself, down to the amounts you find worthwhile or just amusing to keep (including 0 lines).

r=me after

Thanks!

View changes since this review

Comment threadlibrary/core/src/ffi/va_list.rs
@workingjubileeworkingjubilee added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jan 6, 2026
@RalfJung

Copy link
Copy Markdown
Member

@folkertdev what is your plan for va_copy regarding the const-eval support for this?
ISTM that without the intrinsic, it'll not be possible to catch a bunch of the UB that we had planned to catch?

Comment threadlibrary/core/src/intrinsics/mod.rs
@folkertdevfolkertdev changed the title c_variadic: use Clone instead of va_copyc_variadic: use Clone instead of LLVM va_copyJan 7, 2026
@rustbot

This comment has been minimized.

@folkertdev

Copy link
Copy Markdown
ContributorAuthor

Based on further discussion in #t-compiler/const-eval > c-variadics in const-eval, a slight change of plans

  • we still no longer call LLVM's va_copy
  • we do still have our own va_copy intrinsic that serves as a hook for const evaluation
  • va_copy has a fallback body, code generation backends should not provide their own implementation

I've changed the signature of the intrinsic to be more ergonomic, and made it safe because while the hook is used to detect UB, the intrinsic itself is completely safe.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rustbotrustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jan 19, 2026
@rust-log-analyzer

This comment has been minimized.

Comment threadlibrary/core/src/ffi/va_list.rs Outdated
///
/// See the [LLVM source] and [GCC header] for more details.
///
/// `va_copy` is `memcpy`: <https://github.com/llvm/llvm-project/blob/5aee01a3df011e660f26660bc30a8c94a1651d8e/llvm/lib/Target/PowerPC/PPCISelLowering.h#L713>

@RalfJungRalfJungJan 19, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is also just a header, not the implementation? (same for some of the other ones)

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Ah now I understand what happened: i copied these links from a github search result page. I manually looked them all up now, so all links should be correct.

@folkertdev
folkertdevforce-pushed the va-list-copy branch 2 times, most recently from 94ce7b4 to 6011fa6CompareJanuary 19, 2026 20:55
@RalfJung

Copy link
Copy Markdown
Member

Sounds great, thanks! r=workingjubilee,RalfJung with the last commit squashed away.

@bors delegate+

@rust-bors

rust-borsBot commented Jan 20, 2026

Copy link
Copy Markdown
Contributor

✌️ @folkertdev, you can now approve this pull request!

If @RalfJung told you to "r=me" after making some further change, then please make that change and post @bors r=RalfJung.

@folkertdev

Copy link
Copy Markdown
ContributorAuthor

@bors r=workingjubilee,RalfJung

@rust-bors

rust-borsBot commented Jan 20, 2026

Copy link
Copy Markdown
Contributor

📌 Commit 922057c has been approved by workingjubilee,RalfJung

It is now in the queue for this repository.

@rust-borsrust-borsBot added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jan 20, 2026
@jhprattjhpratt mentioned this pull request Jan 21, 2026
rust-borsBot pushed a commit that referenced this pull request Jan 21, 2026
Rollup of 6 pull requests
Successful merges:
- #150436 (`c_variadic`: impl `va_copy` and `va_end` as Rust intrinsics)
- #151340 (Port `#[patchable_function_entry]` to attr parser)
- #151351 (Deduplicate diagnostics for const trait supertraits)
- #151424 (missing colon after the compile-flags directive)
- #151428 (Port variance attrs to attr parser.)
- #151429 (s390x: Support aligned stack datalayout)
Failed merges:
- #151343 (Port some crate level attrs to the attribute parser)
r? @ghost
@rust-bors
rust-borsBot merged commit 43d2006 into rust-lang:mainJan 21, 2026
11 checks passed
@rustbotrustbot added this to the 1.95.0 milestone Jan 21, 2026
rust-timer added a commit that referenced this pull request Jan 21, 2026
Rollup merge of #150436 - va-list-copy, r=workingjubilee,RalfJung
`c_variadic`: impl `va_copy` and `va_end` as Rust intrinsics
tracking issue: #44930
Implement `va_copy` as (the rust equivalent of) `memcpy`, which is the behavior of all current LLVM targets. By providing our own implementation, we can guarantee its behavior. These guarantees are important for implementing c-variadics in e.g. const-eval.
Discussed in [#t-compiler/const-eval > c-variadics in const-eval](https://rust-lang.zulipchat.com/#narrow/channel/146212-t-compiler.2Fconst-eval/topic/c-variadics.20in.20const-eval/with/565509704).
I've also updated the comment for `Drop` a bit. The background here is that the C standard requires that `va_end` is used in the same function (and really, in the same scope) as the corresponding `va_start` or `va_copy`. That is because historically `va_start` would start a scope, which `va_end` would then close. e.g.
https://softwarepreservation.computerhistory.org/c_plus_plus/cfront/release_3.0.3/source/incl-master/proto-headers/stdarg.sol
```c
#define va_start(ap, parmN) {\
va_buf _va;\
_vastart(ap = (va_list)_va, (char *)&parmN + sizeof parmN)
#define va_end(ap) }
#define va_arg(ap, mode) *((mode *)_vaarg(ap, sizeof (mode)))
```
The C standard still has to consider such implementations, but for Rust they are irrelevant. Hence we can use `Clone` for `va_copy` and `Drop` for `va_end`.
christian-schilling pushed a commit to christian-schilling/rustc_codegen_cranelift that referenced this pull request Jan 27, 2026
Rollup of 6 pull requests
Successful merges:
- rust-lang/rust#150436 (`c_variadic`: impl `va_copy` and `va_end` as Rust intrinsics)
- rust-lang/rust#151340 (Port `#[patchable_function_entry]` to attr parser)
- rust-lang/rust#151351 (Deduplicate diagnostics for const trait supertraits)
- rust-lang/rust#151424 (missing colon after the compile-flags directive)
- rust-lang/rust#151428 (Port variance attrs to attr parser.)
- rust-lang/rust#151429 (s390x: Support aligned stack datalayout)
Failed merges:
- rust-lang/rust#151343 (Port some crate level attrs to the attribute parser)
r? @ghost
christian-schilling pushed a commit to christian-schilling/rustc_codegen_cranelift that referenced this pull request Jan 27, 2026
Rollup of 6 pull requests
Successful merges:
- rust-lang/rust#150436 (`c_variadic`: impl `va_copy` and `va_end` as Rust intrinsics)
- rust-lang/rust#151340 (Port `#[patchable_function_entry]` to attr parser)
- rust-lang/rust#151351 (Deduplicate diagnostics for const trait supertraits)
- rust-lang/rust#151424 (missing colon after the compile-flags directive)
- rust-lang/rust#151428 (Port variance attrs to attr parser.)
- rust-lang/rust#151429 (s390x: Support aligned stack datalayout)
Failed merges:
- rust-lang/rust#151343 (Port some crate level attrs to the attribute parser)
r? @ghost
bjorn3 pushed a commit to bjorn3/rust that referenced this pull request Feb 18, 2026
…fJung
`c_variadic`: impl `va_copy` and `va_end` as Rust intrinsics
tracking issue: rust-lang#44930
Implement `va_copy` as (the rust equivalent of) `memcpy`, which is the behavior of all current LLVM targets. By providing our own implementation, we can guarantee its behavior. These guarantees are important for implementing c-variadics in e.g. const-eval.
Discussed in [#t-compiler/const-eval > c-variadics in const-eval](https://rust-lang.zulipchat.com/#narrow/channel/146212-t-compiler.2Fconst-eval/topic/c-variadics.20in.20const-eval/with/565509704).
I've also updated the comment for `Drop` a bit. The background here is that the C standard requires that `va_end` is used in the same function (and really, in the same scope) as the corresponding `va_start` or `va_copy`. That is because historically `va_start` would start a scope, which `va_end` would then close. e.g.
https://softwarepreservation.computerhistory.org/c_plus_plus/cfront/release_3.0.3/source/incl-master/proto-headers/stdarg.sol
```c
#define va_start(ap, parmN) {\
va_buf _va;\
_vastart(ap = (va_list)_va, (char *)&parmN + sizeof parmN)
#define va_end(ap) }
#define va_arg(ap, mode) *((mode *)_vaarg(ap, sizeof (mode)))
```
The C standard still has to consider such implementations, but for Rust they are irrelevant. Hence we can use `Clone` for `va_copy` and `Drop` for `va_end`.
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Jul 31, 2026
…comments, r=folkertdev
Remove outdated comments from `va_list.rs`
Since rust-lang#150436 codegen backends haven't needed to implement `va_copy` or `va_end` as they are implemented using intrinsic fallback bodies, so the comments on the `#[inline]` annotations are no longer relevant. I've left the `#[inline]` annotations themselves as they seem worthwhile since `va_copy` and `va_end` are a memcpy and a no-op respectively.
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Jul 31, 2026
…comments, r=folkertdev
Remove outdated comments from `va_list.rs`
Since rust-lang#150436 codegen backends haven't needed to implement `va_copy` or `va_end` as they are implemented using intrinsic fallback bodies, so the comments on the `#[inline]` annotations are no longer relevant. I've left the `#[inline]` annotations themselves as they seem worthwhile since `va_copy` and `va_end` are a memcpy and a no-op respectively.
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Jul 31, 2026
…comments, r=folkertdev
Remove outdated comments from `va_list.rs`
Since rust-lang#150436 codegen backends haven't needed to implement `va_copy` or `va_end` as they are implemented using intrinsic fallback bodies, so the comments on the `#[inline]` annotations are no longer relevant. I've left the `#[inline]` annotations themselves as they seem worthwhile since `va_copy` and `va_end` are a memcpy and a no-op respectively.
rust-timer added a commit that referenced this pull request Jul 31, 2026
Rollup merge of #160157 - beetrees:va-list-outdated-backend-comments, r=folkertdev
Remove outdated comments from `va_list.rs`
Since #150436 codegen backends haven't needed to implement `va_copy` or `va_end` as they are implemented using intrinsic fallback bodies, so the comments on the `#[inline]` annotations are no longer relevant. I've left the `#[inline]` annotations themselves as they seem worthwhile since `va_copy` and `va_end` are a memcpy and a no-op respectively.
github-actionsBot pushed a commit to rust-lang/rustc-dev-guide that referenced this pull request Aug 3, 2026
… r=folkertdev
Remove outdated comments from `va_list.rs`
Since rust-lang/rust#150436 codegen backends haven't needed to implement `va_copy` or `va_end` as they are implemented using intrinsic fallback bodies, so the comments on the `#[inline]` annotations are no longer relevant. I've left the `#[inline]` annotations themselves as they seem worthwhile since `va_copy` and `va_end` are a memcpy and a no-op respectively.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.F-c_variadic`#![feature(c_variadic)]`S-waiting-on-borsStatus: Waiting on bors to run and complete tests. Bors will change the label on completion.T-libsRelevant to the library team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@folkertdev@rust-log-analyzer@rustbot@RalfJung@workingjubilee
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

c_variadic: impl va_copy and va_end as Rust intrinsics - #150436

Merged
rust-bors[bot] merged 2 commits into
rust-lang:mainfrom
folkertdev:va-list-copy
Jan 21, 2026
Merged

c_variadic: impl va_copy and va_end as Rust intrinsics#150436
rust-bors[bot] merged 2 commits into
rust-lang:mainfrom
folkertdev:va-list-copy

Conversation

@folkertdev

@folkertdevfolkertdev commented Dec 27, 2025

Copy link
Copy Markdown
Contributor

tracking issue: #44930

Implement va_copy as (the rust equivalent of) memcpy, which is the behavior of all current LLVM targets. By providing our own implementation, we can guarantee its behavior. These guarantees are important for implementing c-variadics in e.g. const-eval.

Discussed in #t-compiler/const-eval > c-variadics in const-eval.

I've also updated the comment for Drop a bit. The background here is that the C standard requires that va_end is used in the same function (and really, in the same scope) as the corresponding va_start or va_copy. That is because historically va_start would start a scope, which va_end would then close. e.g.

https://softwarepreservation.computerhistory.org/c_plus_plus/cfront/release_3.0.3/source/incl-master/proto-headers/stdarg.sol

#defineva_start(ap, parmN) {\
va_buf _va;\
_vastart(ap = (va_list)_va, (char *)&parmN + sizeof parmN)
#defineva_end(ap) }
#defineva_arg(ap, mode) *((mode *)_vaarg(ap, sizeof (mode)))

The C standard still has to consider such implementations, but for Rust they are irrelevant. Hence we can use Clone for va_copy and Drop for va_end.

@rustbotrustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Dec 27, 2025
Comment on lines 158 to 163
/// Basic implementation of a `va_list`.
#[repr(transparent)]
#[derive(Debug)]
#[derive(Debug, Clone, Copy)]
struct VaListInner {
ptr: *const c_void,
}

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

/// https://github.com/llvm/llvm-project/blob/0cdc1b6dd4a870fc41d4b15ad97e0001882aba58/clang/lib/CodeGen/Targets/Hexagon.cpp#L407-L417
#[repr(C)]
#[derive(Debug)]
#[derive(Debug, Clone, Copy)]

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

/// https://github.com/llvm/llvm-project/blob/af9a4263a1a209953a1d339ef781a954e31268ff/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp#L1211-L1215
#[repr(C)]
#[derive(Debug)]
#[derive(Debug, Clone, Copy)]

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

/// https://docs.google.com/gview?embedded=true&url=https://github.com/IBM/s390x-abi/releases/download/v1.7/lzsabi_s390x.pdf
#[repr(C)]
#[derive(Debug)]
#[derive(Debug, Clone, Copy)]

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

/// [GCC header]: https://web.mit.edu/darwin/src/modules/gcc/gcc/ginclude/va-ppc.h
#[repr(C)]
#[derive(Debug)]
#[derive(Debug, Clone, Copy)]

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Comment threadlibrary/core/src/ffi/va_list.rs
@folkertdevfolkertdev added the F-c_variadic `#![feature(c_variadic)]` label Dec 27, 2025
@rust-log-analyzer

This comment has been minimized.

@folkertdev
folkertdevforce-pushed the va-list-copy branch 3 times, most recently from 7a78640 to 8e09112CompareJanuary 2, 2026 21:02
@rustbotrustbot added the A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. label Jan 2, 2026
@folkertdev

Copy link
Copy Markdown
ContributorAuthor

r? @workingjubilee

The codegen of VaList::clone is target-specific now, and because minicore does not define VaList it is hard to test. I think it's fine to just test the behavior, and have LLVM use a memcpy when VaList is a struct, or just re-use the pointer value if it's just a pointer.

@folkertdev
folkertdev marked this pull request as ready for review January 2, 2026 21:04
@rustbot

Copy link
Copy Markdown
Collaborator

workingjubilee is currently at their maximum review capacity.
They may take a while to respond.

@rustbotrustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jan 2, 2026
@rustbot

Copy link
Copy Markdown
Collaborator

Some changes occurred in compiler/rustc_codegen_cranelift

cc @bjorn3

Some changes occurred to the intrinsics. Make sure the CTFE / Miri interpreter
gets adapted for the changes, if necessary.

cc @rust-lang/miri, @RalfJung, @oli-obk, @lcnr

Some changes occurred in compiler/rustc_codegen_gcc

cc @antoyo, @GuillaumeGomez

@rustbotrustbot removed the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Jan 2, 2026
@RalfJung

Copy link
Copy Markdown
Member

Implement va_copy as (the rust equivalent of) memcpy, which is the behavior of all current LLVM targets. By providing our own implementation, we can guarantee its behavior.

Didn't we say we would avoid that assumption and also support implementations that do malloc/free in va_copy / va_end? See #t-compiler/const-eval > c-variadics in const-eval @ 💬.

@folkertdev

Copy link
Copy Markdown
ContributorAuthor

That's right, we don't actually impl Copy for VaList, so that a future target could implement a meaningful Clone and Drop. It's just that in practice for all current targets Clone happens to be a memcpy and Drop a no-op

@workingjubileeworkingjubilee left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Offering a suggested historical note.

Please feel free to trim it or move it into the PR description itself, down to the amounts you find worthwhile or just amusing to keep (including 0 lines).

r=me after

Thanks!

View changes since this review

Comment threadlibrary/core/src/ffi/va_list.rs
@workingjubileeworkingjubilee added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jan 6, 2026
@RalfJung

Copy link
Copy Markdown
Member

@folkertdev what is your plan for va_copy regarding the const-eval support for this?
ISTM that without the intrinsic, it'll not be possible to catch a bunch of the UB that we had planned to catch?

Comment threadlibrary/core/src/intrinsics/mod.rs
@folkertdevfolkertdev changed the title c_variadic: use Clone instead of va_copyc_variadic: use Clone instead of LLVM va_copyJan 7, 2026
@rustbot

This comment has been minimized.

@folkertdev

Copy link
Copy Markdown
ContributorAuthor

Based on further discussion in #t-compiler/const-eval > c-variadics in const-eval, a slight change of plans

  • we still no longer call LLVM's va_copy
  • we do still have our own va_copy intrinsic that serves as a hook for const evaluation
  • va_copy has a fallback body, code generation backends should not provide their own implementation

I've changed the signature of the intrinsic to be more ergonomic, and made it safe because while the hook is used to detect UB, the intrinsic itself is completely safe.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rustbotrustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jan 19, 2026
@rust-log-analyzer

This comment has been minimized.

Comment threadlibrary/core/src/ffi/va_list.rs Outdated
///
/// See the [LLVM source] and [GCC header] for more details.
///
/// `va_copy` is `memcpy`: <https://github.com/llvm/llvm-project/blob/5aee01a3df011e660f26660bc30a8c94a1651d8e/llvm/lib/Target/PowerPC/PPCISelLowering.h#L713>

@RalfJungRalfJungJan 19, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is also just a header, not the implementation? (same for some of the other ones)

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Ah now I understand what happened: i copied these links from a github search result page. I manually looked them all up now, so all links should be correct.

@folkertdev
folkertdevforce-pushed the va-list-copy branch 2 times, most recently from 94ce7b4 to 6011fa6CompareJanuary 19, 2026 20:55
@RalfJung

Copy link
Copy Markdown
Member

Sounds great, thanks! r=workingjubilee,RalfJung with the last commit squashed away.

@bors delegate+

@rust-bors

rust-borsBot commented Jan 20, 2026

Copy link
Copy Markdown
Contributor

✌️ @folkertdev, you can now approve this pull request!

If @RalfJung told you to "r=me" after making some further change, then please make that change and post @bors r=RalfJung.

@folkertdev

Copy link
Copy Markdown
ContributorAuthor

@bors r=workingjubilee,RalfJung

@rust-bors

rust-borsBot commented Jan 20, 2026

Copy link
Copy Markdown
Contributor

📌 Commit 922057c has been approved by workingjubilee,RalfJung

It is now in the queue for this repository.

@rust-borsrust-borsBot added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jan 20, 2026
@jhprattjhpratt mentioned this pull request Jan 21, 2026
rust-borsBot pushed a commit that referenced this pull request Jan 21, 2026
Rollup of 6 pull requests
Successful merges:
- #150436 (`c_variadic`: impl `va_copy` and `va_end` as Rust intrinsics)
- #151340 (Port `#[patchable_function_entry]` to attr parser)
- #151351 (Deduplicate diagnostics for const trait supertraits)
- #151424 (missing colon after the compile-flags directive)
- #151428 (Port variance attrs to attr parser.)
- #151429 (s390x: Support aligned stack datalayout)
Failed merges:
- #151343 (Port some crate level attrs to the attribute parser)
r? @ghost
@rust-bors
rust-borsBot merged commit 43d2006 into rust-lang:mainJan 21, 2026
11 checks passed
@rustbotrustbot added this to the 1.95.0 milestone Jan 21, 2026
rust-timer added a commit that referenced this pull request Jan 21, 2026
Rollup merge of #150436 - va-list-copy, r=workingjubilee,RalfJung
`c_variadic`: impl `va_copy` and `va_end` as Rust intrinsics
tracking issue: #44930
Implement `va_copy` as (the rust equivalent of) `memcpy`, which is the behavior of all current LLVM targets. By providing our own implementation, we can guarantee its behavior. These guarantees are important for implementing c-variadics in e.g. const-eval.
Discussed in [#t-compiler/const-eval > c-variadics in const-eval](https://rust-lang.zulipchat.com/#narrow/channel/146212-t-compiler.2Fconst-eval/topic/c-variadics.20in.20const-eval/with/565509704).
I've also updated the comment for `Drop` a bit. The background here is that the C standard requires that `va_end` is used in the same function (and really, in the same scope) as the corresponding `va_start` or `va_copy`. That is because historically `va_start` would start a scope, which `va_end` would then close. e.g.
https://softwarepreservation.computerhistory.org/c_plus_plus/cfront/release_3.0.3/source/incl-master/proto-headers/stdarg.sol
```c
#define va_start(ap, parmN) {\
va_buf _va;\
_vastart(ap = (va_list)_va, (char *)&parmN + sizeof parmN)
#define va_end(ap) }
#define va_arg(ap, mode) *((mode *)_vaarg(ap, sizeof (mode)))
```
The C standard still has to consider such implementations, but for Rust they are irrelevant. Hence we can use `Clone` for `va_copy` and `Drop` for `va_end`.
christian-schilling pushed a commit to christian-schilling/rustc_codegen_cranelift that referenced this pull request Jan 27, 2026
Rollup of 6 pull requests
Successful merges:
- rust-lang/rust#150436 (`c_variadic`: impl `va_copy` and `va_end` as Rust intrinsics)
- rust-lang/rust#151340 (Port `#[patchable_function_entry]` to attr parser)
- rust-lang/rust#151351 (Deduplicate diagnostics for const trait supertraits)
- rust-lang/rust#151424 (missing colon after the compile-flags directive)
- rust-lang/rust#151428 (Port variance attrs to attr parser.)
- rust-lang/rust#151429 (s390x: Support aligned stack datalayout)
Failed merges:
- rust-lang/rust#151343 (Port some crate level attrs to the attribute parser)
r? @ghost
christian-schilling pushed a commit to christian-schilling/rustc_codegen_cranelift that referenced this pull request Jan 27, 2026
Rollup of 6 pull requests
Successful merges:
- rust-lang/rust#150436 (`c_variadic`: impl `va_copy` and `va_end` as Rust intrinsics)
- rust-lang/rust#151340 (Port `#[patchable_function_entry]` to attr parser)
- rust-lang/rust#151351 (Deduplicate diagnostics for const trait supertraits)
- rust-lang/rust#151424 (missing colon after the compile-flags directive)
- rust-lang/rust#151428 (Port variance attrs to attr parser.)
- rust-lang/rust#151429 (s390x: Support aligned stack datalayout)
Failed merges:
- rust-lang/rust#151343 (Port some crate level attrs to the attribute parser)
r? @ghost
bjorn3 pushed a commit to bjorn3/rust that referenced this pull request Feb 18, 2026
…fJung
`c_variadic`: impl `va_copy` and `va_end` as Rust intrinsics
tracking issue: rust-lang#44930
Implement `va_copy` as (the rust equivalent of) `memcpy`, which is the behavior of all current LLVM targets. By providing our own implementation, we can guarantee its behavior. These guarantees are important for implementing c-variadics in e.g. const-eval.
Discussed in [#t-compiler/const-eval > c-variadics in const-eval](https://rust-lang.zulipchat.com/#narrow/channel/146212-t-compiler.2Fconst-eval/topic/c-variadics.20in.20const-eval/with/565509704).
I've also updated the comment for `Drop` a bit. The background here is that the C standard requires that `va_end` is used in the same function (and really, in the same scope) as the corresponding `va_start` or `va_copy`. That is because historically `va_start` would start a scope, which `va_end` would then close. e.g.
https://softwarepreservation.computerhistory.org/c_plus_plus/cfront/release_3.0.3/source/incl-master/proto-headers/stdarg.sol
```c
#define va_start(ap, parmN) {\
va_buf _va;\
_vastart(ap = (va_list)_va, (char *)&parmN + sizeof parmN)
#define va_end(ap) }
#define va_arg(ap, mode) *((mode *)_vaarg(ap, sizeof (mode)))
```
The C standard still has to consider such implementations, but for Rust they are irrelevant. Hence we can use `Clone` for `va_copy` and `Drop` for `va_end`.
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Jul 31, 2026
…comments, r=folkertdev
Remove outdated comments from `va_list.rs`
Since rust-lang#150436 codegen backends haven't needed to implement `va_copy` or `va_end` as they are implemented using intrinsic fallback bodies, so the comments on the `#[inline]` annotations are no longer relevant. I've left the `#[inline]` annotations themselves as they seem worthwhile since `va_copy` and `va_end` are a memcpy and a no-op respectively.
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Jul 31, 2026
…comments, r=folkertdev
Remove outdated comments from `va_list.rs`
Since rust-lang#150436 codegen backends haven't needed to implement `va_copy` or `va_end` as they are implemented using intrinsic fallback bodies, so the comments on the `#[inline]` annotations are no longer relevant. I've left the `#[inline]` annotations themselves as they seem worthwhile since `va_copy` and `va_end` are a memcpy and a no-op respectively.
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Jul 31, 2026
…comments, r=folkertdev
Remove outdated comments from `va_list.rs`
Since rust-lang#150436 codegen backends haven't needed to implement `va_copy` or `va_end` as they are implemented using intrinsic fallback bodies, so the comments on the `#[inline]` annotations are no longer relevant. I've left the `#[inline]` annotations themselves as they seem worthwhile since `va_copy` and `va_end` are a memcpy and a no-op respectively.
rust-timer added a commit that referenced this pull request Jul 31, 2026
Rollup merge of #160157 - beetrees:va-list-outdated-backend-comments, r=folkertdev
Remove outdated comments from `va_list.rs`
Since #150436 codegen backends haven't needed to implement `va_copy` or `va_end` as they are implemented using intrinsic fallback bodies, so the comments on the `#[inline]` annotations are no longer relevant. I've left the `#[inline]` annotations themselves as they seem worthwhile since `va_copy` and `va_end` are a memcpy and a no-op respectively.
github-actionsBot pushed a commit to rust-lang/rustc-dev-guide that referenced this pull request Aug 3, 2026
… r=folkertdev
Remove outdated comments from `va_list.rs`
Since rust-lang/rust#150436 codegen backends haven't needed to implement `va_copy` or `va_end` as they are implemented using intrinsic fallback bodies, so the comments on the `#[inline]` annotations are no longer relevant. I've left the `#[inline]` annotations themselves as they seem worthwhile since `va_copy` and `va_end` are a memcpy and a no-op respectively.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.F-c_variadic`#![feature(c_variadic)]`S-waiting-on-borsStatus: Waiting on bors to run and complete tests. Bors will change the label on completion.T-libsRelevant to the library team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@folkertdev@rust-log-analyzer@rustbot@RalfJung@workingjubilee