Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

run abi/compatibility test against a whole bunch of targets #116030

Merged
merged 1 commit into from
Sep 29, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
183 changes: 173 additions & 10 deletions tests/ui/abi/compatibility.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,174 @@
// check-pass
// revisions: host
// revisions: arm
//[arm] compile-flags: --target arm-unknown-linux-gnueabi
//[arm] needs-llvm-components: arm
// revisions: aarch64
//[aarch64] compile-flags: --target aarch64-unknown-linux-gnu
//[aarch64] needs-llvm-components: aarch64
// revisions: s390x
//[s390x] compile-flags: --target s390x-unknown-linux-gnu
//[s390x] needs-llvm-components: systemz
// revisions: mips
//[mips] compile-flags: --target mips-unknown-linux-gnu
//[mips] needs-llvm-components: mips
// revisions: mips64
//[mips64] compile-flags: --target mips64-unknown-linux-gnuabi64
//[mips64] needs-llvm-components: mips
// revisions: sparc
//[sparc] compile-flags: --target sparc-unknown-linux-gnu
//[sparc] needs-llvm-components: sparc
// revisions: sparc64
//[sparc64] compile-flags: --target sparc64-unknown-linux-gnu
//[sparc64] needs-llvm-components: sparc
// revisions: powerpc64
//[powerpc64] compile-flags: --target powerpc64-unknown-linux-gnu
//[powerpc64] needs-llvm-components: powerpc
// revisions: riscv
//[riscv] compile-flags: --target riscv64gc-unknown-linux-gnu
//[riscv] needs-llvm-components: riscv
// revisions: loongarch64
//[loongarch64] compile-flags: --target loongarch64-unknown-linux-gnu
//[loongarch64] needs-llvm-components: loongarch
// revisions: wasm
//[wasm] compile-flags: --target wasm32-unknown-unknown
RalfJung marked this conversation as resolved.
Show resolved Hide resolved
//[wasm] needs-llvm-components: webassembly
// revisions: wasi
//[wasi] compile-flags: --target wasm32-wasi
//[wasi] needs-llvm-components: webassembly
// revisions: nvptx64
//[nvptx64] compile-flags: --target nvptx64-nvidia-cuda
//[nvptx64] needs-llvm-components: nvptx
#![feature(rustc_attrs, unsized_fn_params, transparent_unions)]
#![cfg_attr(not(host), feature(no_core, lang_items), no_std, no_core)]
#![allow(unused, improper_ctypes_definitions, internal_features)]
use std::marker::PhantomData;
use std::mem::ManuallyDrop;
use std::num::NonZeroI32;
use std::ptr::NonNull;

// FIXME: a bunch of targets are broken in various ways.
// FIXME: some targets are broken in various ways.
// Hence there are `cfg` throughout this test to disable parts of it on those targets.
// sparc64: https://github.com/rust-lang/rust/issues/115336
// mips64: https://github.com/rust-lang/rust/issues/115404

#[cfg(host)]
use std::{
any::Any, marker::PhantomData, mem::ManuallyDrop, num::NonZeroI32, ptr::NonNull, rc::Rc,
sync::Arc,
};

/// To work cross-target this test must be no_core.
/// This little prelude supplies what we need.
#[cfg(not(host))]
mod prelude {
#[lang = "sized"]
pub trait Sized {}

#[lang = "receiver"]
pub trait Receiver {}
impl<T: ?Sized> Receiver for &T {}
impl<T: ?Sized> Receiver for &mut T {}

#[lang = "copy"]
pub trait Copy: Sized {}
impl Copy for i32 {}
impl Copy for f32 {}
impl<T: ?Sized> Copy for &T {}
impl<T: ?Sized> Copy for *const T {}
impl<T: ?Sized> Copy for *mut T {}

#[lang = "clone"]
pub trait Clone: Sized {
fn clone(&self) -> Self;
}

#[lang = "phantom_data"]
pub struct PhantomData<T: ?Sized>;
impl<T: ?Sized> Copy for PhantomData<T> {}

#[lang = "unsafe_cell"]
#[repr(transparent)]
pub struct UnsafeCell<T: ?Sized> {
value: T,
}

pub trait Any: 'static {}

pub enum Option<T> {
None,
Some(T),
}
impl<T: Copy> Copy for Option<T> {}

pub enum Result<T, E> {
Ok(T),
Err(E),
}
impl<T: Copy, E: Copy> Copy for Result<T, E> {}

#[lang = "manually_drop"]
#[repr(transparent)]
pub struct ManuallyDrop<T: ?Sized> {
value: T,
}
impl<T: Copy + ?Sized> Copy for ManuallyDrop<T> {}

#[repr(transparent)]
#[rustc_layout_scalar_valid_range_start(1)]
#[rustc_nonnull_optimization_guaranteed]
pub struct NonNull<T: ?Sized> {
pointer: *const T,
}
impl<T: ?Sized> Copy for NonNull<T> {}

#[repr(transparent)]
#[rustc_layout_scalar_valid_range_start(1)]
#[rustc_nonnull_optimization_guaranteed]
pub struct NonZeroI32(i32);

// This just stands in for a non-trivial type.
pub struct Vec<T> {
ptr: NonNull<T>,
cap: usize,
len: usize,
}

pub struct Unique<T: ?Sized> {
pub pointer: NonNull<T>,
pub _marker: PhantomData<T>,
}

pub struct Global;

#[lang = "owned_box"]
pub struct Box<T: ?Sized, A = Global>(Unique<T>, A);

#[repr(C)]
struct RcBox<T: ?Sized> {
strong: UnsafeCell<usize>,
weak: UnsafeCell<usize>,
value: T,
}
pub struct Rc<T: ?Sized, A = Global> {
ptr: NonNull<RcBox<T>>,
phantom: PhantomData<RcBox<T>>,
alloc: A,
}

#[repr(C, align(8))]
struct AtomicUsize(usize);
#[repr(C)]
struct ArcInner<T: ?Sized> {
strong: AtomicUsize,
weak: AtomicUsize,
data: T,
}
pub struct Arc<T: ?Sized, A = Global> {
ptr: NonNull<ArcInner<T>>,
phantom: PhantomData<ArcInner<T>>,
alloc: A,
}
}
#[cfg(not(host))]
use prelude::*;

macro_rules! assert_abi_compatible {
($name:ident, $t1:ty, $t2:ty) => {
mod $name {
Expand All @@ -26,8 +184,13 @@ macro_rules! assert_abi_compatible {
};
}

#[derive(Copy, Clone)]
struct Zst;
impl Copy for Zst {}
impl Clone for Zst {
fn clone(&self) -> Self {
Zst
}
}

#[repr(C)]
struct ReprC1<T: ?Sized>(T);
Expand Down Expand Up @@ -85,8 +248,8 @@ test_abi_compatible!(nonzero_int, NonZeroI32, i32);

// `DispatchFromDyn` relies on ABI compatibility.
// This is interesting since these types are not `repr(transparent)`.
test_abi_compatible!(rc, std::rc::Rc<i32>, *mut i32);
test_abi_compatible!(arc, std::sync::Arc<i32>, *mut i32);
test_abi_compatible!(rc, Rc<i32>, *mut i32);
test_abi_compatible!(arc, Arc<i32>, *mut i32);

// `repr(transparent)` compatibility.
#[repr(transparent)]
Expand Down Expand Up @@ -160,7 +323,7 @@ mod unsized_ {
use super::*;
test_transparent_unsized!(str_, str);
test_transparent_unsized!(slice, [u8]);
test_transparent_unsized!(dyn_trait, dyn std::any::Any);
test_transparent_unsized!(dyn_trait, dyn Any);
}

// RFC 3391 <https://rust-lang.github.io/rfcs/3391-result_ffi_guarantees.html>.
Expand All @@ -185,7 +348,7 @@ test_nonnull!(ref_unsized, &[i32]);
test_nonnull!(mut_unsized, &mut [i32]);
test_nonnull!(fn_, fn());
test_nonnull!(nonnull, NonNull<i32>);
test_nonnull!(nonnull_unsized, NonNull<dyn std::fmt::Debug>);
test_nonnull!(nonnull_unsized, NonNull<dyn Any>);
test_nonnull!(non_zero, NonZeroI32);

fn main() {}
Loading