From fc37633580af9da06ab5e01e595a51f1e7c54cc7 Mon Sep 17 00:00:00 2001 From: Arvind Mukund Date: Sat, 9 Mar 2024 11:56:17 -0800 Subject: [PATCH 1/9] Support Result across FFI when niche optimization can be used Allow allow enums like `Result` to be used across FFI if the T/E can be niche optimized and the non-niche-optimized type is FFI safe. --- compiler/rustc_lint/src/types.rs | 48 +++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index e982842f5363f..001bf27afb9cc 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -1099,6 +1099,32 @@ fn get_nullable_type<'tcx>( }) } +/// A type is niche_optimization_candiate iff: +/// - Is a zero-sized type with alignment 1 (a “1-ZST”). +/// - Has no fields. +/// - Does not have the #[non_exhaustive] attribute. +fn is_niche_optimization_candidate<'tcx>( + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + ty: Ty<'tcx>, +) -> bool { + if !tcx.layout_of(param_env.and(ty)).is_ok_and(|layout| layout.is_1zst()) { + return false; + } + + match ty.kind() { + ty::Adt(ty_def, _) => { + let non_exhaustive = ty_def.is_variant_list_non_exhaustive() + || ty_def.variants().iter().any(|variant| variant.is_field_list_non_exhaustive()); + let contains_no_fields = ty_def.all_fields().next().is_none(); + + !non_exhaustive && contains_no_fields + } + ty::Tuple(tys) => tys.is_empty(), + _ => false, + } +} + /// Check if this enum can be safely exported based on the "nullable pointer optimization". If it /// can, return the type that `ty` can be safely converted to, otherwise return `None`. /// Currently restricted to function pointers, boxes, references, `core::num::NonZero`, @@ -1115,6 +1141,26 @@ pub(crate) fn repr_nullable_ptr<'tcx>( let field_ty = match &ty_def.variants().raw[..] { [var_one, var_two] => match (&var_one.fields.raw[..], &var_two.fields.raw[..]) { ([], [field]) | ([field], []) => field.ty(tcx, args), + ([field1], [field2]) => { + // TODO: We pass all the checks here although individual enum variants has + // checks for FFI safety even when niche optimized which needs to be + // suppressed. for types like `Result, E>`, PhantomData has + // it's own lint for FFI which needs to be suppressed: `composed only of + // `PhantomData``. This is true for other custom types as well `struct + // Example;` which emits `this struct has unspecified layout` and suggests to + // add `#[repr(C)]` and when that is done, linter emits `this struct has no + // fields`, all under the `improper_ctypes_definitions` lint group + let ty1 = field1.ty(tcx, args); + let ty2 = field2.ty(tcx, args); + + if is_niche_optimization_candidate(tcx, param_env, ty1) { + ty2 + } else if is_niche_optimization_candidate(tcx, param_env, ty2) { + ty1 + } else { + return None; + } + } _ => return None, }, _ => return None, @@ -1331,7 +1377,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { // discriminant. if !def.repr().c() && !def.repr().transparent() && def.repr().int.is_none() { - // Special-case types like `Option`. + // Special-case types like `Option` and `Result` if repr_nullable_ptr(self.cx.tcx, self.cx.param_env, ty, self.mode) .is_none() { From b3e6d52e49345db9e59c955b79ca3ea7cf4f7afc Mon Sep 17 00:00:00 2001 From: Arvind Mukund Date: Sat, 9 Mar 2024 12:35:17 -0800 Subject: [PATCH 2/9] We don't need to check for non-exhaustive fields Fields are disallowed so checking the top attribute is enough. --- compiler/rustc_lint/src/types.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 001bf27afb9cc..ae118ffbf4c38 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -1114,8 +1114,7 @@ fn is_niche_optimization_candidate<'tcx>( match ty.kind() { ty::Adt(ty_def, _) => { - let non_exhaustive = ty_def.is_variant_list_non_exhaustive() - || ty_def.variants().iter().any(|variant| variant.is_field_list_non_exhaustive()); + let non_exhaustive = ty_def.is_variant_list_non_exhaustive(); let contains_no_fields = ty_def.all_fields().next().is_none(); !non_exhaustive && contains_no_fields From 08b85a1c5381cfc9c62347996b4b5c0316522b60 Mon Sep 17 00:00:00 2001 From: Arvind Mukund Date: Sat, 9 Mar 2024 14:30:01 -0800 Subject: [PATCH 3/9] Don't lint niche optimized variants in enums --- compiler/rustc_lint/src/types.rs | 33 +++++++++++++------------------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index ae118ffbf4c38..1fd358836a2cf 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -1141,14 +1141,6 @@ pub(crate) fn repr_nullable_ptr<'tcx>( [var_one, var_two] => match (&var_one.fields.raw[..], &var_two.fields.raw[..]) { ([], [field]) | ([field], []) => field.ty(tcx, args), ([field1], [field2]) => { - // TODO: We pass all the checks here although individual enum variants has - // checks for FFI safety even when niche optimized which needs to be - // suppressed. for types like `Result, E>`, PhantomData has - // it's own lint for FFI which needs to be suppressed: `composed only of - // `PhantomData``. This is true for other custom types as well `struct - // Example;` which emits `this struct has unspecified layout` and suggests to - // add `#[repr(C)]` and when that is done, linter emits `this struct has no - // fields`, all under the `improper_ctypes_definitions` lint group let ty1 = field1.ty(tcx, args); let ty2 = field2.ty(tcx, args); @@ -1245,7 +1237,6 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { args: GenericArgsRef<'tcx>, ) -> FfiResult<'tcx> { use FfiResult::*; - let transparent_with_all_zst_fields = if def.repr().transparent() { if let Some(field) = transparent_newtype_field(self.cx.tcx, variant) { // Transparent newtypes have at most one non-ZST field which needs to be checked.. @@ -1372,27 +1363,29 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { return FfiSafe; } + if def.is_variant_list_non_exhaustive() && !def.did().is_local() { + return FfiUnsafe { + ty, + reason: fluent::lint_improper_ctypes_non_exhaustive, + help: None, + }; + } + // Check for a repr() attribute to specify the size of the // discriminant. if !def.repr().c() && !def.repr().transparent() && def.repr().int.is_none() { // Special-case types like `Option` and `Result` - if repr_nullable_ptr(self.cx.tcx, self.cx.param_env, ty, self.mode) - .is_none() + if let Some(ty) = + repr_nullable_ptr(self.cx.tcx, self.cx.param_env, ty, self.mode) { - return FfiUnsafe { - ty, - reason: fluent::lint_improper_ctypes_enum_repr_reason, - help: Some(fluent::lint_improper_ctypes_enum_repr_help), - }; + return self.check_type_for_ffi(cache, ty); } - } - if def.is_variant_list_non_exhaustive() && !def.did().is_local() { return FfiUnsafe { ty, - reason: fluent::lint_improper_ctypes_non_exhaustive, - help: None, + reason: fluent::lint_improper_ctypes_enum_repr_reason, + help: Some(fluent::lint_improper_ctypes_enum_repr_help), }; } From 223d5eb64f492a41801396e34e714a657d020ac6 Mon Sep 17 00:00:00 2001 From: Arvind Mukund Date: Sat, 9 Mar 2024 14:34:08 -0800 Subject: [PATCH 4/9] Add tests Tests both `T` and `E` for niche variant optimization lints --- tests/ui/lint/lint-ctypes-enum.rs | 144 +++++++++++++++----- tests/ui/lint/lint-ctypes-enum.stderr | 183 ++++++++++++++++++++++---- 2 files changed, 270 insertions(+), 57 deletions(-) diff --git a/tests/ui/lint/lint-ctypes-enum.rs b/tests/ui/lint/lint-ctypes-enum.rs index c60290f8553a7..8d60a8dd3171f 100644 --- a/tests/ui/lint/lint-ctypes-enum.rs +++ b/tests/ui/lint/lint-ctypes-enum.rs @@ -55,38 +55,120 @@ union TransparentUnion { struct Rust(T); +struct NoField; + +#[repr(transparent)] +struct Field(()); + +#[non_exhaustive] +enum NonExhaustive {} + extern "C" { - fn zf(x: Z); - fn uf(x: U); //~ ERROR `extern` block uses type `U` - fn bf(x: B); //~ ERROR `extern` block uses type `B` - fn tf(x: T); //~ ERROR `extern` block uses type `T` - fn repr_c(x: ReprC); - fn repr_u8(x: U8); - fn repr_isize(x: Isize); - fn option_ref(x: Option<&'static u8>); - fn option_fn(x: Option); - fn nonnull(x: Option>); - fn unique(x: Option>); - fn nonzero_u8(x: Option>); - fn nonzero_u16(x: Option>); - fn nonzero_u32(x: Option>); - fn nonzero_u64(x: Option>); - fn nonzero_u128(x: Option>); - //~^ ERROR `extern` block uses type `u128` - fn nonzero_usize(x: Option>); - fn nonzero_i8(x: Option>); - fn nonzero_i16(x: Option>); - fn nonzero_i32(x: Option>); - fn nonzero_i64(x: Option>); - fn nonzero_i128(x: Option>); - //~^ ERROR `extern` block uses type `i128` - fn nonzero_isize(x: Option>); - fn transparent_struct(x: Option>>); - fn transparent_enum(x: Option>>); - fn transparent_union(x: Option>>); - //~^ ERROR `extern` block uses type - fn repr_rust(x: Option>>); //~ ERROR `extern` block uses type - fn no_result(x: Result<(), num::NonZero>); //~ ERROR `extern` block uses type + fn zf(x: Z); + fn uf(x: U); //~ ERROR `extern` block uses type `U` + fn bf(x: B); //~ ERROR `extern` block uses type `B` + fn tf(x: T); //~ ERROR `extern` block uses type `T` + fn repr_c(x: ReprC); + fn repr_u8(x: U8); + fn repr_isize(x: Isize); + fn option_ref(x: Option<&'static u8>); + fn option_fn(x: Option); + fn option_nonnull(x: Option>); + fn option_unique(x: Option>); + fn option_nonzero_u8(x: Option>); + fn option_nonzero_u16(x: Option>); + fn option_nonzero_u32(x: Option>); + fn option_nonzero_u64(x: Option>); + fn option_nonzero_u128(x: Option>); + //~^ ERROR `extern` block uses type `u128` + fn option_nonzero_usize(x: Option>); + fn option_nonzero_i8(x: Option>); + fn option_nonzero_i16(x: Option>); + fn option_nonzero_i32(x: Option>); + fn option_nonzero_i64(x: Option>); + fn option_nonzero_i128(x: Option>); + //~^ ERROR `extern` block uses type `i128` + fn option_nonzero_isize(x: Option>); + fn option_transparent_struct(x: Option>>); + fn option_transparent_enum(x: Option>>); + fn option_transparent_union(x: Option>>); + //~^ ERROR `extern` block uses type + fn option_repr_rust(x: Option>>); //~ ERROR `extern` block uses type + + fn result_ref_t(x: Result<&'static u8, ()>); + fn result_fn_t(x: Result); + fn result_nonnull_t(x: Result, ()>); + fn result_unique_t(x: Result, ()>); + fn result_nonzero_u8_t(x: Result, ()>); + fn result_nonzero_u16_t(x: Result, ()>); + fn result_nonzero_u32_t(x: Result, ()>); + fn result_nonzero_u64_t(x: Result, ()>); + fn result_nonzero_u128_t(x: Result, ()>); + //~^ ERROR `extern` block uses type `u128` + fn result_nonzero_usize_t(x: Result, ()>); + fn result_nonzero_i8_t(x: Result, ()>); + fn result_nonzero_i16_t(x: Result, ()>); + fn result_nonzero_i32_t(x: Result, ()>); + fn result_nonzero_i64_t(x: Result, ()>); + fn result_nonzero_i128_t(x: Result, ()>); + //~^ ERROR `extern` block uses type `i128` + fn result_nonzero_isize_t(x: Result, ()>); + fn result_transparent_struct_t(x: Result>, ()>); + fn result_transparent_enum_t(x: Result>, ()>); + fn result_transparent_union_t(x: Result>, ()>); + //~^ ERROR `extern` block uses type + fn result_repr_rust_t(x: Result>, ()>); + //~^ ERROR `extern` block uses type + fn result_phantom_t(x: Result, std::marker::PhantomData<()>>); + fn result_1zst_exhaustive_no_variant_t(x: Result, Z>); + fn result_1zst_exhaustive_single_variant_t(x: Result, U>); + fn result_1zst_exhaustive_multiple_variant_t(x: Result, B>); + //~^ ERROR `extern` block uses type + fn result_1zst_non_exhaustive_no_variant_t(x: Result, NonExhaustive>); + //~^ ERROR `extern` block uses type + fn result_1zst_exhaustive_no_field_t(x: Result, NoField>); + fn result_1zst_exhaustive_single_field_t(x: Result, Field>); + //~^ ERROR `extern` block uses type + fn result_cascading_t(x: Result>, ()>); + //~^ ERROR `extern` block uses type + + fn result_ref_e(x: Result<(), &'static u8>); + fn result_fn_e(x: Result<(), extern "C" fn()>); + fn result_nonnull_e(x: Result<(), std::ptr::NonNull>); + fn result_unique_e(x: Result<(), std::ptr::Unique>); + fn result_nonzero_u8_e(x: Result<(), num::NonZero>); + fn result_nonzero_u16_e(x: Result<(), num::NonZero>); + fn result_nonzero_u32_e(x: Result<(), num::NonZero>); + fn result_nonzero_u64_e(x: Result<(), num::NonZero>); + fn result_nonzero_u128_e(x: Result<(), num::NonZero>); + //~^ ERROR `extern` block uses type `u128` + fn result_nonzero_usize_e(x: Result<(), num::NonZero>); + fn result_nonzero_i8_e(x: Result<(), num::NonZero>); + fn result_nonzero_i16_e(x: Result<(), num::NonZero>); + fn result_nonzero_i32_e(x: Result<(), num::NonZero>); + fn result_nonzero_i64_e(x: Result<(), num::NonZero>); + fn result_nonzero_i128_e(x: Result<(), num::NonZero>); + //~^ ERROR `extern` block uses type `i128` + fn result_nonzero_isize_e(x: Result<(), num::NonZero>); + fn result_transparent_struct_e(x: Result<(), TransparentStruct>>); + fn result_transparent_enum_e(x: Result<(), TransparentEnum>>); + fn result_transparent_union_e(x: Result<(), TransparentUnion>>); + //~^ ERROR `extern` block uses type + fn result_repr_rust_e(x: Result<(), Rust>>); + //~^ ERROR `extern` block uses type + fn result_phantom_e(x: Result, std::marker::PhantomData<()>>); + fn result_1zst_exhaustive_no_variant_e(x: Result>); + fn result_1zst_exhaustive_single_variant_e(x: Result>); + fn result_1zst_exhaustive_multiple_variant_e(x: Result>); + //~^ ERROR `extern` block uses type + fn result_1zst_non_exhaustive_no_variant_e(x: Result>); + //~^ ERROR `extern` block uses type + fn result_1zst_exhaustive_no_field_e(x: Result>); + fn result_1zst_exhaustive_single_field_e(x: Result>); + //~^ ERROR `extern` block uses type + fn result_cascading_e(x: Result<(), Result<(), num::NonZero>>); + //~^ ERROR `extern` block uses type + } pub fn main() {} diff --git a/tests/ui/lint/lint-ctypes-enum.stderr b/tests/ui/lint/lint-ctypes-enum.stderr index 103fda8d40253..c982f040fb6fb 100644 --- a/tests/ui/lint/lint-ctypes-enum.stderr +++ b/tests/ui/lint/lint-ctypes-enum.stderr @@ -1,8 +1,8 @@ error: `extern` block uses type `U`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:60:13 + --> $DIR/lint-ctypes-enum.rs:68:14 | -LL | fn uf(x: U); - | ^ not FFI-safe +LL | fn uf(x: U); + | ^ not FFI-safe | = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum = note: enum has no representation hint @@ -18,10 +18,10 @@ LL | #![deny(improper_ctypes)] | ^^^^^^^^^^^^^^^ error: `extern` block uses type `B`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:61:13 + --> $DIR/lint-ctypes-enum.rs:69:14 | -LL | fn bf(x: B); - | ^ not FFI-safe +LL | fn bf(x: B); + | ^ not FFI-safe | = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum = note: enum has no representation hint @@ -32,10 +32,10 @@ LL | enum B { | ^^^^^^ error: `extern` block uses type `T`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:62:13 + --> $DIR/lint-ctypes-enum.rs:70:14 | -LL | fn tf(x: T); - | ^ not FFI-safe +LL | fn tf(x: T); + | ^ not FFI-safe | = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum = note: enum has no representation hint @@ -46,47 +46,178 @@ LL | enum T { | ^^^^^^ error: `extern` block uses type `u128`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:74:23 + --> $DIR/lint-ctypes-enum.rs:82:31 | -LL | fn nonzero_u128(x: Option>); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe +LL | fn option_nonzero_u128(x: Option>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe | = note: 128-bit integers don't currently have a known stable ABI error: `extern` block uses type `i128`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:81:23 + --> $DIR/lint-ctypes-enum.rs:89:31 | -LL | fn nonzero_i128(x: Option>); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe +LL | fn option_nonzero_i128(x: Option>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe | = note: 128-bit integers don't currently have a known stable ABI error: `extern` block uses type `Option>>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:86:28 + --> $DIR/lint-ctypes-enum.rs:94:36 | -LL | fn transparent_union(x: Option>>); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe +LL | fn option_transparent_union(x: Option>>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe | = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum = note: enum has no representation hint error: `extern` block uses type `Option>>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:88:20 + --> $DIR/lint-ctypes-enum.rs:96:28 | -LL | fn repr_rust(x: Option>>); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe +LL | fn option_repr_rust(x: Option>>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe | = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum = note: enum has no representation hint -error: `extern` block uses type `Result<(), NonZero>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:89:20 +error: `extern` block uses type `u128`, which is not FFI-safe + --> $DIR/lint-ctypes-enum.rs:106:33 + | +LL | fn result_nonzero_u128_t(x: Result, ()>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = note: 128-bit integers don't currently have a known stable ABI + +error: `extern` block uses type `i128`, which is not FFI-safe + --> $DIR/lint-ctypes-enum.rs:113:33 + | +LL | fn result_nonzero_i128_t(x: Result, ()>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = note: 128-bit integers don't currently have a known stable ABI + +error: `extern` block uses type `Result>, ()>`, which is not FFI-safe + --> $DIR/lint-ctypes-enum.rs:118:38 + | +LL | fn result_transparent_union_t(x: Result>, ()>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `Result>, ()>`, which is not FFI-safe + --> $DIR/lint-ctypes-enum.rs:120:30 + | +LL | fn result_repr_rust_t(x: Result>, ()>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `Result, B>`, which is not FFI-safe + --> $DIR/lint-ctypes-enum.rs:125:53 + | +LL | fn result_1zst_exhaustive_multiple_variant_t(x: Result, B>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `Result, NonExhaustive>`, which is not FFI-safe + --> $DIR/lint-ctypes-enum.rs:127:51 + | +LL | fn result_1zst_non_exhaustive_no_variant_t(x: Result, NonExhaustive>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `Result, Field>`, which is not FFI-safe + --> $DIR/lint-ctypes-enum.rs:130:49 + | +LL | fn result_1zst_exhaustive_single_field_t(x: Result, Field>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `Result>, ()>`, which is not FFI-safe + --> $DIR/lint-ctypes-enum.rs:132:30 + | +LL | fn result_cascading_t(x: Result>, ()>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `u128`, which is not FFI-safe + --> $DIR/lint-ctypes-enum.rs:143:33 + | +LL | fn result_nonzero_u128_e(x: Result<(), num::NonZero>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = note: 128-bit integers don't currently have a known stable ABI + +error: `extern` block uses type `i128`, which is not FFI-safe + --> $DIR/lint-ctypes-enum.rs:150:33 + | +LL | fn result_nonzero_i128_e(x: Result<(), num::NonZero>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = note: 128-bit integers don't currently have a known stable ABI + +error: `extern` block uses type `Result<(), TransparentUnion>>`, which is not FFI-safe + --> $DIR/lint-ctypes-enum.rs:155:38 + | +LL | fn result_transparent_union_e(x: Result<(), TransparentUnion>>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `Result<(), Rust>>`, which is not FFI-safe + --> $DIR/lint-ctypes-enum.rs:157:30 + | +LL | fn result_repr_rust_e(x: Result<(), Rust>>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `Result>`, which is not FFI-safe + --> $DIR/lint-ctypes-enum.rs:162:53 + | +LL | fn result_1zst_exhaustive_multiple_variant_e(x: Result>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `Result>`, which is not FFI-safe + --> $DIR/lint-ctypes-enum.rs:164:51 + | +LL | fn result_1zst_non_exhaustive_no_variant_e(x: Result>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `Result>`, which is not FFI-safe + --> $DIR/lint-ctypes-enum.rs:167:49 + | +LL | fn result_1zst_exhaustive_single_field_e(x: Result>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `Result<(), Result<(), NonZero>>`, which is not FFI-safe + --> $DIR/lint-ctypes-enum.rs:169:30 | -LL | fn no_result(x: Result<(), num::NonZero>); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe +LL | fn result_cascading_e(x: Result<(), Result<(), num::NonZero>>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe | = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum = note: enum has no representation hint -error: aborting due to 8 previous errors +error: aborting due to 23 previous errors From 014ddac9c98d827237c1179050e5f96312884254 Mon Sep 17 00:00:00 2001 From: Arvind Mukund Date: Sat, 9 Mar 2024 15:13:29 -0800 Subject: [PATCH 5/9] Disallow single-variant enums Couldn't find documentation supporting that single-variant `#[repr(Rust)]` enums with RHS assigned work as expected with this change. ```rust enum Variants { A = 17, } // Would this be zero sized optimized guaranteed? ``` --- compiler/rustc_lint/src/types.rs | 10 +++--- tests/ui/lint/lint-ctypes-enum.rs | 2 ++ tests/ui/lint/lint-ctypes-enum.stderr | 44 +++++++++++++++++++-------- 3 files changed, 39 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 1fd358836a2cf..d491de7609beb 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -1102,22 +1102,24 @@ fn get_nullable_type<'tcx>( /// A type is niche_optimization_candiate iff: /// - Is a zero-sized type with alignment 1 (a “1-ZST”). /// - Has no fields. -/// - Does not have the #[non_exhaustive] attribute. +/// - Does not have the `#[non_exhaustive]` attribute. fn is_niche_optimization_candidate<'tcx>( tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>, ) -> bool { - if !tcx.layout_of(param_env.and(ty)).is_ok_and(|layout| layout.is_1zst()) { + if tcx.layout_of(param_env.and(ty)).is_ok_and(|layout| !layout.is_1zst()) { return false; } match ty.kind() { ty::Adt(ty_def, _) => { let non_exhaustive = ty_def.is_variant_list_non_exhaustive(); - let contains_no_fields = ty_def.all_fields().next().is_none(); + // Should single-variant enums be allowed? + let empty = (ty_def.is_struct() && ty_def.all_fields().next().is_none()) + || (ty_def.is_enum() && ty_def.variants().is_empty()); - !non_exhaustive && contains_no_fields + !non_exhaustive && empty } ty::Tuple(tys) => tys.is_empty(), _ => false, diff --git a/tests/ui/lint/lint-ctypes-enum.rs b/tests/ui/lint/lint-ctypes-enum.rs index 8d60a8dd3171f..b69ee82f8aeb1 100644 --- a/tests/ui/lint/lint-ctypes-enum.rs +++ b/tests/ui/lint/lint-ctypes-enum.rs @@ -122,6 +122,7 @@ extern "C" { fn result_phantom_t(x: Result, std::marker::PhantomData<()>>); fn result_1zst_exhaustive_no_variant_t(x: Result, Z>); fn result_1zst_exhaustive_single_variant_t(x: Result, U>); + //~^ ERROR `extern` block uses type fn result_1zst_exhaustive_multiple_variant_t(x: Result, B>); //~^ ERROR `extern` block uses type fn result_1zst_non_exhaustive_no_variant_t(x: Result, NonExhaustive>); @@ -159,6 +160,7 @@ extern "C" { fn result_phantom_e(x: Result, std::marker::PhantomData<()>>); fn result_1zst_exhaustive_no_variant_e(x: Result>); fn result_1zst_exhaustive_single_variant_e(x: Result>); + //~^ ERROR `extern` block uses type fn result_1zst_exhaustive_multiple_variant_e(x: Result>); //~^ ERROR `extern` block uses type fn result_1zst_non_exhaustive_no_variant_e(x: Result>); diff --git a/tests/ui/lint/lint-ctypes-enum.stderr b/tests/ui/lint/lint-ctypes-enum.stderr index c982f040fb6fb..ab1eb67c07510 100644 --- a/tests/ui/lint/lint-ctypes-enum.stderr +++ b/tests/ui/lint/lint-ctypes-enum.stderr @@ -113,8 +113,17 @@ LL | fn result_repr_rust_t(x: Result>, ()>); = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum = note: enum has no representation hint +error: `extern` block uses type `Result, U>`, which is not FFI-safe + --> $DIR/lint-ctypes-enum.rs:124:51 + | +LL | fn result_1zst_exhaustive_single_variant_t(x: Result, U>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + error: `extern` block uses type `Result, B>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:125:53 + --> $DIR/lint-ctypes-enum.rs:126:53 | LL | fn result_1zst_exhaustive_multiple_variant_t(x: Result, B>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -123,7 +132,7 @@ LL | fn result_1zst_exhaustive_multiple_variant_t(x: Result = note: enum has no representation hint error: `extern` block uses type `Result, NonExhaustive>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:127:51 + --> $DIR/lint-ctypes-enum.rs:128:51 | LL | fn result_1zst_non_exhaustive_no_variant_t(x: Result, NonExhaustive>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -132,7 +141,7 @@ LL | fn result_1zst_non_exhaustive_no_variant_t(x: Result, = note: enum has no representation hint error: `extern` block uses type `Result, Field>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:130:49 + --> $DIR/lint-ctypes-enum.rs:131:49 | LL | fn result_1zst_exhaustive_single_field_t(x: Result, Field>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -141,7 +150,7 @@ LL | fn result_1zst_exhaustive_single_field_t(x: Result, Fi = note: enum has no representation hint error: `extern` block uses type `Result>, ()>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:132:30 + --> $DIR/lint-ctypes-enum.rs:133:30 | LL | fn result_cascading_t(x: Result>, ()>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -150,7 +159,7 @@ LL | fn result_cascading_t(x: Result>, ()>); = note: enum has no representation hint error: `extern` block uses type `u128`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:143:33 + --> $DIR/lint-ctypes-enum.rs:144:33 | LL | fn result_nonzero_u128_e(x: Result<(), num::NonZero>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -158,7 +167,7 @@ LL | fn result_nonzero_u128_e(x: Result<(), num::NonZero>); = note: 128-bit integers don't currently have a known stable ABI error: `extern` block uses type `i128`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:150:33 + --> $DIR/lint-ctypes-enum.rs:151:33 | LL | fn result_nonzero_i128_e(x: Result<(), num::NonZero>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -166,7 +175,7 @@ LL | fn result_nonzero_i128_e(x: Result<(), num::NonZero>); = note: 128-bit integers don't currently have a known stable ABI error: `extern` block uses type `Result<(), TransparentUnion>>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:155:38 + --> $DIR/lint-ctypes-enum.rs:156:38 | LL | fn result_transparent_union_e(x: Result<(), TransparentUnion>>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -175,7 +184,7 @@ LL | fn result_transparent_union_e(x: Result<(), TransparentUnion>>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:157:30 + --> $DIR/lint-ctypes-enum.rs:158:30 | LL | fn result_repr_rust_e(x: Result<(), Rust>>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -183,8 +192,17 @@ LL | fn result_repr_rust_e(x: Result<(), Rust>>); = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum = note: enum has no representation hint +error: `extern` block uses type `Result>`, which is not FFI-safe + --> $DIR/lint-ctypes-enum.rs:162:51 + | +LL | fn result_1zst_exhaustive_single_variant_e(x: Result>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + error: `extern` block uses type `Result>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:162:53 + --> $DIR/lint-ctypes-enum.rs:164:53 | LL | fn result_1zst_exhaustive_multiple_variant_e(x: Result>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -193,7 +211,7 @@ LL | fn result_1zst_exhaustive_multiple_variant_e(x: Result>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:164:51 + --> $DIR/lint-ctypes-enum.rs:166:51 | LL | fn result_1zst_non_exhaustive_no_variant_e(x: Result>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -202,7 +220,7 @@ LL | fn result_1zst_non_exhaustive_no_variant_e(x: Result>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:167:49 + --> $DIR/lint-ctypes-enum.rs:169:49 | LL | fn result_1zst_exhaustive_single_field_e(x: Result>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -211,7 +229,7 @@ LL | fn result_1zst_exhaustive_single_field_e(x: Result>>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:169:30 + --> $DIR/lint-ctypes-enum.rs:171:30 | LL | fn result_cascading_e(x: Result<(), Result<(), num::NonZero>>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -219,5 +237,5 @@ LL | fn result_cascading_e(x: Result<(), Result<(), num::NonZero>>); = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum = note: enum has no representation hint -error: aborting due to 23 previous errors +error: aborting due to 25 previous errors From b3f6511755228ee3ff2e59c69f575454f6eb3108 Mon Sep 17 00:00:00 2001 From: Arvind Mukund Date: Mon, 18 Mar 2024 19:45:40 -0700 Subject: [PATCH 6/9] Add a test against Result<(), ()> --- tests/ui/lint/lint-ctypes-enum.rs | 3 ++- tests/ui/lint/lint-ctypes-enum.stderr | 11 ++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/tests/ui/lint/lint-ctypes-enum.rs b/tests/ui/lint/lint-ctypes-enum.rs index b69ee82f8aeb1..19af1de95760b 100644 --- a/tests/ui/lint/lint-ctypes-enum.rs +++ b/tests/ui/lint/lint-ctypes-enum.rs @@ -170,7 +170,8 @@ extern "C" { //~^ ERROR `extern` block uses type fn result_cascading_e(x: Result<(), Result<(), num::NonZero>>); //~^ ERROR `extern` block uses type - + fn result_unit_t_e(x: Result<(), ()>); + //~^ ERROR `extern` block uses type } pub fn main() {} diff --git a/tests/ui/lint/lint-ctypes-enum.stderr b/tests/ui/lint/lint-ctypes-enum.stderr index ab1eb67c07510..8d7b28bfb7ddf 100644 --- a/tests/ui/lint/lint-ctypes-enum.stderr +++ b/tests/ui/lint/lint-ctypes-enum.stderr @@ -237,5 +237,14 @@ LL | fn result_cascading_e(x: Result<(), Result<(), num::NonZero>>); = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum = note: enum has no representation hint -error: aborting due to 25 previous errors +error: `extern` block uses type `Result<(), ()>`, which is not FFI-safe + --> $DIR/lint-ctypes-enum.rs:174:27 + | +LL | fn result_unit_t_e(x: Result<(), ()>); + | ^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: aborting due to 26 previous errors From 764f64f0d7e8a51adb05f29bee11909b4f446579 Mon Sep 17 00:00:00 2001 From: Arvind Mukund Date: Mon, 18 Mar 2024 19:47:43 -0700 Subject: [PATCH 7/9] Reword `is_niche_optimization_candidate` doc --- compiler/rustc_lint/src/types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index d491de7609beb..5db5f4ab9eedc 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -1099,7 +1099,7 @@ fn get_nullable_type<'tcx>( }) } -/// A type is niche_optimization_candiate iff: +/// A type is niche-optimization candidate iff: /// - Is a zero-sized type with alignment 1 (a “1-ZST”). /// - Has no fields. /// - Does not have the `#[non_exhaustive]` attribute. From 437ca26de5d2fe25a37f88956b6225344084fd1d Mon Sep 17 00:00:00 2001 From: Arvind Mukund Date: Mon, 18 Mar 2024 19:48:40 -0700 Subject: [PATCH 8/9] Remove comment out of RFC's scope --- compiler/rustc_lint/src/types.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 5db5f4ab9eedc..09fdceb156cf6 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -1115,7 +1115,6 @@ fn is_niche_optimization_candidate<'tcx>( match ty.kind() { ty::Adt(ty_def, _) => { let non_exhaustive = ty_def.is_variant_list_non_exhaustive(); - // Should single-variant enums be allowed? let empty = (ty_def.is_struct() && ty_def.all_fields().next().is_none()) || (ty_def.is_enum() && ty_def.variants().is_empty()); From ed532cc186a651a3e4b848ffbef8c080018f1732 Mon Sep 17 00:00:00 2001 From: Arvind Mukund Date: Mon, 18 Mar 2024 20:31:48 -0700 Subject: [PATCH 9/9] Put the RFC behind a feature gate `result_ffi_guarantees` --- compiler/rustc_feature/src/unstable.rs | 3 + compiler/rustc_lint/src/types.rs | 4 + compiler/rustc_span/src/symbol.rs | 1 + .../result-ffi-guarantees.md | 14 + .../feature-gate-result_ffi_guarantees.rs | 99 +++++ .../feature-gate-result_ffi_guarantees.stderr | 349 ++++++++++++++++++ tests/ui/lint/lint-ctypes-enum.rs | 1 + tests/ui/lint/lint-ctypes-enum.stderr | 56 +-- 8 files changed, 499 insertions(+), 28 deletions(-) create mode 100644 src/doc/unstable-book/src/language-features/result-ffi-guarantees.md create mode 100644 tests/ui/feature-gates/feature-gate-result_ffi_guarantees.rs create mode 100644 tests/ui/feature-gates/feature-gate-result_ffi_guarantees.stderr diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 9641d336c3f3c..eec0d0eb5298a 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -585,6 +585,9 @@ declare_features! ( (incomplete, repr128, "1.16.0", Some(56071)), /// Allows `repr(simd)` and importing the various simd intrinsics. (unstable, repr_simd, "1.4.0", Some(27731)), + /// Allows enums like Result to be used across FFI, if T's niche value can + /// be used to describe E or vise-versa. + (unstable, result_ffi_guarantees, "CURRENT_RUSTC_VERSION", Some(110503)), /// Allows bounding the return type of AFIT/RPITIT. (incomplete, return_type_notation, "1.70.0", Some(109417)), /// Allows `extern "rust-cold"`. diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 09fdceb156cf6..b3fd03d3f78bf 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -1142,6 +1142,10 @@ pub(crate) fn repr_nullable_ptr<'tcx>( [var_one, var_two] => match (&var_one.fields.raw[..], &var_two.fields.raw[..]) { ([], [field]) | ([field], []) => field.ty(tcx, args), ([field1], [field2]) => { + if !tcx.features().result_ffi_guarantees { + return None; + } + let ty1 = field1.ty(tcx, args); let ty2 = field2.ty(tcx, args); diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 8abf42e2c1392..ff9b2a413c952 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1509,6 +1509,7 @@ symbols! { require, residual, result, + result_ffi_guarantees, resume, return_position_impl_trait_in_trait, return_type_notation, diff --git a/src/doc/unstable-book/src/language-features/result-ffi-guarantees.md b/src/doc/unstable-book/src/language-features/result-ffi-guarantees.md new file mode 100644 index 0000000000000..dc9c196524ed4 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/result-ffi-guarantees.md @@ -0,0 +1,14 @@ +# `result_ffi_guarantees` + +The tracking issue for this feature is: [#110503] + +[#110503]: https://github.com/rust-lang/rust/issues/110503 + +------------------------ + +This feature adds the possibility of using `Result` in FFI if T's niche +value can be used to describe E or vise-versa. + +See [RFC 3391] for more information. + +[RFC 3391]: https://github.com/rust-lang/rfcs/blob/master/text/3391-result_ffi_guarantees.md diff --git a/tests/ui/feature-gates/feature-gate-result_ffi_guarantees.rs b/tests/ui/feature-gates/feature-gate-result_ffi_guarantees.rs new file mode 100644 index 0000000000000..dda317aecc3c3 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-result_ffi_guarantees.rs @@ -0,0 +1,99 @@ +#![allow(dead_code)] +#![deny(improper_ctypes)] +#![feature(ptr_internals)] + +use std::num; + +enum Z {} + +#[repr(transparent)] +struct TransparentStruct(T, std::marker::PhantomData); + +#[repr(transparent)] +enum TransparentEnum { + Variant(T, std::marker::PhantomData), +} + +struct NoField; + +extern "C" { + fn result_ref_t(x: Result<&'static u8, ()>); + //~^ ERROR `extern` block uses type `Result + fn result_fn_t(x: Result); + //~^ ERROR `extern` block uses type `Result + fn result_nonnull_t(x: Result, ()>); + //~^ ERROR `extern` block uses type `Result + fn result_unique_t(x: Result, ()>); + //~^ ERROR `extern` block uses type `Result + fn result_nonzero_u8_t(x: Result, ()>); + //~^ ERROR `extern` block uses type `Result + fn result_nonzero_u16_t(x: Result, ()>); + //~^ ERROR `extern` block uses type `Result + fn result_nonzero_u32_t(x: Result, ()>); + //~^ ERROR `extern` block uses type `Result + fn result_nonzero_u64_t(x: Result, ()>); + //~^ ERROR `extern` block uses type `Result + fn result_nonzero_usize_t(x: Result, ()>); + //~^ ERROR `extern` block uses type `Result + fn result_nonzero_i8_t(x: Result, ()>); + //~^ ERROR `extern` block uses type `Result + fn result_nonzero_i16_t(x: Result, ()>); + //~^ ERROR `extern` block uses type `Result + fn result_nonzero_i32_t(x: Result, ()>); + //~^ ERROR `extern` block uses type `Result + fn result_nonzero_i64_t(x: Result, ()>); + //~^ ERROR `extern` block uses type `Result + fn result_nonzero_isize_t(x: Result, ()>); + //~^ ERROR `extern` block uses type `Result + fn result_transparent_struct_t(x: Result>, ()>); + //~^ ERROR `extern` block uses type `Result + fn result_transparent_enum_t(x: Result>, ()>); + //~^ ERROR `extern` block uses type `Result + fn result_phantom_t(x: Result, std::marker::PhantomData<()>>); + //~^ ERROR `extern` block uses type `Result + fn result_1zst_exhaustive_no_variant_t(x: Result, Z>); + //~^ ERROR `extern` block uses type `Result + fn result_1zst_exhaustive_no_field_t(x: Result, NoField>); + //~^ ERROR `extern` block uses type `Result + + fn result_ref_e(x: Result<(), &'static u8>); + //~^ ERROR `extern` block uses type `Result + fn result_fn_e(x: Result<(), extern "C" fn()>); + //~^ ERROR `extern` block uses type `Result + fn result_nonnull_e(x: Result<(), std::ptr::NonNull>); + //~^ ERROR `extern` block uses type `Result + fn result_unique_e(x: Result<(), std::ptr::Unique>); + //~^ ERROR `extern` block uses type `Result + fn result_nonzero_u8_e(x: Result<(), num::NonZero>); + //~^ ERROR `extern` block uses type `Result + fn result_nonzero_u16_e(x: Result<(), num::NonZero>); + //~^ ERROR `extern` block uses type `Result + fn result_nonzero_u32_e(x: Result<(), num::NonZero>); + //~^ ERROR `extern` block uses type `Result + fn result_nonzero_u64_e(x: Result<(), num::NonZero>); + //~^ ERROR `extern` block uses type `Result + fn result_nonzero_usize_e(x: Result<(), num::NonZero>); + //~^ ERROR `extern` block uses type `Result + fn result_nonzero_i8_e(x: Result<(), num::NonZero>); + //~^ ERROR `extern` block uses type `Result + fn result_nonzero_i16_e(x: Result<(), num::NonZero>); + //~^ ERROR `extern` block uses type `Result + fn result_nonzero_i32_e(x: Result<(), num::NonZero>); + //~^ ERROR `extern` block uses type `Result + fn result_nonzero_i64_e(x: Result<(), num::NonZero>); + //~^ ERROR `extern` block uses type `Result + fn result_nonzero_isize_e(x: Result<(), num::NonZero>); + //~^ ERROR `extern` block uses type `Result + fn result_transparent_struct_e(x: Result<(), TransparentStruct>>); + //~^ ERROR `extern` block uses type `Result + fn result_transparent_enum_e(x: Result<(), TransparentEnum>>); + //~^ ERROR `extern` block uses type `Result + fn result_phantom_e(x: Result, std::marker::PhantomData<()>>); + //~^ ERROR `extern` block uses type `Result + fn result_1zst_exhaustive_no_variant_e(x: Result>); + //~^ ERROR `extern` block uses type `Result + fn result_1zst_exhaustive_no_field_e(x: Result>); + //~^ ERROR `extern` block uses type `Result +} + +pub fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-result_ffi_guarantees.stderr b/tests/ui/feature-gates/feature-gate-result_ffi_guarantees.stderr new file mode 100644 index 0000000000000..94416eb99c878 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-result_ffi_guarantees.stderr @@ -0,0 +1,349 @@ +error: `extern` block uses type `Result<&u8, ()>`, which is not FFI-safe + --> $DIR/feature-gate-result_ffi_guarantees.rs:20:24 + | +LL | fn result_ref_t(x: Result<&'static u8, ()>); + | ^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint +note: the lint level is defined here + --> $DIR/feature-gate-result_ffi_guarantees.rs:2:9 + | +LL | #![deny(improper_ctypes)] + | ^^^^^^^^^^^^^^^ + +error: `extern` block uses type `Result`, which is not FFI-safe + --> $DIR/feature-gate-result_ffi_guarantees.rs:22:23 + | +LL | fn result_fn_t(x: Result); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `Result, ()>`, which is not FFI-safe + --> $DIR/feature-gate-result_ffi_guarantees.rs:24:28 + | +LL | fn result_nonnull_t(x: Result, ()>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `Result, ()>`, which is not FFI-safe + --> $DIR/feature-gate-result_ffi_guarantees.rs:26:27 + | +LL | fn result_unique_t(x: Result, ()>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `Result, ()>`, which is not FFI-safe + --> $DIR/feature-gate-result_ffi_guarantees.rs:28:31 + | +LL | fn result_nonzero_u8_t(x: Result, ()>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `Result, ()>`, which is not FFI-safe + --> $DIR/feature-gate-result_ffi_guarantees.rs:30:32 + | +LL | fn result_nonzero_u16_t(x: Result, ()>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `Result, ()>`, which is not FFI-safe + --> $DIR/feature-gate-result_ffi_guarantees.rs:32:32 + | +LL | fn result_nonzero_u32_t(x: Result, ()>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `Result, ()>`, which is not FFI-safe + --> $DIR/feature-gate-result_ffi_guarantees.rs:34:32 + | +LL | fn result_nonzero_u64_t(x: Result, ()>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `Result, ()>`, which is not FFI-safe + --> $DIR/feature-gate-result_ffi_guarantees.rs:36:34 + | +LL | fn result_nonzero_usize_t(x: Result, ()>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `Result, ()>`, which is not FFI-safe + --> $DIR/feature-gate-result_ffi_guarantees.rs:38:31 + | +LL | fn result_nonzero_i8_t(x: Result, ()>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `Result, ()>`, which is not FFI-safe + --> $DIR/feature-gate-result_ffi_guarantees.rs:40:32 + | +LL | fn result_nonzero_i16_t(x: Result, ()>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `Result, ()>`, which is not FFI-safe + --> $DIR/feature-gate-result_ffi_guarantees.rs:42:32 + | +LL | fn result_nonzero_i32_t(x: Result, ()>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `Result, ()>`, which is not FFI-safe + --> $DIR/feature-gate-result_ffi_guarantees.rs:44:32 + | +LL | fn result_nonzero_i64_t(x: Result, ()>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `Result, ()>`, which is not FFI-safe + --> $DIR/feature-gate-result_ffi_guarantees.rs:46:34 + | +LL | fn result_nonzero_isize_t(x: Result, ()>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `Result>, ()>`, which is not FFI-safe + --> $DIR/feature-gate-result_ffi_guarantees.rs:48:39 + | +LL | fn result_transparent_struct_t(x: Result>, ()>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `Result>, ()>`, which is not FFI-safe + --> $DIR/feature-gate-result_ffi_guarantees.rs:50:37 + | +LL | fn result_transparent_enum_t(x: Result>, ()>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `Result, PhantomData<()>>`, which is not FFI-safe + --> $DIR/feature-gate-result_ffi_guarantees.rs:52:28 + | +LL | fn result_phantom_t(x: Result, std::marker::PhantomData<()>>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `Result, Z>`, which is not FFI-safe + --> $DIR/feature-gate-result_ffi_guarantees.rs:54:47 + | +LL | fn result_1zst_exhaustive_no_variant_t(x: Result, Z>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `Result, NoField>`, which is not FFI-safe + --> $DIR/feature-gate-result_ffi_guarantees.rs:56:45 + | +LL | fn result_1zst_exhaustive_no_field_t(x: Result, NoField>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `Result<(), &u8>`, which is not FFI-safe + --> $DIR/feature-gate-result_ffi_guarantees.rs:59:24 + | +LL | fn result_ref_e(x: Result<(), &'static u8>); + | ^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `Result<(), extern "C" fn()>`, which is not FFI-safe + --> $DIR/feature-gate-result_ffi_guarantees.rs:61:23 + | +LL | fn result_fn_e(x: Result<(), extern "C" fn()>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `Result<(), NonNull>`, which is not FFI-safe + --> $DIR/feature-gate-result_ffi_guarantees.rs:63:28 + | +LL | fn result_nonnull_e(x: Result<(), std::ptr::NonNull>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `Result<(), Unique>`, which is not FFI-safe + --> $DIR/feature-gate-result_ffi_guarantees.rs:65:27 + | +LL | fn result_unique_e(x: Result<(), std::ptr::Unique>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `Result<(), NonZero>`, which is not FFI-safe + --> $DIR/feature-gate-result_ffi_guarantees.rs:67:31 + | +LL | fn result_nonzero_u8_e(x: Result<(), num::NonZero>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `Result<(), NonZero>`, which is not FFI-safe + --> $DIR/feature-gate-result_ffi_guarantees.rs:69:32 + | +LL | fn result_nonzero_u16_e(x: Result<(), num::NonZero>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `Result<(), NonZero>`, which is not FFI-safe + --> $DIR/feature-gate-result_ffi_guarantees.rs:71:32 + | +LL | fn result_nonzero_u32_e(x: Result<(), num::NonZero>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `Result<(), NonZero>`, which is not FFI-safe + --> $DIR/feature-gate-result_ffi_guarantees.rs:73:32 + | +LL | fn result_nonzero_u64_e(x: Result<(), num::NonZero>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `Result<(), NonZero>`, which is not FFI-safe + --> $DIR/feature-gate-result_ffi_guarantees.rs:75:34 + | +LL | fn result_nonzero_usize_e(x: Result<(), num::NonZero>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `Result<(), NonZero>`, which is not FFI-safe + --> $DIR/feature-gate-result_ffi_guarantees.rs:77:31 + | +LL | fn result_nonzero_i8_e(x: Result<(), num::NonZero>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `Result<(), NonZero>`, which is not FFI-safe + --> $DIR/feature-gate-result_ffi_guarantees.rs:79:32 + | +LL | fn result_nonzero_i16_e(x: Result<(), num::NonZero>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `Result<(), NonZero>`, which is not FFI-safe + --> $DIR/feature-gate-result_ffi_guarantees.rs:81:32 + | +LL | fn result_nonzero_i32_e(x: Result<(), num::NonZero>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `Result<(), NonZero>`, which is not FFI-safe + --> $DIR/feature-gate-result_ffi_guarantees.rs:83:32 + | +LL | fn result_nonzero_i64_e(x: Result<(), num::NonZero>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `Result<(), NonZero>`, which is not FFI-safe + --> $DIR/feature-gate-result_ffi_guarantees.rs:85:34 + | +LL | fn result_nonzero_isize_e(x: Result<(), num::NonZero>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `Result<(), TransparentStruct>>`, which is not FFI-safe + --> $DIR/feature-gate-result_ffi_guarantees.rs:87:39 + | +LL | fn result_transparent_struct_e(x: Result<(), TransparentStruct>>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `Result<(), TransparentEnum>>`, which is not FFI-safe + --> $DIR/feature-gate-result_ffi_guarantees.rs:89:37 + | +LL | fn result_transparent_enum_e(x: Result<(), TransparentEnum>>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `Result, PhantomData<()>>`, which is not FFI-safe + --> $DIR/feature-gate-result_ffi_guarantees.rs:91:28 + | +LL | fn result_phantom_e(x: Result, std::marker::PhantomData<()>>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `Result>`, which is not FFI-safe + --> $DIR/feature-gate-result_ffi_guarantees.rs:93:47 + | +LL | fn result_1zst_exhaustive_no_variant_e(x: Result>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `Result>`, which is not FFI-safe + --> $DIR/feature-gate-result_ffi_guarantees.rs:95:45 + | +LL | fn result_1zst_exhaustive_no_field_e(x: Result>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: aborting due to 38 previous errors + diff --git a/tests/ui/lint/lint-ctypes-enum.rs b/tests/ui/lint/lint-ctypes-enum.rs index 19af1de95760b..cb8e9e8067513 100644 --- a/tests/ui/lint/lint-ctypes-enum.rs +++ b/tests/ui/lint/lint-ctypes-enum.rs @@ -2,6 +2,7 @@ #![deny(improper_ctypes)] #![feature(ptr_internals)] #![feature(transparent_unions)] +#![feature(result_ffi_guarantees)] use std::num; diff --git a/tests/ui/lint/lint-ctypes-enum.stderr b/tests/ui/lint/lint-ctypes-enum.stderr index 8d7b28bfb7ddf..bba5b09b69cc9 100644 --- a/tests/ui/lint/lint-ctypes-enum.stderr +++ b/tests/ui/lint/lint-ctypes-enum.stderr @@ -1,5 +1,5 @@ error: `extern` block uses type `U`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:68:14 + --> $DIR/lint-ctypes-enum.rs:69:14 | LL | fn uf(x: U); | ^ not FFI-safe @@ -7,7 +7,7 @@ LL | fn uf(x: U); = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum = note: enum has no representation hint note: the type is defined here - --> $DIR/lint-ctypes-enum.rs:9:1 + --> $DIR/lint-ctypes-enum.rs:10:1 | LL | enum U { | ^^^^^^ @@ -18,7 +18,7 @@ LL | #![deny(improper_ctypes)] | ^^^^^^^^^^^^^^^ error: `extern` block uses type `B`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:69:14 + --> $DIR/lint-ctypes-enum.rs:70:14 | LL | fn bf(x: B); | ^ not FFI-safe @@ -26,13 +26,13 @@ LL | fn bf(x: B); = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum = note: enum has no representation hint note: the type is defined here - --> $DIR/lint-ctypes-enum.rs:12:1 + --> $DIR/lint-ctypes-enum.rs:13:1 | LL | enum B { | ^^^^^^ error: `extern` block uses type `T`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:70:14 + --> $DIR/lint-ctypes-enum.rs:71:14 | LL | fn tf(x: T); | ^ not FFI-safe @@ -40,13 +40,13 @@ LL | fn tf(x: T); = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum = note: enum has no representation hint note: the type is defined here - --> $DIR/lint-ctypes-enum.rs:16:1 + --> $DIR/lint-ctypes-enum.rs:17:1 | LL | enum T { | ^^^^^^ error: `extern` block uses type `u128`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:82:31 + --> $DIR/lint-ctypes-enum.rs:83:31 | LL | fn option_nonzero_u128(x: Option>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -54,7 +54,7 @@ LL | fn option_nonzero_u128(x: Option>); = note: 128-bit integers don't currently have a known stable ABI error: `extern` block uses type `i128`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:89:31 + --> $DIR/lint-ctypes-enum.rs:90:31 | LL | fn option_nonzero_i128(x: Option>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -62,7 +62,7 @@ LL | fn option_nonzero_i128(x: Option>); = note: 128-bit integers don't currently have a known stable ABI error: `extern` block uses type `Option>>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:94:36 + --> $DIR/lint-ctypes-enum.rs:95:36 | LL | fn option_transparent_union(x: Option>>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -71,7 +71,7 @@ LL | fn option_transparent_union(x: Option = note: enum has no representation hint error: `extern` block uses type `Option>>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:96:28 + --> $DIR/lint-ctypes-enum.rs:97:28 | LL | fn option_repr_rust(x: Option>>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -80,7 +80,7 @@ LL | fn option_repr_rust(x: Option>>); = note: enum has no representation hint error: `extern` block uses type `u128`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:106:33 + --> $DIR/lint-ctypes-enum.rs:107:33 | LL | fn result_nonzero_u128_t(x: Result, ()>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -88,7 +88,7 @@ LL | fn result_nonzero_u128_t(x: Result, ()>); = note: 128-bit integers don't currently have a known stable ABI error: `extern` block uses type `i128`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:113:33 + --> $DIR/lint-ctypes-enum.rs:114:33 | LL | fn result_nonzero_i128_t(x: Result, ()>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -96,7 +96,7 @@ LL | fn result_nonzero_i128_t(x: Result, ()>); = note: 128-bit integers don't currently have a known stable ABI error: `extern` block uses type `Result>, ()>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:118:38 + --> $DIR/lint-ctypes-enum.rs:119:38 | LL | fn result_transparent_union_t(x: Result>, ()>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -105,7 +105,7 @@ LL | fn result_transparent_union_t(x: Result>, ()>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:120:30 + --> $DIR/lint-ctypes-enum.rs:121:30 | LL | fn result_repr_rust_t(x: Result>, ()>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -114,7 +114,7 @@ LL | fn result_repr_rust_t(x: Result>, ()>); = note: enum has no representation hint error: `extern` block uses type `Result, U>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:124:51 + --> $DIR/lint-ctypes-enum.rs:125:51 | LL | fn result_1zst_exhaustive_single_variant_t(x: Result, U>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -123,7 +123,7 @@ LL | fn result_1zst_exhaustive_single_variant_t(x: Result, = note: enum has no representation hint error: `extern` block uses type `Result, B>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:126:53 + --> $DIR/lint-ctypes-enum.rs:127:53 | LL | fn result_1zst_exhaustive_multiple_variant_t(x: Result, B>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -132,7 +132,7 @@ LL | fn result_1zst_exhaustive_multiple_variant_t(x: Result = note: enum has no representation hint error: `extern` block uses type `Result, NonExhaustive>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:128:51 + --> $DIR/lint-ctypes-enum.rs:129:51 | LL | fn result_1zst_non_exhaustive_no_variant_t(x: Result, NonExhaustive>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -141,7 +141,7 @@ LL | fn result_1zst_non_exhaustive_no_variant_t(x: Result, = note: enum has no representation hint error: `extern` block uses type `Result, Field>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:131:49 + --> $DIR/lint-ctypes-enum.rs:132:49 | LL | fn result_1zst_exhaustive_single_field_t(x: Result, Field>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -150,7 +150,7 @@ LL | fn result_1zst_exhaustive_single_field_t(x: Result, Fi = note: enum has no representation hint error: `extern` block uses type `Result>, ()>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:133:30 + --> $DIR/lint-ctypes-enum.rs:134:30 | LL | fn result_cascading_t(x: Result>, ()>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -159,7 +159,7 @@ LL | fn result_cascading_t(x: Result>, ()>); = note: enum has no representation hint error: `extern` block uses type `u128`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:144:33 + --> $DIR/lint-ctypes-enum.rs:145:33 | LL | fn result_nonzero_u128_e(x: Result<(), num::NonZero>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -167,7 +167,7 @@ LL | fn result_nonzero_u128_e(x: Result<(), num::NonZero>); = note: 128-bit integers don't currently have a known stable ABI error: `extern` block uses type `i128`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:151:33 + --> $DIR/lint-ctypes-enum.rs:152:33 | LL | fn result_nonzero_i128_e(x: Result<(), num::NonZero>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -175,7 +175,7 @@ LL | fn result_nonzero_i128_e(x: Result<(), num::NonZero>); = note: 128-bit integers don't currently have a known stable ABI error: `extern` block uses type `Result<(), TransparentUnion>>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:156:38 + --> $DIR/lint-ctypes-enum.rs:157:38 | LL | fn result_transparent_union_e(x: Result<(), TransparentUnion>>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -184,7 +184,7 @@ LL | fn result_transparent_union_e(x: Result<(), TransparentUnion>>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:158:30 + --> $DIR/lint-ctypes-enum.rs:159:30 | LL | fn result_repr_rust_e(x: Result<(), Rust>>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -193,7 +193,7 @@ LL | fn result_repr_rust_e(x: Result<(), Rust>>); = note: enum has no representation hint error: `extern` block uses type `Result>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:162:51 + --> $DIR/lint-ctypes-enum.rs:163:51 | LL | fn result_1zst_exhaustive_single_variant_e(x: Result>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -202,7 +202,7 @@ LL | fn result_1zst_exhaustive_single_variant_e(x: Result>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:164:53 + --> $DIR/lint-ctypes-enum.rs:165:53 | LL | fn result_1zst_exhaustive_multiple_variant_e(x: Result>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -211,7 +211,7 @@ LL | fn result_1zst_exhaustive_multiple_variant_e(x: Result>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:166:51 + --> $DIR/lint-ctypes-enum.rs:167:51 | LL | fn result_1zst_non_exhaustive_no_variant_e(x: Result>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -220,7 +220,7 @@ LL | fn result_1zst_non_exhaustive_no_variant_e(x: Result>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:169:49 + --> $DIR/lint-ctypes-enum.rs:170:49 | LL | fn result_1zst_exhaustive_single_field_e(x: Result>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -229,7 +229,7 @@ LL | fn result_1zst_exhaustive_single_field_e(x: Result>>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:171:30 + --> $DIR/lint-ctypes-enum.rs:172:30 | LL | fn result_cascading_e(x: Result<(), Result<(), num::NonZero>>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe