diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 4c910d25c30a8..d763adf5ceff7 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::UNSUPPORTED_CALLING_CONVENTIONS; use rustc_middle::hir::nested_filter; use rustc_middle::middle::resolve_bound_vars::ResolvedArg; use rustc_middle::middle::stability::EvalResult; @@ -1510,9 +1508,27 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>) return; } + // 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)`. 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, + Uninhabited, + } + 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. 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 +1536,18 @@ 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)> { - // 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), + adt: DefId, + ty: Ty<'tcx>, + ) -> ControlFlow> { + match ty.kind() { + ty::Tuple(list) => list.iter().try_for_each(|t| check_unsuited(tcx, adt, t)), + ty::Array(ty, _) => check_unsuited(tcx, adt, *ty), ty::Adt(def, args) => { if !def.did().is_local() && !find_attr!( @@ -1550,28 +1562,44 @@ 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, adt, t)) } _ => ControlFlow::Continue(()), } } - (span, trivial, check_non_exhaustive(tcx, typing_env, ty).break_value()) + FieldInfo { + span, + trivial, + unsuited: check_unsuited(tcx, adt.did(), ty).break_value().or_else(|| { + // We don't need to check this recursively, a single top-level check suffices. + let uninhabited = layout.is_ok_and(|layout| layout.is_uninhabited()); + uninhabited.then_some(UnsuitedInfo { ty, reason: UnsuitedReason::Uninhabited }) + }), + } }); 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 +1611,34 @@ 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 { - tcx.node_span_lint( - REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS, - tcx.local_def_id_to_hir_id(adt.did().expect_local()), - span, - |lint| { - lint.primary_message( - "zero-sized fields in `repr(transparent)` cannot \ + if non_trivial_count > 0 || prev_unsuited_1zst { + let mut diag = tcx.dcx().struct_span_err( + field.span, + "zero-sized fields in `repr(transparent)` cannot \ contain external non-exhaustive types", - ); - let note = if non_exhaustive { - "is marked with `#[non_exhaustive]`" - } else { - "contains private fields" - }; - let field_ty = tcx.def_path_str_with_args(def_id, args); - lint.note(format!( - "this {descr} contains `{field_ty}`, which {note}, \ + ); + let note = match unsuited.reason { + UnsuitedReason::NonExhaustive => "is marked with `#[non_exhaustive]`", + UnsuitedReason::PrivateField => "contains private fields", + UnsuitedReason::ReprC => "is marked with `#[repr(C)]`", + UnsuitedReason::Uninhabited => "is not inhabited", + }; + diag.note(format!( + "this field contains `{field_ty}`, which {note}, \ and makes it not a breaking change to become \ - non-zero-sized in the future." - )); - }, - ) + non-zero-sized in the future.", + field_ty = unsuited.ty, + )); + diag.emit(); } else { - prev_non_exhaustive_1zst = true; + prev_unsuited_1zst = 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/src/build_helper/src/lib.rs b/src/build_helper/src/lib.rs index 266eedc624582..50027488760cf 100644 --- a/src/build_helper/src/lib.rs +++ b/src/build_helper/src/lib.rs @@ -18,7 +18,6 @@ pub const LLVM_PGO_CRATES: &[&str] = &[ "ripgrep-14.1.1", "regex-automata-0.4.8", "clap_derive-4.5.32", - "hyper-1.6.0", ]; /// The default set of crates for opt-dist to collect rustc profiles. diff --git a/tests/ui/repr/repr-transparent-non-exhaustive.rs b/tests/ui/repr/repr-transparent-non-exhaustive.rs index 38bab0163b4c5..c81bfa83a8603 100644 --- a/tests/ui/repr/repr-transparent-non-exhaustive.rs +++ b/tests/ui/repr/repr-transparent-non-exhaustive.rs @@ -43,12 +43,10 @@ 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 -//~| WARN this was previously accepted by the compiler #[repr(transparent)] pub struct T6(Sized, NonExhaustive); //~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types -//~| WARN this was previously accepted by the compiler #[repr(transparent)] pub struct T6a(Sized, ::Assoc); // normalizes to `NonExhaustive` @@ -58,72 +56,58 @@ pub struct T6a(Sized, ::Assoc); // normalizes to `NonExhaustive` #[repr(transparent)] pub struct T7(Sized, NonExhaustiveEnum); //~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types -//~| WARN this was previously accepted by the compiler #[repr(transparent)] pub struct T8(Sized, NonExhaustiveVariant); //~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types -//~| WARN this was previously accepted by the compiler #[repr(transparent)] pub struct T9(Sized, InternalIndirection); //~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types -//~| WARN this was previously accepted by the compiler #[repr(transparent)] pub struct T10(Sized, InternalIndirection); //~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types -//~| WARN this was previously accepted by the compiler #[repr(transparent)] pub struct T11(Sized, InternalIndirection); //~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types -//~| WARN this was previously accepted by the compiler #[repr(transparent)] pub struct T12(Sized, InternalIndirection); //~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types -//~| WARN this was previously accepted by the compiler #[repr(transparent)] pub struct T13(Sized, ExternalIndirection); //~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types -//~| WARN this was previously accepted by the compiler #[repr(transparent)] pub struct T14(Sized, ExternalIndirection); //~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types -//~| WARN this was previously accepted by the compiler #[repr(transparent)] pub struct T15(Sized, ExternalIndirection); //~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types -//~| WARN this was previously accepted by the compiler #[repr(transparent)] pub struct T16(Sized, ExternalIndirection); //~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types -//~| WARN this was previously accepted by the compiler #[repr(transparent)] pub struct T17(NonExhaustive, Sized); //~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types -//~| WARN this was previously accepted by the compiler #[repr(transparent)] pub struct T18(NonExhaustive, NonExhaustive); //~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types -//~| WARN this was previously accepted by the compiler #[repr(transparent)] pub struct T19(NonExhaustive, Private); //~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types -//~| WARN this was previously accepted by the compiler #[repr(transparent)] pub struct T19Flipped(Private, NonExhaustive); //~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types -//~| WARN this was previously accepted by the compiler #[repr(transparent)] pub struct T20(NonExhaustive); diff --git a/tests/ui/repr/repr-transparent-non-exhaustive.stderr b/tests/ui/repr/repr-transparent-non-exhaustive.stderr index 27ba6e82a539a..97169fcb8fbb6 100644 --- a/tests/ui/repr/repr-transparent-non-exhaustive.stderr +++ b/tests/ui/repr/repr-transparent-non-exhaustive.stderr @@ -4,174 +4,127 @@ error: zero-sized fields in `repr(transparent)` cannot contain external non-exha 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: the lint level is defined here - --> $DIR/repr-transparent-non-exhaustive.rs:1:9 - | -LL | #![deny(repr_transparent_external_private_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this field contains `Private`, which contains private fields, and makes it not a breaking change to 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:49:22 + --> $DIR/repr-transparent-non-exhaustive.rs:48: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 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]`, and makes it not a breaking change to 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 - | -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 struct contains `NonExhaustive`, which is marked with `#[non_exhaustive]`, and makes it not a breaking change to 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 + --> $DIR/repr-transparent-non-exhaustive.rs:57: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 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]`, and makes it not a breaking change to 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 + --> $DIR/repr-transparent-non-exhaustive.rs:61: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 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]`, and makes it not a breaking change to 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:69:22 + --> $DIR/repr-transparent-non-exhaustive.rs:65: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 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, and makes it not a breaking change to 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 + --> $DIR/repr-transparent-non-exhaustive.rs:69: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 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]`, and makes it not a breaking change to 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 + --> $DIR/repr-transparent-non-exhaustive.rs:73: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 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]`, and makes it not a breaking change to 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 + --> $DIR/repr-transparent-non-exhaustive.rs:77: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 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]`, and makes it not a breaking change to 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:89:23 + --> $DIR/repr-transparent-non-exhaustive.rs:81: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 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, and makes it not a breaking change to 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 + --> $DIR/repr-transparent-non-exhaustive.rs:85: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 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]`, and makes it not a breaking change to 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 + --> $DIR/repr-transparent-non-exhaustive.rs:89: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 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]`, and makes it not a breaking change to 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 + --> $DIR/repr-transparent-non-exhaustive.rs:93: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 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]`, and makes it not a breaking change to 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 + --> $DIR/repr-transparent-non-exhaustive.rs:97: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 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]`, and makes it not a breaking change to 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 + --> $DIR/repr-transparent-non-exhaustive.rs:101: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 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]`, and makes it not a breaking change to 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:119:31 + --> $DIR/repr-transparent-non-exhaustive.rs:105: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 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, and makes it not a breaking change to 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 + --> $DIR/repr-transparent-non-exhaustive.rs:109: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 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]`, and makes it not a breaking change to become non-zero-sized in the future. -error: aborting due to 17 previous errors +error: aborting due to 16 previous errors 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..d897c44c8b6b9 --- /dev/null +++ b/tests/ui/repr/repr-transparent-repr-c.rs @@ -0,0 +1,29 @@ +#![deny(repr_transparent_external_private_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 external non-exhaustive types + +#[repr(transparent)] +pub struct T6(ReprC1Zst, Sized); +//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types + +#[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 external non-exhaustive types + +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..11e8de3d9a5df --- /dev/null +++ b/tests/ui/repr/repr-transparent-repr-c.stderr @@ -0,0 +1,26 @@ +error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types + --> $DIR/repr-transparent-repr-c.rs:18:22 + | +LL | pub struct T5(Sized, ReprC1Zst); + | ^^^^^^^^^ + | + = note: this field contains `ReprC1Zst`, which is marked with `#[repr(C)]`, and makes it not a breaking change to become non-zero-sized in the future. + +error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types + --> $DIR/repr-transparent-repr-c.rs:22:15 + | +LL | pub struct T6(ReprC1Zst, Sized); + | ^^^^^^^^^ + | + = note: this field contains `ReprC1Zst`, which is marked with `#[repr(C)]`, and makes it not a breaking change to become non-zero-sized in the future. + +error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types + --> $DIR/repr-transparent-repr-c.rs:26:15 + | +LL | pub struct T7(T1, Sized); // still wrong, even when the repr(C) is hidden inside another type + | ^^ + | + = note: this field contains `ReprC1Zst`, which is marked with `#[repr(C)]`, and makes it not a breaking change to become non-zero-sized in the future. + +error: aborting due to 3 previous errors + diff --git a/tests/ui/repr/repr-transparent-uninhabited.rs b/tests/ui/repr/repr-transparent-uninhabited.rs new file mode 100644 index 0000000000000..578c20a0b1a40 --- /dev/null +++ b/tests/ui/repr/repr-transparent-uninhabited.rs @@ -0,0 +1,23 @@ +#![feature(never_type)] +#![deny(repr_transparent_external_private_fields)] + +enum Void {} + +pub type Sized = i32; + +#[repr(transparent)] +pub struct T1(!); +#[repr(transparent)] +pub struct T2((), Void); +#[repr(transparent)] +pub struct T3(!, ()); + +#[repr(transparent)] +pub struct T5(Sized, Void); +//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types + +#[repr(transparent)] +pub struct T6(!, Sized); +//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types + +fn main() {} diff --git a/tests/ui/repr/repr-transparent-uninhabited.stderr b/tests/ui/repr/repr-transparent-uninhabited.stderr new file mode 100644 index 0000000000000..0fd424ccf57c4 --- /dev/null +++ b/tests/ui/repr/repr-transparent-uninhabited.stderr @@ -0,0 +1,18 @@ +error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types + --> $DIR/repr-transparent-uninhabited.rs:16:22 + | +LL | pub struct T5(Sized, Void); + | ^^^^ + | + = note: this field contains `Void`, which is not inhabited, and makes it not a breaking change to become non-zero-sized in the future. + +error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types + --> $DIR/repr-transparent-uninhabited.rs:20:15 + | +LL | pub struct T6(!, Sized); + | ^ + | + = note: this field contains `!`, which is not inhabited, and makes it not a breaking change to become non-zero-sized in the future. + +error: aborting due to 2 previous errors +