diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 4c910d25c30a8..da080b1c7be85 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -12,9 +12,7 @@ use rustc_hir::def::{CtorKind, DefKind}; use rustc_hir::{LangItem, Node, attrs, find_attr, intravisit}; use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt}; use rustc_infer::traits::{Obligation, ObligationCauseCode, WellFormedLoc}; -use rustc_lint_defs::builtin::{ - REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS, UNSUPPORTED_CALLING_CONVENTIONS, -}; +use rustc_lint_defs::builtin::{REPR_TRANSPARENT_NON_ZST_FIELDS, UNSUPPORTED_CALLING_CONVENTIONS}; use rustc_middle::hir::nested_filter; use rustc_middle::middle::resolve_bound_vars::ResolvedArg; use rustc_middle::middle::stability::EvalResult; @@ -1511,8 +1509,25 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>) } let typing_env = ty::TypingEnv::non_body_analysis(tcx, adt.did()); - // For each field, figure out if it's known to have "trivial" layout (i.e., is a 1-ZST), with - // "known" respecting #[non_exhaustive] attributes. + // For each field, figure out if it has "trivial" layout (i.e., is a 1-ZST). + // Even some 1-ZST fields are not allowed though, if they have `non_exhaustive` or private + // fields or `repr(C)` or uninhabited. We call those fields "unsuited". + struct FieldInfo<'tcx> { + span: Span, + trivial: bool, + unsuited: Option>, + } + struct UnsuitedInfo<'tcx> { + /// The source of the problem, a type that is found somewhere within the field type. + ty: Ty<'tcx>, + reason: UnsuitedReason, + } + enum UnsuitedReason { + NonExhaustive, + PrivateField, + ReprC, + } + let field_infos = adt.all_fields().map(|field| { let ty = field.ty(tcx, GenericArgs::identity_for_item(tcx, field.did)); let layout = tcx.layout_of(typing_env.as_query_input(ty)); @@ -1520,22 +1535,20 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>) let span = tcx.hir_span_if_local(field.did).unwrap(); let trivial = layout.is_ok_and(|layout| layout.is_1zst()); if !trivial { - return (span, trivial, None); + // No need to even compute `unsuited`. + return FieldInfo { span, trivial, unsuited: None }; } - // Even some 1-ZST fields are not allowed though, if they have `non_exhaustive`. - fn check_non_exhaustive<'tcx>( + fn check_unsuited<'tcx>( tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>, - t: Ty<'tcx>, - ) -> ControlFlow<(&'static str, DefId, GenericArgsRef<'tcx>, bool)> { + ty: Ty<'tcx>, + ) -> ControlFlow> { // We can encounter projections during traversal, so ensure the type is normalized. - let t = tcx.try_normalize_erasing_regions(typing_env, t).unwrap_or(t); - match t.kind() { - ty::Tuple(list) => { - list.iter().try_for_each(|t| check_non_exhaustive(tcx, typing_env, t)) - } - ty::Array(ty, _) => check_non_exhaustive(tcx, typing_env, *ty), + let ty = tcx.try_normalize_erasing_regions(typing_env, ty).unwrap_or(ty); + match ty.kind() { + ty::Tuple(list) => list.iter().try_for_each(|t| check_unsuited(tcx, typing_env, t)), + ty::Array(ty, _) => check_unsuited(tcx, typing_env, *ty), ty::Adt(def, args) => { if !def.did().is_local() && !find_attr!( @@ -1550,28 +1563,36 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>) .any(ty::VariantDef::is_field_list_non_exhaustive); let has_priv = def.all_fields().any(|f| !f.vis.is_public()); if non_exhaustive || has_priv { - return ControlFlow::Break(( - def.descr(), - def.did(), - args, - non_exhaustive, - )); + return ControlFlow::Break(UnsuitedInfo { + ty, + reason: if non_exhaustive { + UnsuitedReason::NonExhaustive + } else { + UnsuitedReason::PrivateField + }, + }); } } + if def.repr().c() { + return ControlFlow::Break(UnsuitedInfo { + ty, + reason: UnsuitedReason::ReprC, + }); + } def.all_fields() .map(|field| field.ty(tcx, args)) - .try_for_each(|t| check_non_exhaustive(tcx, typing_env, t)) + .try_for_each(|t| check_unsuited(tcx, typing_env, t)) } _ => ControlFlow::Continue(()), } } - (span, trivial, check_non_exhaustive(tcx, typing_env, ty).break_value()) + FieldInfo { span, trivial, unsuited: check_unsuited(tcx, typing_env, ty).break_value() } }); let non_trivial_fields = field_infos .clone() - .filter_map(|(span, trivial, _non_exhaustive)| if !trivial { Some(span) } else { None }); + .filter_map(|field| if !field.trivial { Some(field.span) } else { None }); let non_trivial_count = non_trivial_fields.clone().count(); if non_trivial_count >= 2 { bad_non_zero_sized_fields( @@ -1583,36 +1604,40 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>) ); return; } - let mut prev_non_exhaustive_1zst = false; - for (span, _trivial, non_exhaustive_1zst) in field_infos { - if let Some((descr, def_id, args, non_exhaustive)) = non_exhaustive_1zst { + + let mut prev_unsuited_1zst = false; + for field in field_infos { + if let Some(unsuited) = field.unsuited { + assert!(field.trivial); // If there are any non-trivial fields, then there can be no non-exhaustive 1-zsts. // Otherwise, it's only an issue if there's >1 non-exhaustive 1-zst. - if non_trivial_count > 0 || prev_non_exhaustive_1zst { + if non_trivial_count > 0 || prev_unsuited_1zst { tcx.node_span_lint( - REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS, + REPR_TRANSPARENT_NON_ZST_FIELDS, tcx.local_def_id_to_hir_id(adt.did().expect_local()), - span, + field.span, |lint| { + let title = match unsuited.reason { + UnsuitedReason::NonExhaustive => "external non-exhaustive types", + UnsuitedReason::PrivateField => "external types with private fields", + UnsuitedReason::ReprC => "`repr(C)` types", + }; lint.primary_message( - "zero-sized fields in `repr(transparent)` cannot \ - contain external non-exhaustive types", + format!("zero-sized fields in `repr(transparent)` cannot contain {title}"), ); - let note = if non_exhaustive { - "is marked with `#[non_exhaustive]`" - } else { - "contains private fields" + let note = match unsuited.reason { + UnsuitedReason::NonExhaustive => "is marked with `#[non_exhaustive]`, so it could become non-zero-sized in the future.", + UnsuitedReason::PrivateField => "contains private fields, so it could become non-zero-sized in the future.", + UnsuitedReason::ReprC => "is a `#[repr(C)]` type, so it is not guaranteed to be zero-sized on all targets.", }; - let field_ty = tcx.def_path_str_with_args(def_id, args); lint.note(format!( - "this {descr} contains `{field_ty}`, which {note}, \ - and makes it not a breaking change to become \ - non-zero-sized in the future." + "this field contains `{field_ty}`, which {note}", + field_ty = unsuited.ty, )); }, - ) + ); } else { - prev_non_exhaustive_1zst = true; + prev_unsuited_1zst = true; } } } diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 9bb53fea54a18..003bf0c3db3c2 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -362,6 +362,10 @@ fn register_builtins(store: &mut LintStore) { store.register_renamed("static_mut_ref", "static_mut_refs"); store.register_renamed("temporary_cstring_as_ptr", "dangling_pointers_from_temporaries"); store.register_renamed("elided_named_lifetimes", "mismatched_lifetime_syntaxes"); + store.register_renamed( + "repr_transparent_external_private_fields", + "repr_transparent_non_zst_fields", + ); // These were moved to tool lints, but rustc still sees them when compiling normally, before // tool lints are registered, so `check_tool_name_for_backwards_compat` doesn't work. Use diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 8b7b13a4c3622..91b82ecfa43d4 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -86,7 +86,7 @@ declare_lint_pass! { REFINING_IMPL_TRAIT_INTERNAL, REFINING_IMPL_TRAIT_REACHABLE, RENAMED_AND_REMOVED_LINTS, - REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS, + REPR_TRANSPARENT_NON_ZST_FIELDS, RUST_2021_INCOMPATIBLE_CLOSURE_CAPTURES, RUST_2021_INCOMPATIBLE_OR_PATTERNS, RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX, @@ -3011,10 +3011,9 @@ declare_lint! { } declare_lint! { - /// The `repr_transparent_external_private_fields` lint + /// The `repr_transparent_non_zst_fields` lint /// detects types marked `#[repr(transparent)]` that (transitively) - /// contain an external ZST type marked `#[non_exhaustive]` or containing - /// private fields + /// contain a type that is not guaranteed to remain a ZST type under all configurations. /// /// ### Example /// @@ -3022,8 +3021,13 @@ declare_lint! { /// #![deny(repr_transparent_external_private_fields)] /// use foo::NonExhaustiveZst; /// + /// #[repr(C)] + /// struct CZst([u8; 0]); + /// /// #[repr(transparent)] /// struct Bar(u32, ([u32; 0], NonExhaustiveZst)); + /// #[repr(transparent)] + /// struct Baz(u32, CZst); /// ``` /// /// This will produce: @@ -3042,26 +3046,39 @@ declare_lint! { /// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /// = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! /// = note: for more information, see issue #78586 - /// = note: this struct contains `NonExhaustiveZst`, which is marked with `#[non_exhaustive]`, and makes it not a breaking change to become non-zero-sized in the future. + /// = note: this field contains `NonExhaustiveZst`, which is marked with `#[non_exhaustive]`, so it could become non-zero-sized in the future. + /// + /// error: zero-sized fields in repr(transparent) cannot contain `#[repr(C)]` types + /// --> src/main.rs:5:28 + /// | + /// 5 | struct Baz(u32, CZst); + /// | ^^^^ + /// = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + /// = note: for more information, see issue #78586 + /// = note: this field contains `CZst`, which is a `#[repr(C)]` type, so it is not guaranteed to be zero-sized on all targets. /// ``` /// /// ### Explanation /// - /// Previous, Rust accepted fields that contain external private zero-sized types, - /// even though it should not be a breaking change to add a non-zero-sized field to - /// that private type. + /// Previous, Rust accepted fields that contain external private zero-sized types, even though + /// those types could gain a non-zero-sized field in a future, semver-compatible update. + /// + /// Rust also accepted fields that contain `repr(C)` zero-sized types, even though those types + /// are not guaranteed to be zero-sized on all targets, and even though those types can + /// make a difference for the ABI (and therefore cannot be ignored by `repr(transparent)`). /// /// This is a [future-incompatible] lint to transition this /// to a hard error in the future. See [issue #78586] for more details. /// /// [issue #78586]: https://github.com/rust-lang/rust/issues/78586 /// [future-incompatible]: ../index.md#future-incompatible-lints - pub REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS, - Warn, + pub REPR_TRANSPARENT_NON_ZST_FIELDS, + Deny, "transparent type contains an external ZST that is marked #[non_exhaustive] or contains private fields", @future_incompatible = FutureIncompatibleInfo { reason: FutureIncompatibilityReason::FutureReleaseError, reference: "issue #78586 ", + report_in_deps: true, }; } diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 40a818a3c9dc7..ec26c35ffdc9f 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -403,7 +403,7 @@ pub enum FutureIncompatibilityReason { /// /// After a lint has been in this state for a while and you feel like it is ready to graduate /// to warning everyone, consider setting [`FutureIncompatibleInfo::report_in_deps`] to true. - /// (see it's documentation for more guidance) + /// (see its documentation for more guidance) /// /// After some period of time, lints with this variant can be turned into /// hard errors (and the lint removed). Preferably when there is some diff --git a/tests/ui/lint/improper-ctypes/lint-ctypes.rs b/tests/ui/lint/improper-ctypes/lint-ctypes.rs index 7dc06079fa32c..5d90e22e4b492 100644 --- a/tests/ui/lint/improper-ctypes/lint-ctypes.rs +++ b/tests/ui/lint/improper-ctypes/lint-ctypes.rs @@ -38,6 +38,7 @@ pub struct TransparentLifetime<'a>(*const u8, PhantomData<&'a ()>); #[repr(transparent)] pub struct TransparentUnit(f32, PhantomData); #[repr(transparent)] +#[allow(repr_transparent_non_zst_fields)] pub struct TransparentCustomZst(i32, ZeroSize); #[repr(C)] diff --git a/tests/ui/lint/improper-ctypes/lint-ctypes.stderr b/tests/ui/lint/improper-ctypes/lint-ctypes.stderr index 6f8b951c53d70..ef23f3ca6c919 100644 --- a/tests/ui/lint/improper-ctypes/lint-ctypes.stderr +++ b/tests/ui/lint/improper-ctypes/lint-ctypes.stderr @@ -1,5 +1,5 @@ error: `extern` block uses type `Foo`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:47:28 + --> $DIR/lint-ctypes.rs:48:28 | LL | pub fn ptr_type1(size: *const Foo); | ^^^^^^^^^^ not FFI-safe @@ -18,7 +18,7 @@ LL | #![deny(improper_ctypes)] | ^^^^^^^^^^^^^^^ error: `extern` block uses type `Foo`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:48:28 + --> $DIR/lint-ctypes.rs:49:28 | LL | pub fn ptr_type2(size: *const Foo); | ^^^^^^^^^^ not FFI-safe @@ -32,7 +32,7 @@ LL | pub struct Foo; | ^^^^^^^^^^^^^^ error: `extern` block uses type `((),)`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:50:25 + --> $DIR/lint-ctypes.rs:51:25 | LL | pub fn ptr_tuple(p: *const ((),)); | ^^^^^^^^^^^^ not FFI-safe @@ -41,7 +41,7 @@ LL | pub fn ptr_tuple(p: *const ((),)); = note: tuples have unspecified layout error: `extern` block uses type `[u32]`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:51:26 + --> $DIR/lint-ctypes.rs:52:26 | LL | pub fn slice_type(p: &[u32]); | ^^^^^^ not FFI-safe @@ -50,7 +50,7 @@ LL | pub fn slice_type(p: &[u32]); = note: slices have no C equivalent error: `extern` block uses type `str`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:52:24 + --> $DIR/lint-ctypes.rs:53:24 | LL | pub fn str_type(p: &str); | ^^^^ not FFI-safe @@ -59,7 +59,7 @@ LL | pub fn str_type(p: &str); = note: string slices have no C equivalent error: `extern` block uses type `Box`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:53:24 + --> $DIR/lint-ctypes.rs:54:24 | LL | pub fn box_type(p: Box); | ^^^^^^^^ not FFI-safe @@ -68,7 +68,7 @@ LL | pub fn box_type(p: Box); = note: this struct has unspecified layout error: `extern` block uses type `char`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:55:25 + --> $DIR/lint-ctypes.rs:56:25 | LL | pub fn char_type(p: char); | ^^^^ not FFI-safe @@ -77,7 +77,7 @@ LL | pub fn char_type(p: char); = note: the `char` type has no C equivalent error: `extern` block uses type `dyn Bar`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:56:26 + --> $DIR/lint-ctypes.rs:57:26 | LL | pub fn trait_type(p: &dyn Bar); | ^^^^^^^^ not FFI-safe @@ -85,7 +85,7 @@ LL | pub fn trait_type(p: &dyn Bar); = note: trait objects have no C equivalent error: `extern` block uses type `(i32, i32)`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:57:26 + --> $DIR/lint-ctypes.rs:58:26 | LL | pub fn tuple_type(p: (i32, i32)); | ^^^^^^^^^^ not FFI-safe @@ -94,7 +94,7 @@ LL | pub fn tuple_type(p: (i32, i32)); = note: tuples have unspecified layout error: `extern` block uses type `(i32, i32)`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:58:27 + --> $DIR/lint-ctypes.rs:59:27 | LL | pub fn tuple_type2(p: I32Pair); | ^^^^^^^ not FFI-safe @@ -103,7 +103,7 @@ LL | pub fn tuple_type2(p: I32Pair); = note: tuples have unspecified layout error: `extern` block uses type `ZeroSize`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:59:25 + --> $DIR/lint-ctypes.rs:60:25 | LL | pub fn zero_size(p: ZeroSize); | ^^^^^^^^ not FFI-safe @@ -117,20 +117,20 @@ LL | pub struct ZeroSize; | ^^^^^^^^^^^^^^^^^^^ error: `extern` block uses type `ZeroSizeWithPhantomData`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:60:33 + --> $DIR/lint-ctypes.rs:61:33 | LL | pub fn zero_size_phantom(p: ZeroSizeWithPhantomData); | ^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe | = note: composed only of `PhantomData` note: the type is defined here - --> $DIR/lint-ctypes.rs:44:1 + --> $DIR/lint-ctypes.rs:45:1 | LL | pub struct ZeroSizeWithPhantomData(::std::marker::PhantomData); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `extern` block uses type `PhantomData`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:63:12 + --> $DIR/lint-ctypes.rs:64:12 | LL | -> ::std::marker::PhantomData; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -138,7 +138,7 @@ LL | -> ::std::marker::PhantomData; = note: composed only of `PhantomData` error: `extern` block uses type `fn()`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:64:23 + --> $DIR/lint-ctypes.rs:65:23 | LL | pub fn fn_type(p: RustFn); | ^^^^^^ not FFI-safe @@ -147,7 +147,7 @@ LL | pub fn fn_type(p: RustFn); = note: this function pointer has Rust-specific calling convention error: `extern` block uses type `fn()`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:65:24 + --> $DIR/lint-ctypes.rs:66:24 | LL | pub fn fn_type2(p: fn()); | ^^^^ not FFI-safe @@ -156,7 +156,7 @@ LL | pub fn fn_type2(p: fn()); = note: this function pointer has Rust-specific calling convention error: `extern` block uses type `Box`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:66:28 + --> $DIR/lint-ctypes.rs:67:28 | LL | pub fn fn_contained(p: RustBadRet); | ^^^^^^^^^^ not FFI-safe @@ -165,7 +165,7 @@ LL | pub fn fn_contained(p: RustBadRet); = note: this struct has unspecified layout error: `extern` block uses type `str`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:67:31 + --> $DIR/lint-ctypes.rs:68:31 | LL | pub fn transparent_str(p: TransparentStr); | ^^^^^^^^^^^^^^ not FFI-safe @@ -174,7 +174,7 @@ LL | pub fn transparent_str(p: TransparentStr); = note: string slices have no C equivalent error: `extern` block uses type `Box`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:68:30 + --> $DIR/lint-ctypes.rs:69:30 | LL | pub fn transparent_fn(p: TransparentBadFn); | ^^^^^^^^^^^^^^^^ not FFI-safe @@ -183,7 +183,7 @@ LL | pub fn transparent_fn(p: TransparentBadFn); = note: this struct has unspecified layout error: `extern` block uses type `[u8; 8]`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:69:27 + --> $DIR/lint-ctypes.rs:70:27 | LL | pub fn raw_array(arr: [u8; 8]); | ^^^^^^^ not FFI-safe @@ -192,7 +192,7 @@ LL | pub fn raw_array(arr: [u8; 8]); = note: passing raw arrays by value is not FFI-safe error: `extern` block uses type `Option>`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:71:26 + --> $DIR/lint-ctypes.rs:72:26 | LL | pub fn no_niche_a(a: Option>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -201,7 +201,7 @@ LL | pub fn no_niche_a(a: Option>); = note: enum has no representation hint error: `extern` block uses type `Option>`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:73:26 + --> $DIR/lint-ctypes.rs:74:26 | LL | pub fn no_niche_b(b: Option>); | ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -211,3 +211,14 @@ LL | pub fn no_niche_b(b: Option>); error: aborting due to 21 previous errors +Future incompatibility report: Future breakage diagnostic: +warning: zero-sized fields in `repr(transparent)` cannot contain `repr(C)` types + --> $DIR/lint-ctypes.rs:42:38 + | +LL | pub struct TransparentCustomZst(i32, ZeroSize); + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #78586 + = note: this field contains `ZeroSize`, which is a `#[repr(C)]` type, so it is not guaranteed to be zero-sized on all targets. + diff --git a/tests/ui/lint/improper-ctypes/lint-fn.rs b/tests/ui/lint/improper-ctypes/lint-fn.rs index 0b84098e39067..e71febb493dc4 100644 --- a/tests/ui/lint/improper-ctypes/lint-fn.rs +++ b/tests/ui/lint/improper-ctypes/lint-fn.rs @@ -54,6 +54,7 @@ pub struct TransparentLifetime<'a>(*const u8, PhantomData<&'a ()>); pub struct TransparentUnit(f32, PhantomData); #[repr(transparent)] +#[allow(repr_transparent_non_zst_fields)] pub struct TransparentCustomZst(i32, ZeroSize); #[repr(C)] diff --git a/tests/ui/lint/improper-ctypes/lint-fn.stderr b/tests/ui/lint/improper-ctypes/lint-fn.stderr index 34e3bd021b92d..a0d1ab232c6ad 100644 --- a/tests/ui/lint/improper-ctypes/lint-fn.stderr +++ b/tests/ui/lint/improper-ctypes/lint-fn.stderr @@ -1,5 +1,5 @@ error: `extern` fn uses type `[u32]`, which is not FFI-safe - --> $DIR/lint-fn.rs:70:33 + --> $DIR/lint-fn.rs:71:33 | LL | pub extern "C" fn slice_type(p: &[u32]) { } | ^^^^^^ not FFI-safe @@ -13,7 +13,7 @@ LL | #![deny(improper_ctypes_definitions)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `extern` fn uses type `str`, which is not FFI-safe - --> $DIR/lint-fn.rs:73:31 + --> $DIR/lint-fn.rs:74:31 | LL | pub extern "C" fn str_type(p: &str) { } | ^^^^ not FFI-safe @@ -22,7 +22,7 @@ LL | pub extern "C" fn str_type(p: &str) { } = note: string slices have no C equivalent error: `extern` fn uses type `Box<[u8]>`, which is not FFI-safe - --> $DIR/lint-fn.rs:80:34 + --> $DIR/lint-fn.rs:81:34 | LL | pub extern "C" fn boxed_slice(p: Box<[u8]>) { } | ^^^^^^^^^ not FFI-safe @@ -30,7 +30,7 @@ LL | pub extern "C" fn boxed_slice(p: Box<[u8]>) { } = note: box cannot be represented as a single pointer error: `extern` fn uses type `Box`, which is not FFI-safe - --> $DIR/lint-fn.rs:83:35 + --> $DIR/lint-fn.rs:84:35 | LL | pub extern "C" fn boxed_string(p: Box) { } | ^^^^^^^^ not FFI-safe @@ -38,7 +38,7 @@ LL | pub extern "C" fn boxed_string(p: Box) { } = note: box cannot be represented as a single pointer error: `extern` fn uses type `Box`, which is not FFI-safe - --> $DIR/lint-fn.rs:86:34 + --> $DIR/lint-fn.rs:87:34 | LL | pub extern "C" fn boxed_trait(p: Box) { } | ^^^^^^^^^^^^^^ not FFI-safe @@ -46,7 +46,7 @@ LL | pub extern "C" fn boxed_trait(p: Box) { } = note: box cannot be represented as a single pointer error: `extern` fn uses type `char`, which is not FFI-safe - --> $DIR/lint-fn.rs:89:32 + --> $DIR/lint-fn.rs:90:32 | LL | pub extern "C" fn char_type(p: char) { } | ^^^^ not FFI-safe @@ -55,7 +55,7 @@ LL | pub extern "C" fn char_type(p: char) { } = note: the `char` type has no C equivalent error: `extern` fn uses type `(i32, i32)`, which is not FFI-safe - --> $DIR/lint-fn.rs:92:33 + --> $DIR/lint-fn.rs:93:33 | LL | pub extern "C" fn tuple_type(p: (i32, i32)) { } | ^^^^^^^^^^ not FFI-safe @@ -64,7 +64,7 @@ LL | pub extern "C" fn tuple_type(p: (i32, i32)) { } = note: tuples have unspecified layout error: `extern` fn uses type `(i32, i32)`, which is not FFI-safe - --> $DIR/lint-fn.rs:95:34 + --> $DIR/lint-fn.rs:96:34 | LL | pub extern "C" fn tuple_type2(p: I32Pair) { } | ^^^^^^^ not FFI-safe @@ -73,7 +73,7 @@ LL | pub extern "C" fn tuple_type2(p: I32Pair) { } = note: tuples have unspecified layout error: `extern` fn uses type `ZeroSize`, which is not FFI-safe - --> $DIR/lint-fn.rs:98:32 + --> $DIR/lint-fn.rs:99:32 | LL | pub extern "C" fn zero_size(p: ZeroSize) { } | ^^^^^^^^ not FFI-safe @@ -87,20 +87,20 @@ LL | pub struct ZeroSize; | ^^^^^^^^^^^^^^^^^^^ error: `extern` fn uses type `ZeroSizeWithPhantomData`, which is not FFI-safe - --> $DIR/lint-fn.rs:101:40 + --> $DIR/lint-fn.rs:102:40 | LL | pub extern "C" fn zero_size_phantom(p: ZeroSizeWithPhantomData) { } | ^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe | = note: composed only of `PhantomData` note: the type is defined here - --> $DIR/lint-fn.rs:60:1 + --> $DIR/lint-fn.rs:61:1 | LL | pub struct ZeroSizeWithPhantomData(PhantomData); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `extern` fn uses type `PhantomData`, which is not FFI-safe - --> $DIR/lint-fn.rs:104:51 + --> $DIR/lint-fn.rs:105:51 | LL | pub extern "C" fn zero_size_phantom_toplevel() -> PhantomData { | ^^^^^^^^^^^^^^^^^ not FFI-safe @@ -108,7 +108,7 @@ LL | pub extern "C" fn zero_size_phantom_toplevel() -> PhantomData { = note: composed only of `PhantomData` error: `extern` fn uses type `fn()`, which is not FFI-safe - --> $DIR/lint-fn.rs:109:30 + --> $DIR/lint-fn.rs:110:30 | LL | pub extern "C" fn fn_type(p: RustFn) { } | ^^^^^^ not FFI-safe @@ -117,7 +117,7 @@ LL | pub extern "C" fn fn_type(p: RustFn) { } = note: this function pointer has Rust-specific calling convention error: `extern` fn uses type `fn()`, which is not FFI-safe - --> $DIR/lint-fn.rs:112:31 + --> $DIR/lint-fn.rs:113:31 | LL | pub extern "C" fn fn_type2(p: fn()) { } | ^^^^ not FFI-safe @@ -126,7 +126,7 @@ LL | pub extern "C" fn fn_type2(p: fn()) { } = note: this function pointer has Rust-specific calling convention error: `extern` fn uses type `str`, which is not FFI-safe - --> $DIR/lint-fn.rs:117:38 + --> $DIR/lint-fn.rs:118:38 | LL | pub extern "C" fn transparent_str(p: TransparentStr) { } | ^^^^^^^^^^^^^^ not FFI-safe @@ -135,7 +135,7 @@ LL | pub extern "C" fn transparent_str(p: TransparentStr) { } = note: string slices have no C equivalent error: `extern` fn uses type `PhantomData`, which is not FFI-safe - --> $DIR/lint-fn.rs:169:43 + --> $DIR/lint-fn.rs:170:43 | LL | pub extern "C" fn unused_generic2() -> PhantomData { | ^^^^^^^^^^^^^^^^^ not FFI-safe @@ -143,7 +143,7 @@ LL | pub extern "C" fn unused_generic2() -> PhantomData { = note: composed only of `PhantomData` error: `extern` fn uses type `Vec`, which is not FFI-safe - --> $DIR/lint-fn.rs:182:39 + --> $DIR/lint-fn.rs:183:39 | LL | pub extern "C" fn used_generic4(x: Vec) { } | ^^^^^^ not FFI-safe @@ -152,7 +152,7 @@ LL | pub extern "C" fn used_generic4(x: Vec) { } = note: this struct has unspecified layout error: `extern` fn uses type `Vec`, which is not FFI-safe - --> $DIR/lint-fn.rs:185:41 + --> $DIR/lint-fn.rs:186:41 | LL | pub extern "C" fn used_generic5() -> Vec { | ^^^^^^ not FFI-safe @@ -162,3 +162,14 @@ LL | pub extern "C" fn used_generic5() -> Vec { error: aborting due to 17 previous errors +Future incompatibility report: Future breakage diagnostic: +warning: zero-sized fields in `repr(transparent)` cannot contain `repr(C)` types + --> $DIR/lint-fn.rs:58:38 + | +LL | pub struct TransparentCustomZst(i32, ZeroSize); + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #78586 + = note: this field contains `ZeroSize`, which is a `#[repr(C)]` type, so it is not guaranteed to be zero-sized on all targets. + diff --git a/tests/ui/repr/repr-transparent-non-exhaustive-transparent-in-prose.rs b/tests/ui/repr/repr-transparent-non-exhaustive-transparent-in-prose.rs index 6ab34719f0664..8de25ab266290 100644 --- a/tests/ui/repr/repr-transparent-non-exhaustive-transparent-in-prose.rs +++ b/tests/ui/repr/repr-transparent-non-exhaustive-transparent-in-prose.rs @@ -2,7 +2,7 @@ #![feature(sync_unsafe_cell)] #![allow(unused)] -#![deny(repr_transparent_external_private_fields)] +#![deny(repr_transparent_non_zst_fields)] // https://github.com/rust-lang/rust/issues/129470 diff --git a/tests/ui/repr/repr-transparent-non-exhaustive.rs b/tests/ui/repr/repr-transparent-non-exhaustive.rs index 38bab0163b4c5..9188d6df3446f 100644 --- a/tests/ui/repr/repr-transparent-non-exhaustive.rs +++ b/tests/ui/repr/repr-transparent-non-exhaustive.rs @@ -1,4 +1,4 @@ -#![deny(repr_transparent_external_private_fields)] +#![deny(repr_transparent_non_zst_fields)] //@ aux-build: repr-transparent-non-exhaustive.rs extern crate repr_transparent_non_exhaustive; @@ -42,7 +42,7 @@ pub struct T4(Sized, ExternalIndirection<(InternalPrivate, InternalNonExhaustive #[repr(transparent)] pub struct T5(Sized, Private); -//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types +//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external types with private fields //~| WARN this was previously accepted by the compiler #[repr(transparent)] @@ -67,7 +67,7 @@ pub struct T8(Sized, NonExhaustiveVariant); #[repr(transparent)] pub struct T9(Sized, InternalIndirection); -//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types +//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external types with private fields //~| WARN this was previously accepted by the compiler #[repr(transparent)] @@ -87,7 +87,7 @@ pub struct T12(Sized, InternalIndirection); #[repr(transparent)] pub struct T13(Sized, ExternalIndirection); -//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types +//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external types with private fields //~| WARN this was previously accepted by the compiler #[repr(transparent)] @@ -117,7 +117,7 @@ pub struct T18(NonExhaustive, NonExhaustive); #[repr(transparent)] pub struct T19(NonExhaustive, Private); -//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types +//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external types with private fields //~| WARN this was previously accepted by the compiler #[repr(transparent)] diff --git a/tests/ui/repr/repr-transparent-non-exhaustive.stderr b/tests/ui/repr/repr-transparent-non-exhaustive.stderr index 27ba6e82a539a..ac5493bf7e59c 100644 --- a/tests/ui/repr/repr-transparent-non-exhaustive.stderr +++ b/tests/ui/repr/repr-transparent-non-exhaustive.stderr @@ -1,4 +1,4 @@ -error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types +error: zero-sized fields in `repr(transparent)` cannot contain external types with private fields --> $DIR/repr-transparent-non-exhaustive.rs:44:22 | LL | pub struct T5(Sized, Private); @@ -6,12 +6,12 @@ LL | pub struct T5(Sized, Private); | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #78586 - = note: this struct contains `Private`, which contains private fields, and makes it not a breaking change to become non-zero-sized in the future. + = note: this field contains `Private`, which contains private fields, so it could become non-zero-sized in the future. note: the lint level is defined here --> $DIR/repr-transparent-non-exhaustive.rs:1:9 | -LL | #![deny(repr_transparent_external_private_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #![deny(repr_transparent_non_zst_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types --> $DIR/repr-transparent-non-exhaustive.rs:49:22 @@ -21,7 +21,7 @@ LL | pub struct T6(Sized, NonExhaustive); | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #78586 - = note: this struct contains `NonExhaustive`, which is marked with `#[non_exhaustive]`, and makes it not a breaking change to become non-zero-sized in the future. + = note: this field contains `NonExhaustive`, which is marked with `#[non_exhaustive]`, so it could become non-zero-sized in the future. error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types --> $DIR/repr-transparent-non-exhaustive.rs:54:23 @@ -31,7 +31,7 @@ LL | pub struct T6a(Sized, ::Assoc); // normalizes to `NonExhausti | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #78586 - = note: this struct contains `NonExhaustive`, which is marked with `#[non_exhaustive]`, and makes it not a breaking change to become non-zero-sized in the future. + = note: this field contains `NonExhaustive`, which is marked with `#[non_exhaustive]`, so it could become non-zero-sized in the future. error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types --> $DIR/repr-transparent-non-exhaustive.rs:59:22 @@ -41,7 +41,7 @@ LL | pub struct T7(Sized, NonExhaustiveEnum); | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #78586 - = note: this enum contains `NonExhaustiveEnum`, which is marked with `#[non_exhaustive]`, and makes it not a breaking change to become non-zero-sized in the future. + = note: this field contains `NonExhaustiveEnum`, which is marked with `#[non_exhaustive]`, so it could become non-zero-sized in the future. error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types --> $DIR/repr-transparent-non-exhaustive.rs:64:22 @@ -51,9 +51,9 @@ LL | pub struct T8(Sized, NonExhaustiveVariant); | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #78586 - = note: this enum contains `NonExhaustiveVariant`, which is marked with `#[non_exhaustive]`, and makes it not a breaking change to become non-zero-sized in the future. + = note: this field contains `NonExhaustiveVariant`, which is marked with `#[non_exhaustive]`, so it could become non-zero-sized in the future. -error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types +error: zero-sized fields in `repr(transparent)` cannot contain external types with private fields --> $DIR/repr-transparent-non-exhaustive.rs:69:22 | LL | pub struct T9(Sized, InternalIndirection); @@ -61,7 +61,7 @@ LL | pub struct T9(Sized, InternalIndirection); | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #78586 - = note: this struct contains `Private`, which contains private fields, and makes it not a breaking change to become non-zero-sized in the future. + = note: this field contains `Private`, which contains private fields, so it could become non-zero-sized in the future. error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types --> $DIR/repr-transparent-non-exhaustive.rs:74:23 @@ -71,7 +71,7 @@ LL | pub struct T10(Sized, InternalIndirection); | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #78586 - = note: this struct contains `NonExhaustive`, which is marked with `#[non_exhaustive]`, and makes it not a breaking change to become non-zero-sized in the future. + = note: this field contains `NonExhaustive`, which is marked with `#[non_exhaustive]`, so it could become non-zero-sized in the future. error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types --> $DIR/repr-transparent-non-exhaustive.rs:79:23 @@ -81,7 +81,7 @@ LL | pub struct T11(Sized, InternalIndirection); | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #78586 - = note: this enum contains `NonExhaustiveEnum`, which is marked with `#[non_exhaustive]`, and makes it not a breaking change to become non-zero-sized in the future. + = note: this field contains `NonExhaustiveEnum`, which is marked with `#[non_exhaustive]`, so it could become non-zero-sized in the future. error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types --> $DIR/repr-transparent-non-exhaustive.rs:84:23 @@ -91,9 +91,9 @@ LL | pub struct T12(Sized, InternalIndirection); | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #78586 - = note: this enum contains `NonExhaustiveVariant`, which is marked with `#[non_exhaustive]`, and makes it not a breaking change to become non-zero-sized in the future. + = note: this field contains `NonExhaustiveVariant`, which is marked with `#[non_exhaustive]`, so it could become non-zero-sized in the future. -error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types +error: zero-sized fields in `repr(transparent)` cannot contain external types with private fields --> $DIR/repr-transparent-non-exhaustive.rs:89:23 | LL | pub struct T13(Sized, ExternalIndirection); @@ -101,7 +101,7 @@ LL | pub struct T13(Sized, ExternalIndirection); | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #78586 - = note: this struct contains `Private`, which contains private fields, and makes it not a breaking change to become non-zero-sized in the future. + = note: this field contains `Private`, which contains private fields, so it could become non-zero-sized in the future. error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types --> $DIR/repr-transparent-non-exhaustive.rs:94:23 @@ -111,7 +111,7 @@ LL | pub struct T14(Sized, ExternalIndirection); | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #78586 - = note: this struct contains `NonExhaustive`, which is marked with `#[non_exhaustive]`, and makes it not a breaking change to become non-zero-sized in the future. + = note: this field contains `NonExhaustive`, which is marked with `#[non_exhaustive]`, so it could become non-zero-sized in the future. error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types --> $DIR/repr-transparent-non-exhaustive.rs:99:23 @@ -121,7 +121,7 @@ LL | pub struct T15(Sized, ExternalIndirection); | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #78586 - = note: this enum contains `NonExhaustiveEnum`, which is marked with `#[non_exhaustive]`, and makes it not a breaking change to become non-zero-sized in the future. + = note: this field contains `NonExhaustiveEnum`, which is marked with `#[non_exhaustive]`, so it could become non-zero-sized in the future. error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types --> $DIR/repr-transparent-non-exhaustive.rs:104:23 @@ -131,7 +131,7 @@ LL | pub struct T16(Sized, ExternalIndirection); | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #78586 - = note: this enum contains `NonExhaustiveVariant`, which is marked with `#[non_exhaustive]`, and makes it not a breaking change to become non-zero-sized in the future. + = note: this field contains `NonExhaustiveVariant`, which is marked with `#[non_exhaustive]`, so it could become non-zero-sized in the future. error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types --> $DIR/repr-transparent-non-exhaustive.rs:109:16 @@ -141,7 +141,7 @@ LL | pub struct T17(NonExhaustive, Sized); | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #78586 - = note: this struct contains `NonExhaustive`, which is marked with `#[non_exhaustive]`, and makes it not a breaking change to become non-zero-sized in the future. + = note: this field contains `NonExhaustive`, which is marked with `#[non_exhaustive]`, so it could become non-zero-sized in the future. error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types --> $DIR/repr-transparent-non-exhaustive.rs:114:31 @@ -151,9 +151,9 @@ LL | pub struct T18(NonExhaustive, NonExhaustive); | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #78586 - = note: this struct contains `NonExhaustive`, which is marked with `#[non_exhaustive]`, and makes it not a breaking change to become non-zero-sized in the future. + = note: this field contains `NonExhaustive`, which is marked with `#[non_exhaustive]`, so it could become non-zero-sized in the future. -error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types +error: zero-sized fields in `repr(transparent)` cannot contain external types with private fields --> $DIR/repr-transparent-non-exhaustive.rs:119:31 | LL | pub struct T19(NonExhaustive, Private); @@ -161,7 +161,7 @@ LL | pub struct T19(NonExhaustive, Private); | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #78586 - = note: this struct contains `Private`, which contains private fields, and makes it not a breaking change to become non-zero-sized in the future. + = note: this field contains `Private`, which contains private fields, so it could become non-zero-sized in the future. error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types --> $DIR/repr-transparent-non-exhaustive.rs:124:32 @@ -171,7 +171,279 @@ LL | pub struct T19Flipped(Private, NonExhaustive); | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #78586 - = note: this struct contains `NonExhaustive`, which is marked with `#[non_exhaustive]`, and makes it not a breaking change to become non-zero-sized in the future. + = note: this field contains `NonExhaustive`, which is marked with `#[non_exhaustive]`, so it could become non-zero-sized in the future. error: aborting due to 17 previous errors +Future incompatibility report: Future breakage diagnostic: +error: zero-sized fields in `repr(transparent)` cannot contain external types with private fields + --> $DIR/repr-transparent-non-exhaustive.rs:44:22 + | +LL | pub struct T5(Sized, Private); + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #78586 + = note: this field contains `Private`, which contains private fields, so it could become non-zero-sized in the future. +note: the lint level is defined here + --> $DIR/repr-transparent-non-exhaustive.rs:1:9 + | +LL | #![deny(repr_transparent_non_zst_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types + --> $DIR/repr-transparent-non-exhaustive.rs:49:22 + | +LL | pub struct T6(Sized, NonExhaustive); + | ^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #78586 + = note: this field contains `NonExhaustive`, which is marked with `#[non_exhaustive]`, so it could become non-zero-sized in the future. +note: the lint level is defined here + --> $DIR/repr-transparent-non-exhaustive.rs:1:9 + | +LL | #![deny(repr_transparent_non_zst_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types + --> $DIR/repr-transparent-non-exhaustive.rs:54:23 + | +LL | pub struct T6a(Sized, ::Assoc); // normalizes to `NonExhaustive` + | ^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #78586 + = note: this field contains `NonExhaustive`, which is marked with `#[non_exhaustive]`, so it could become non-zero-sized in the future. +note: the lint level is defined here + --> $DIR/repr-transparent-non-exhaustive.rs:1:9 + | +LL | #![deny(repr_transparent_non_zst_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types + --> $DIR/repr-transparent-non-exhaustive.rs:59:22 + | +LL | pub struct T7(Sized, NonExhaustiveEnum); + | ^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #78586 + = note: this field contains `NonExhaustiveEnum`, which is marked with `#[non_exhaustive]`, so it could become non-zero-sized in the future. +note: the lint level is defined here + --> $DIR/repr-transparent-non-exhaustive.rs:1:9 + | +LL | #![deny(repr_transparent_non_zst_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types + --> $DIR/repr-transparent-non-exhaustive.rs:64:22 + | +LL | pub struct T8(Sized, NonExhaustiveVariant); + | ^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #78586 + = note: this field contains `NonExhaustiveVariant`, which is marked with `#[non_exhaustive]`, so it could become non-zero-sized in the future. +note: the lint level is defined here + --> $DIR/repr-transparent-non-exhaustive.rs:1:9 + | +LL | #![deny(repr_transparent_non_zst_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: zero-sized fields in `repr(transparent)` cannot contain external types with private fields + --> $DIR/repr-transparent-non-exhaustive.rs:69:22 + | +LL | pub struct T9(Sized, InternalIndirection); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #78586 + = note: this field contains `Private`, which contains private fields, so it could become non-zero-sized in the future. +note: the lint level is defined here + --> $DIR/repr-transparent-non-exhaustive.rs:1:9 + | +LL | #![deny(repr_transparent_non_zst_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types + --> $DIR/repr-transparent-non-exhaustive.rs:74:23 + | +LL | pub struct T10(Sized, InternalIndirection); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #78586 + = note: this field contains `NonExhaustive`, which is marked with `#[non_exhaustive]`, so it could become non-zero-sized in the future. +note: the lint level is defined here + --> $DIR/repr-transparent-non-exhaustive.rs:1:9 + | +LL | #![deny(repr_transparent_non_zst_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types + --> $DIR/repr-transparent-non-exhaustive.rs:79:23 + | +LL | pub struct T11(Sized, InternalIndirection); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #78586 + = note: this field contains `NonExhaustiveEnum`, which is marked with `#[non_exhaustive]`, so it could become non-zero-sized in the future. +note: the lint level is defined here + --> $DIR/repr-transparent-non-exhaustive.rs:1:9 + | +LL | #![deny(repr_transparent_non_zst_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types + --> $DIR/repr-transparent-non-exhaustive.rs:84:23 + | +LL | pub struct T12(Sized, InternalIndirection); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #78586 + = note: this field contains `NonExhaustiveVariant`, which is marked with `#[non_exhaustive]`, so it could become non-zero-sized in the future. +note: the lint level is defined here + --> $DIR/repr-transparent-non-exhaustive.rs:1:9 + | +LL | #![deny(repr_transparent_non_zst_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: zero-sized fields in `repr(transparent)` cannot contain external types with private fields + --> $DIR/repr-transparent-non-exhaustive.rs:89:23 + | +LL | pub struct T13(Sized, ExternalIndirection); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #78586 + = note: this field contains `Private`, which contains private fields, so it could become non-zero-sized in the future. +note: the lint level is defined here + --> $DIR/repr-transparent-non-exhaustive.rs:1:9 + | +LL | #![deny(repr_transparent_non_zst_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types + --> $DIR/repr-transparent-non-exhaustive.rs:94:23 + | +LL | pub struct T14(Sized, ExternalIndirection); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #78586 + = note: this field contains `NonExhaustive`, which is marked with `#[non_exhaustive]`, so it could become non-zero-sized in the future. +note: the lint level is defined here + --> $DIR/repr-transparent-non-exhaustive.rs:1:9 + | +LL | #![deny(repr_transparent_non_zst_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types + --> $DIR/repr-transparent-non-exhaustive.rs:99:23 + | +LL | pub struct T15(Sized, ExternalIndirection); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #78586 + = note: this field contains `NonExhaustiveEnum`, which is marked with `#[non_exhaustive]`, so it could become non-zero-sized in the future. +note: the lint level is defined here + --> $DIR/repr-transparent-non-exhaustive.rs:1:9 + | +LL | #![deny(repr_transparent_non_zst_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types + --> $DIR/repr-transparent-non-exhaustive.rs:104:23 + | +LL | pub struct T16(Sized, ExternalIndirection); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #78586 + = note: this field contains `NonExhaustiveVariant`, which is marked with `#[non_exhaustive]`, so it could become non-zero-sized in the future. +note: the lint level is defined here + --> $DIR/repr-transparent-non-exhaustive.rs:1:9 + | +LL | #![deny(repr_transparent_non_zst_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types + --> $DIR/repr-transparent-non-exhaustive.rs:109:16 + | +LL | pub struct T17(NonExhaustive, Sized); + | ^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #78586 + = note: this field contains `NonExhaustive`, which is marked with `#[non_exhaustive]`, so it could become non-zero-sized in the future. +note: the lint level is defined here + --> $DIR/repr-transparent-non-exhaustive.rs:1:9 + | +LL | #![deny(repr_transparent_non_zst_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types + --> $DIR/repr-transparent-non-exhaustive.rs:114:31 + | +LL | pub struct T18(NonExhaustive, NonExhaustive); + | ^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #78586 + = note: this field contains `NonExhaustive`, which is marked with `#[non_exhaustive]`, so it could become non-zero-sized in the future. +note: the lint level is defined here + --> $DIR/repr-transparent-non-exhaustive.rs:1:9 + | +LL | #![deny(repr_transparent_non_zst_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: zero-sized fields in `repr(transparent)` cannot contain external types with private fields + --> $DIR/repr-transparent-non-exhaustive.rs:119:31 + | +LL | pub struct T19(NonExhaustive, Private); + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #78586 + = note: this field contains `Private`, which contains private fields, so it could become non-zero-sized in the future. +note: the lint level is defined here + --> $DIR/repr-transparent-non-exhaustive.rs:1:9 + | +LL | #![deny(repr_transparent_non_zst_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types + --> $DIR/repr-transparent-non-exhaustive.rs:124:32 + | +LL | pub struct T19Flipped(Private, NonExhaustive); + | ^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #78586 + = note: this field contains `NonExhaustive`, which is marked with `#[non_exhaustive]`, so it could become non-zero-sized in the future. +note: the lint level is defined here + --> $DIR/repr-transparent-non-exhaustive.rs:1:9 + | +LL | #![deny(repr_transparent_non_zst_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/repr/repr-transparent-repr-c.rs b/tests/ui/repr/repr-transparent-repr-c.rs new file mode 100644 index 0000000000000..c887c443f3fcd --- /dev/null +++ b/tests/ui/repr/repr-transparent-repr-c.rs @@ -0,0 +1,32 @@ +#![deny(repr_transparent_non_zst_fields)] + +#[repr(C)] +pub struct ReprC1Zst { + pub _f: (), +} + +pub type Sized = i32; + +#[repr(transparent)] +pub struct T1(ReprC1Zst); +#[repr(transparent)] +pub struct T2((), ReprC1Zst); +#[repr(transparent)] +pub struct T3(ReprC1Zst, ()); + +#[repr(transparent)] +pub struct T5(Sized, ReprC1Zst); +//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain `repr(C)` types +//~| WARN this was previously accepted by the compiler + +#[repr(transparent)] +pub struct T6(ReprC1Zst, Sized); +//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain `repr(C)` types +//~| WARN this was previously accepted by the compiler + +#[repr(transparent)] +pub struct T7(T1, Sized); // still wrong, even when the repr(C) is hidden inside another type +//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain `repr(C)` types +//~| WARN this was previously accepted by the compiler + +fn main() {} diff --git a/tests/ui/repr/repr-transparent-repr-c.stderr b/tests/ui/repr/repr-transparent-repr-c.stderr new file mode 100644 index 0000000000000..5724845afdc1e --- /dev/null +++ b/tests/ui/repr/repr-transparent-repr-c.stderr @@ -0,0 +1,85 @@ +error: zero-sized fields in `repr(transparent)` cannot contain `repr(C)` types + --> $DIR/repr-transparent-repr-c.rs:18:22 + | +LL | pub struct T5(Sized, ReprC1Zst); + | ^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #78586 + = note: this field contains `ReprC1Zst`, which is a `#[repr(C)]` type, so it is not guaranteed to be zero-sized on all targets. +note: the lint level is defined here + --> $DIR/repr-transparent-repr-c.rs:1:9 + | +LL | #![deny(repr_transparent_non_zst_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: zero-sized fields in `repr(transparent)` cannot contain `repr(C)` types + --> $DIR/repr-transparent-repr-c.rs:23:15 + | +LL | pub struct T6(ReprC1Zst, Sized); + | ^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #78586 + = note: this field contains `ReprC1Zst`, which is a `#[repr(C)]` type, so it is not guaranteed to be zero-sized on all targets. + +error: zero-sized fields in `repr(transparent)` cannot contain `repr(C)` types + --> $DIR/repr-transparent-repr-c.rs:28:15 + | +LL | pub struct T7(T1, Sized); // still wrong, even when the repr(C) is hidden inside another type + | ^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #78586 + = note: this field contains `ReprC1Zst`, which is a `#[repr(C)]` type, so it is not guaranteed to be zero-sized on all targets. + +error: aborting due to 3 previous errors + +Future incompatibility report: Future breakage diagnostic: +error: zero-sized fields in `repr(transparent)` cannot contain `repr(C)` types + --> $DIR/repr-transparent-repr-c.rs:18:22 + | +LL | pub struct T5(Sized, ReprC1Zst); + | ^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #78586 + = note: this field contains `ReprC1Zst`, which is a `#[repr(C)]` type, so it is not guaranteed to be zero-sized on all targets. +note: the lint level is defined here + --> $DIR/repr-transparent-repr-c.rs:1:9 + | +LL | #![deny(repr_transparent_non_zst_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: zero-sized fields in `repr(transparent)` cannot contain `repr(C)` types + --> $DIR/repr-transparent-repr-c.rs:23:15 + | +LL | pub struct T6(ReprC1Zst, Sized); + | ^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #78586 + = note: this field contains `ReprC1Zst`, which is a `#[repr(C)]` type, so it is not guaranteed to be zero-sized on all targets. +note: the lint level is defined here + --> $DIR/repr-transparent-repr-c.rs:1:9 + | +LL | #![deny(repr_transparent_non_zst_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: zero-sized fields in `repr(transparent)` cannot contain `repr(C)` types + --> $DIR/repr-transparent-repr-c.rs:28:15 + | +LL | pub struct T7(T1, Sized); // still wrong, even when the repr(C) is hidden inside another type + | ^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #78586 + = note: this field contains `ReprC1Zst`, which is a `#[repr(C)]` type, so it is not guaranteed to be zero-sized on all targets. +note: the lint level is defined here + --> $DIR/repr-transparent-repr-c.rs:1:9 + | +LL | #![deny(repr_transparent_non_zst_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +