Skip to content

UI test async-drop-initial now fails size assertion on aarch64-unknown-none #140939

Closed
@japaric

Description

@japaric

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-testsuiteArea: The testsuite used to check the correctness of rustcC-bugCategory: This is a bug.F-async_drop`#![feature(async_drop)]`O-AArch64Armv8-A or later processors in AArch64 modeT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions