diff --git a/tests/ui/rfcs/rfc-3391-result-ffi-guarantees.rs b/tests/ui/rfcs/rfc-3391-result-ffi-guarantees.rs index dea9f60c7e13b..c5ade67cadda2 100644 --- a/tests/ui/rfcs/rfc-3391-result-ffi-guarantees.rs +++ b/tests/ui/rfcs/rfc-3391-result-ffi-guarantees.rs @@ -1,4 +1,27 @@ //@ build-pass +/*! + +The guarantees in RFC 3391 were strengthened as a result of the 2024 Oct 09 T-lang meeting[^1] +following the precedent of T-lang's guaranteeing[^2] ABI compatibility for "Option-like" enums[^2]. +We now guarantee ABI compatibility for enums that conform to these rules described by scottmcm: + +* The enum `E` has exactly two variants. +* One variant has exactly one field, of type `T`. +* `T` is a `rustc_nonnull_optimization_guaranteed` type. +* All fields of the other variant are 1-ZSTs. + +Where "all" fields includes "there aren't any fields, so they're vacuously all 1-ZSTs". + +Note: "1-ZST" means a type of size 0 and alignment 1. + +The reason alignment of the zero-sized type matters is it can affect the alignment of the enum, +which also will affect its size if the enum has a non-zero size. + +[^1]: +[^2]: + +*/ + #![allow(dead_code)] #![deny(improper_ctypes)] #![feature(ptr_internals)] @@ -59,4 +82,52 @@ extern "C" { fn result_1zst_exhaustive_no_field_e(x: Result>); } +// Custom "Result-like" enum for testing custom "Option-like" types are also accepted, +enum Either { + Left(L), + Right(R), +} + +extern "C" { + fn either_ref_t(x: Either<&'static u8, ()>); + fn either_fn_t(x: Either); + fn either_nonnull_t(x: Either, ()>); + fn either_unique_t(x: Either, ()>); + fn either_nonzero_u8_t(x: Either, ()>); + fn either_nonzero_u16_t(x: Either, ()>); + fn either_nonzero_u32_t(x: Either, ()>); + fn either_nonzero_u64_t(x: Either, ()>); + fn either_nonzero_usize_t(x: Either, ()>); + fn either_nonzero_i8_t(x: Either, ()>); + fn either_nonzero_i16_t(x: Either, ()>); + fn either_nonzero_i32_t(x: Either, ()>); + fn either_nonzero_i64_t(x: Either, ()>); + fn either_nonzero_isize_t(x: Either, ()>); + fn either_transparent_struct_t(x: Either>, ()>); + fn either_transparent_enum_t(x: Either>, ()>); + fn either_phantom_t(x: Either, std::marker::PhantomData<()>>); + fn either_1zst_exhaustive_no_variant_t(x: Either, Z>); + fn either_1zst_exhaustive_no_field_t(x: Either, NoField>); + + fn either_ref_e(x: Either<(), &'static u8>); + fn either_fn_e(x: Either<(), extern "C" fn()>); + fn either_nonnull_e(x: Either<(), std::ptr::NonNull>); + fn either_unique_e(x: Either<(), std::ptr::Unique>); + fn either_nonzero_u8_e(x: Either<(), num::NonZero>); + fn either_nonzero_u16_e(x: Either<(), num::NonZero>); + fn either_nonzero_u32_e(x: Either<(), num::NonZero>); + fn either_nonzero_u64_e(x: Either<(), num::NonZero>); + fn either_nonzero_usize_e(x: Either<(), num::NonZero>); + fn either_nonzero_i8_e(x: Either<(), num::NonZero>); + fn either_nonzero_i16_e(x: Either<(), num::NonZero>); + fn either_nonzero_i32_e(x: Either<(), num::NonZero>); + fn either_nonzero_i64_e(x: Either<(), num::NonZero>); + fn either_nonzero_isize_e(x: Either<(), num::NonZero>); + fn either_transparent_struct_e(x: Either<(), TransparentStruct>>); + fn either_transparent_enum_e(x: Either<(), TransparentEnum>>); + fn either_phantom_e(x: Either, std::marker::PhantomData<()>>); + fn either_1zst_exhaustive_no_variant_e(x: Either>); + fn either_1zst_exhaustive_no_field_e(x: Either>); +} + pub fn main() {}