Skip to content

fix ICE in const_c_variadic when passing ZSTs#153398

Open
folkertdev wants to merge 1 commit intorust-lang:mainfrom
folkertdev:const-c-variadic-trailing-zst
Open

fix ICE in const_c_variadic when passing ZSTs#153398
folkertdev wants to merge 1 commit intorust-lang:mainfrom
folkertdev:const-c-variadic-trailing-zst

Conversation

@folkertdev
Copy link
Contributor

fixes #153351
r? RalfJung

There was a mismatch between the caller and callee ABI where the caller does not pass ZST arguments, but the callee does expect them. Because ZSTs don't implement VaArgSafe the program must already be invalid if this comes up.

@folkertdev folkertdev added the F-c_variadic `#![feature(c_variadic)]` label Mar 4, 2026
@rustbot
Copy link
Collaborator

rustbot commented Mar 4, 2026

Some changes occurred to the CTFE / Miri interpreter

cc @rust-lang/miri

Some changes occurred to the CTFE machinery

cc @RalfJung, @oli-obk, @lcnr

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Mar 4, 2026
@rustbot
Copy link
Collaborator

rustbot commented Mar 4, 2026

RalfJung is not on the review rotation at the moment.
They may take a while to respond.

J: Iterator<Item = (usize, &'a ArgAbi<'tcx, Ty<'tcx>>)>,
{
// Arguments that are ignored (ZSTs) are not passed by the caller.
let mut callee_abis = callee_abis.filter(|(_, abi)| !abi.is_ignore());
Copy link
Member

Choose a reason for hiding this comment

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

I think it'd be better to do this in call.rs where this function is called; that's closer to the other logic for skipping ignored arguments.


unsafe fn read_too_many() {
const { read_n::<0>(read_as::<u32>, 1i32) }
//~^ ERROR can't pass a function item to a variadic function
Copy link
Member

Choose a reason for hiding this comment

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

Wait, we are executing this const even though it has a type error? That seems very wrong.

J: Iterator<Item = (usize, &'a ArgAbi<'tcx, Ty<'tcx>>)>,
{
// Arguments that are ignored (ZSTs) are not passed by the caller.
let mut callee_abis = callee_abis.filter(|(_, abi)| !abi.is_ignore());
Copy link
Member

Choose a reason for hiding this comment

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

Can you add a test in src/tools/miri/tests/pass/c-variadic.rs where the caller passes i32, (), i32 and then I guess the callee only sees the two integers? That does seem strange though, arguably the callee needs to fetch the () argument or else it's UB, no?

@folkertdev folkertdev force-pushed the const-c-variadic-trailing-zst branch from fd19350 to f8da51c Compare March 7, 2026 18:27
@rustbot
Copy link
Collaborator

rustbot commented Mar 7, 2026

The Miri subtree was changed

cc @rust-lang/miri

@rustbot
Copy link
Collaborator

rustbot commented Mar 7, 2026

This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

@rust-log-analyzer

This comment has been minimized.

@folkertdev folkertdev force-pushed the const-c-variadic-trailing-zst branch from f8da51c to e24fd0a Compare March 7, 2026 20:19
@folkertdev folkertdev force-pushed the const-c-variadic-trailing-zst branch from e24fd0a to 7b35105 Compare March 7, 2026 20:42
@folkertdev
Copy link
Contributor Author

After playing around with this some more, it turned out that ignored arguments are platform-specific, because some ABIs explicitly pass ZSTs. So, I think that it's actually best to truly pass the argument, and then have any use fail because there is no valid way to e.g. read a () from the variable argument list.

Comment on lines +645 to +658
loop {
// Peel off ignored arguments. These are not passed by the caller, but are present in
// the callee's ABI.
while let Some((_idx, callee_abi)) = callee_abis.peek()
&& callee_abi.is_ignore()
{
let mplace = self.allocate(callee_abi.layout, MemoryKind::Stack)?;
varargs.push(mplace);
let _ = callee_abis.next();
}

let Some((fn_arg, caller_abi)) = caller_args.next() else {
break;
};
Copy link
Contributor Author

Choose a reason for hiding this comment

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

a bit weird, but this needs a do-while loop

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

Labels

F-c_variadic `#![feature(c_variadic)]` S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[ICE]: callee_abis.next().is_none()

4 participants