Description
We found this issue while integrating recent upstream changes into ferrocene.
The easiest way to reproduce the issue is with the following Cargo project.
Cargo.toml
[package]
name = "repro"
edition = "2024"
[target.aarch64-unknown-none.dependencies]
semihosting.version = "=0.1.20"
semihosting.features = ["stdio", "panic-handler"]
.cargo/config.toml
[target.aarch64-unknown-none]
runner = "qemu-aarch64-static" # `qemu-aarch64` should also work
src/main.rs
#![allow(incomplete_features)]
#![cfg_attr(target_arch = "aarch64", no_main)]
#![cfg_attr(target_arch = "aarch64", no_std)]
#![feature(async_drop, impl_trait_in_assoc_type)]
use core::future::{self, AsyncDrop};
use core::mem;
use core::pin::{Pin, pin};
#[cfg(target_arch = "aarch64")]
use semihosting::println;
#[cfg_attr(target_arch = "aarch64", unsafe(export_name = "_start"))]
fn main() {
test_async_drop(AsyncStruct {
b: AsyncInt(8),
a: AsyncInt(7),
i: 6,
});
#[cfg(target_arch = "aarch64")]
semihosting::process::exit(0);
}
fn test_async_drop<T>(x: T) {
let mut x = mem::MaybeUninit::new(x);
let dtor = pin!(unsafe { future::async_drop_in_place(x.as_mut_ptr()) });
println!("{}", mem::size_of_val(&*dtor));
}
#[allow(dead_code)]
struct AsyncInt(i32);
impl Drop for AsyncInt {
fn drop(&mut self) {}
}
impl AsyncDrop for AsyncInt {
async fn drop(self: Pin<&mut Self>) {}
}
#[allow(dead_code)]
struct AsyncStruct {
i: i32,
a: AsyncInt,
b: AsyncInt,
}
impl Drop for AsyncStruct {
fn drop(&mut self) {}
}
impl AsyncDrop for AsyncStruct {
async fn drop(self: Pin<&mut Self>) {}
}
If you run this on a x86_64 host then you get the value 168 which is what the test expects
$ cargo run
168
If you compile to aarch64-unknown-none
and run the program in QEMU you get the value 136.
$ cargo run --target aarch64-unknown-none
136
The difference might be that the aarch64-unknown-none
target is a panic=abort
(non-unwinding) target so the size of the coroutine is different due to the lack of drop flags or landing pads.
Note that both targets have 64-bit pointer which is what the UI test uses as the only criteria to execute the assertion or not.
Were are not exactly sure which recent PR broke the test as it was passing before but it should be one of the PRs listed in ferrocene/ferrocene#1459 (comment)
Meta
rustc --version --verbose
:
rustc --version --verbose
rustc 1.89.0-nightly (ce7e97f73 2025-05-11)
binary: rustc
commit-hash: ce7e97f7371af47e0786f74aa169f6ac9473ff4e
commit-date: 2025-05-11
host: x86_64-unknown-linux-gnu
release: 1.89.0-nightly
LLVM version: 20.1.4
Activity
japaric commentedon May 12, 2025
after bisecting:
The last good nightly was nightly-2025-04-28
(cb31a009e 2025-04-27)
. There, both targets report a size of 1376.The first bad nightly is nightly-2025-04-29
(25cdf1f67 2025-04-28)
. That's where we start seeing the 168 vs 136 divergence.The most relevant PR between those two nightlies is PR #123948 (cc @azhogin) . That PR also changed the expected values in the UI test.
japaric commentedon May 12, 2025
The reported size changes if one switches from
panic=unwind
topanic=abort
. This can be confirmed in the repro with the following change in theCargo.toml
With this change the reported size becomes 136 which matches the value of the
aarch64-unknown-none
target, a target that defaults topanic=abort
as seen belowui/async-drop-initial: factor in panic strategy in destructor size check
ui/async-drop-initial: factor in panic strategy in destructor size check
ui/async-drop-initial: factor in panic strategy in destructor size check
japaric commentedon May 12, 2025
submitted a fix in #140941
petrochenkov commentedon May 12, 2025
Duplicate of #140493.
Auto merge of rust-lang#140941 - ferrocene:ja/gh140939-fix-async-drop…
Auto merge of rust-lang#140941 - ferrocene:ja/gh140939-fix-async-drop…