diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 1fd358836a2..d491de7609b 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 8d60a8dd317..b69ee82f8ae 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 c982f040fb6..ab1eb67c075 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