From 944c0e23b8e44782e5097a7265bd78d124b92523 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Thu, 7 Jul 2022 16:55:41 +0000 Subject: [PATCH 1/3] check non_exhaustive attr and private fields for transparent types --- compiler/rustc_lint_defs/src/builtin.rs | 51 +++++++++++++ compiler/rustc_typeck/src/check/check.rs | 71 +++++++++++++++++-- .../repr-transparent-non-exhaustive.rs | 10 +++ .../repr/repr-transparent-non-exhaustive.rs | 60 ++++++++++++++++ .../repr-transparent-non-exhaustive.stderr | 67 +++++++++++++++++ 5 files changed, 254 insertions(+), 5 deletions(-) create mode 100644 src/test/ui/repr/auxiliary/repr-transparent-non-exhaustive.rs create mode 100644 src/test/ui/repr/repr-transparent-non-exhaustive.rs create mode 100644 src/test/ui/repr/repr-transparent-non-exhaustive.stderr diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 9fc2249b29019..ae973e6a56382 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -3132,6 +3132,56 @@ declare_lint! { "detects unexpected names and values in `#[cfg]` conditions", } +declare_lint! { + /// The `repr_transparent_external_private_fields` lint + /// detects types marked #[repr(trasparent)] that (transitively) + /// contain an external ZST type marked #[non_exhaustive] + /// + /// ### Example + /// + /// ```rust,ignore (needs external crate) + /// #![deny(repr_transparent_external_private_fields)] + /// use foo::NonExhaustiveZst; + /// + /// #[repr(transparent)] + /// struct Bar(u32, ([u32; 0], NonExhaustiveZst)); + /// ``` + /// + /// This will produce: + /// + /// ```text + /// error: deprecated `#[macro_use]` attribute used to import macros should be replaced at use sites with a `use` item to import the macro instead + /// --> src/main.rs:3:1 + /// | + /// 3 | #[macro_use] + /// | ^^^^^^^^^^^^ + /// | + /// note: the lint level is defined here + /// --> src/main.rs:1:9 + /// | + /// 1 | #![deny(repr_transparent_external_private_fields)] + /// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + /// ``` + /// + /// ### 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. + /// + /// 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, + "tranparent type contains an external ZST that is marked #[non_exhaustive] or contains private fields", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #78586 ", + }; +} + declare_lint_pass! { /// Does nothing as a lint pass, but registers some `Lint`s /// that are used by other parts of the compiler. @@ -3237,6 +3287,7 @@ declare_lint_pass! { DEPRECATED_WHERE_CLAUSE_LOCATION, TEST_UNSTABLE_LINT, FFI_UNWIND_CALLS, + REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS, ] } diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index e9709b64d930e..79edbeab9c72e 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -17,6 +17,7 @@ use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt}; use rustc_infer::traits::Obligation; +use rustc_lint::builtin::REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS; use rustc_middle::hir::nested_filter; use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES}; use rustc_middle::ty::subst::GenericArgKind; @@ -1318,7 +1319,8 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, adt: ty::AdtD } } - // For each field, figure out if it's known to be a ZST and align(1) + // For each field, figure out if it's known to be a ZST and align(1), with "known" + // respecting #[non_exhaustive] attributes. let field_infos = adt.all_fields().map(|field| { let ty = field.ty(tcx, InternalSubsts::identity_for_item(tcx, field.did)); let param_env = tcx.param_env(field.did); @@ -1327,16 +1329,56 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, adt: ty::AdtD let span = tcx.hir().span_if_local(field.did).unwrap(); let zst = layout.map_or(false, |layout| layout.is_zst()); let align1 = layout.map_or(false, |layout| layout.align.abi.bytes() == 1); - (span, zst, align1) + if !zst { + return (span, zst, align1, None); + } + + fn check_non_exhaustive<'tcx>( + tcx: TyCtxt<'tcx>, + t: Ty<'tcx>, + ) -> ControlFlow<(&'static str, DefId, SubstsRef<'tcx>, bool)> { + match t.kind() { + ty::Tuple(list) => list.iter().try_for_each(|t| check_non_exhaustive(tcx, t)), + ty::Array(ty, _) => check_non_exhaustive(tcx, *ty), + ty::Adt(def, subst) => { + if !def.did().is_local() { + let non_exhaustive = def.is_variant_list_non_exhaustive() + || def + .variants() + .iter() + .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(), + subst, + non_exhaustive, + )); + } + } + def.all_fields() + .map(|field| field.ty(tcx, subst)) + .try_for_each(|t| check_non_exhaustive(tcx, t)) + } + _ => ControlFlow::Continue(()), + } + } + + (span, zst, align1, check_non_exhaustive(tcx, ty).break_value()) }); - let non_zst_fields = - field_infos.clone().filter_map(|(span, zst, _align1)| if !zst { Some(span) } else { None }); + let non_zst_fields = field_infos + .clone() + .filter_map(|(span, zst, _align1, _non_exhaustive)| if !zst { Some(span) } else { None }); let non_zst_count = non_zst_fields.clone().count(); if non_zst_count >= 2 { bad_non_zero_sized_fields(tcx, adt, non_zst_count, non_zst_fields, sp); } - for (span, zst, align1) in field_infos { + let incompatible_zst_fields = + field_infos.clone().filter(|(_, _, _, opt)| opt.is_some()).count(); + let incompat = incompatible_zst_fields + non_zst_count >= 2 && non_zst_count < 2; + for (span, zst, align1, non_exhaustive) in field_infos { if zst && !align1 { struct_span_err!( tcx.sess, @@ -1348,6 +1390,25 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, adt: ty::AdtD .span_label(span, "has alignment larger than 1") .emit(); } + if incompat && let Some((descr, def_id, substs, non_exhaustive)) = non_exhaustive { + tcx.struct_span_lint_hir( + REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS, + tcx.hir().local_def_id_to_hir_id(adt.did().expect_local()), + span, + |lint| { + let note = if non_exhaustive { + "is marked with `#[non_exhaustive]`" + } else { + "contains private fields" + }; + let field_ty = tcx.def_path_str_with_substs(def_id, substs); + lint.build("zero-sized fields in repr(transparent) cannot contain external non-exhaustive types") + .note(format!("this {descr} contains `{field_ty}`, which {note}, \ + and makes it not a breaking change to become non-zero-sized in the future.")) + .emit(); + }, + ) + } } } diff --git a/src/test/ui/repr/auxiliary/repr-transparent-non-exhaustive.rs b/src/test/ui/repr/auxiliary/repr-transparent-non-exhaustive.rs new file mode 100644 index 0000000000000..b8ae5c2b729fd --- /dev/null +++ b/src/test/ui/repr/auxiliary/repr-transparent-non-exhaustive.rs @@ -0,0 +1,10 @@ +#![crate_type = "lib"] + +pub struct Private { _priv: () } + +#[non_exhaustive] +pub struct NonExhaustive {} + +pub struct ExternalIndirection { + pub x: T, +} diff --git a/src/test/ui/repr/repr-transparent-non-exhaustive.rs b/src/test/ui/repr/repr-transparent-non-exhaustive.rs new file mode 100644 index 0000000000000..600caee8ba3a4 --- /dev/null +++ b/src/test/ui/repr/repr-transparent-non-exhaustive.rs @@ -0,0 +1,60 @@ +#![deny(repr_transparent_external_private_fields)] + +// aux-build: repr-transparent-non-exhaustive.rs +extern crate repr_transparent_non_exhaustive; + +use repr_transparent_non_exhaustive::{Private, NonExhaustive, ExternalIndirection}; + +pub struct InternalPrivate { + _priv: (), +} + +#[non_exhaustive] +pub struct InternalNonExhaustive; + +pub struct InternalIndirection { + x: T, +} + +pub type Sized = i32; + +#[repr(transparent)] +pub struct T1(Sized, InternalPrivate); +#[repr(transparent)] +pub struct T2(Sized, InternalNonExhaustive); +#[repr(transparent)] +pub struct T3(Sized, InternalIndirection<(InternalPrivate, InternalNonExhaustive)>); +#[repr(transparent)] +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 T7(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 T8(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 T9(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 T10(Sized, ExternalIndirection); +//~^ ERROR zero-sized fields in repr(transparent) cannot contain external non-exhaustive types +//~| WARN this was previously accepted by the compiler + +fn main() {} diff --git a/src/test/ui/repr/repr-transparent-non-exhaustive.stderr b/src/test/ui/repr/repr-transparent-non-exhaustive.stderr new file mode 100644 index 0000000000000..3e45b2ab22cd5 --- /dev/null +++ b/src/test/ui/repr/repr-transparent-non-exhaustive.stderr @@ -0,0 +1,67 @@ +error: zero-sized fields in repr(transparent) cannot contain external non-exhaustive types + --> $DIR/repr-transparent-non-exhaustive.rs:31:22 + | +LL | pub struct T5(Sized, Private); + | ^^^^^^^ + | +note: the lint level is defined here + --> $DIR/repr-transparent-non-exhaustive.rs:1:9 + | +LL | #![deny(repr_transparent_external_private_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = 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. + +error: zero-sized fields in repr(transparent) cannot contain external non-exhaustive types + --> $DIR/repr-transparent-non-exhaustive.rs:36: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. + +error: zero-sized fields in repr(transparent) cannot contain external non-exhaustive types + --> $DIR/repr-transparent-non-exhaustive.rs:41:22 + | +LL | pub struct T7(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. + +error: zero-sized fields in repr(transparent) cannot contain external non-exhaustive types + --> $DIR/repr-transparent-non-exhaustive.rs:46:22 + | +LL | pub struct T8(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. + +error: zero-sized fields in repr(transparent) cannot contain external non-exhaustive types + --> $DIR/repr-transparent-non-exhaustive.rs:51:22 + | +LL | pub struct T9(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. + +error: zero-sized fields in repr(transparent) cannot contain external non-exhaustive types + --> $DIR/repr-transparent-non-exhaustive.rs:56:23 + | +LL | pub struct T10(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. + +error: aborting due to 6 previous errors + From e65214785d85a4e2c76141e14eb38a55f1fd21d1 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Sun, 10 Jul 2022 13:31:58 +0000 Subject: [PATCH 2/3] add more tests --- .../repr-transparent-non-exhaustive.rs | 8 ++ .../repr/repr-transparent-non-exhaustive.rs | 46 ++++++++-- .../repr-transparent-non-exhaustive.stderr | 86 ++++++++++++++++--- 3 files changed, 122 insertions(+), 18 deletions(-) diff --git a/src/test/ui/repr/auxiliary/repr-transparent-non-exhaustive.rs b/src/test/ui/repr/auxiliary/repr-transparent-non-exhaustive.rs index b8ae5c2b729fd..4bf6b54fe0787 100644 --- a/src/test/ui/repr/auxiliary/repr-transparent-non-exhaustive.rs +++ b/src/test/ui/repr/auxiliary/repr-transparent-non-exhaustive.rs @@ -5,6 +5,14 @@ pub struct Private { _priv: () } #[non_exhaustive] pub struct NonExhaustive {} +#[non_exhaustive] +pub enum NonExhaustiveEnum {} + +pub enum NonExhaustiveVariant { + #[non_exhaustive] + A, +} + pub struct ExternalIndirection { pub x: T, } diff --git a/src/test/ui/repr/repr-transparent-non-exhaustive.rs b/src/test/ui/repr/repr-transparent-non-exhaustive.rs index 600caee8ba3a4..9ccd8610dad47 100644 --- a/src/test/ui/repr/repr-transparent-non-exhaustive.rs +++ b/src/test/ui/repr/repr-transparent-non-exhaustive.rs @@ -3,7 +3,13 @@ // aux-build: repr-transparent-non-exhaustive.rs extern crate repr_transparent_non_exhaustive; -use repr_transparent_non_exhaustive::{Private, NonExhaustive, ExternalIndirection}; +use repr_transparent_non_exhaustive::{ + Private, + NonExhaustive, + NonExhaustiveEnum, + NonExhaustiveVariant, + ExternalIndirection, +}; pub struct InternalPrivate { _priv: (), @@ -38,22 +44,52 @@ pub struct T6(Sized, NonExhaustive); //~| WARN this was previously accepted by the compiler #[repr(transparent)] -pub struct T7(Sized, InternalIndirection); +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, InternalIndirection); +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, ExternalIndirection); +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, ExternalIndirection); +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 diff --git a/src/test/ui/repr/repr-transparent-non-exhaustive.stderr b/src/test/ui/repr/repr-transparent-non-exhaustive.stderr index 3e45b2ab22cd5..3b1e334a0cbe2 100644 --- a/src/test/ui/repr/repr-transparent-non-exhaustive.stderr +++ b/src/test/ui/repr/repr-transparent-non-exhaustive.stderr @@ -1,5 +1,5 @@ error: zero-sized fields in repr(transparent) cannot contain external non-exhaustive types - --> $DIR/repr-transparent-non-exhaustive.rs:31:22 + --> $DIR/repr-transparent-non-exhaustive.rs:37:22 | LL | pub struct T5(Sized, Private); | ^^^^^^^ @@ -14,7 +14,7 @@ LL | #![deny(repr_transparent_external_private_fields)] = note: this struct 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:36:22 + --> $DIR/repr-transparent-non-exhaustive.rs:42:22 | LL | pub struct T6(Sized, NonExhaustive); | ^^^^^^^^^^^^^ @@ -24,9 +24,29 @@ LL | pub struct T6(Sized, NonExhaustive); = 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:41:22 + --> $DIR/repr-transparent-non-exhaustive.rs:47:22 | -LL | pub struct T7(Sized, InternalIndirection); +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. + +error: zero-sized fields in repr(transparent) cannot contain external non-exhaustive types + --> $DIR/repr-transparent-non-exhaustive.rs:52: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. + +error: zero-sized fields in repr(transparent) cannot contain external non-exhaustive types + --> $DIR/repr-transparent-non-exhaustive.rs:57: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! @@ -34,34 +54,74 @@ LL | pub struct T7(Sized, InternalIndirection); = note: this struct 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:46:22 + --> $DIR/repr-transparent-non-exhaustive.rs:62:23 | -LL | pub struct T8(Sized, InternalIndirection); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +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. error: zero-sized fields in repr(transparent) cannot contain external non-exhaustive types - --> $DIR/repr-transparent-non-exhaustive.rs:51:22 + --> $DIR/repr-transparent-non-exhaustive.rs:67:23 | -LL | pub struct T9(Sized, ExternalIndirection); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +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. + +error: zero-sized fields in repr(transparent) cannot contain external non-exhaustive types + --> $DIR/repr-transparent-non-exhaustive.rs:72: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. + +error: zero-sized fields in repr(transparent) cannot contain external non-exhaustive types + --> $DIR/repr-transparent-non-exhaustive.rs:77: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. error: zero-sized fields in repr(transparent) cannot contain external non-exhaustive types - --> $DIR/repr-transparent-non-exhaustive.rs:56:23 + --> $DIR/repr-transparent-non-exhaustive.rs:82:23 | -LL | pub struct T10(Sized, ExternalIndirection); +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. -error: aborting due to 6 previous errors +error: zero-sized fields in repr(transparent) cannot contain external non-exhaustive types + --> $DIR/repr-transparent-non-exhaustive.rs:87: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. + +error: zero-sized fields in repr(transparent) cannot contain external non-exhaustive types + --> $DIR/repr-transparent-non-exhaustive.rs:92: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. + +error: aborting due to 12 previous errors From 1d260067f14a41ea64bd2c7c2c537d5bc33380d6 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Tue, 12 Jul 2022 10:33:52 +0000 Subject: [PATCH 3/3] fix documentation --- compiler/rustc_lint_defs/src/builtin.rs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index ae973e6a56382..6d2cb63c1d71a 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -3134,8 +3134,9 @@ declare_lint! { declare_lint! { /// The `repr_transparent_external_private_fields` lint - /// detects types marked #[repr(trasparent)] that (transitively) - /// contain an external ZST type marked #[non_exhaustive] + /// detects types marked `#[repr(transparent)]` that (transitively) + /// contain an external ZST type marked `#[non_exhaustive]` or containing + /// private fields /// /// ### Example /// @@ -3150,17 +3151,20 @@ declare_lint! { /// This will produce: /// /// ```text - /// error: deprecated `#[macro_use]` attribute used to import macros should be replaced at use sites with a `use` item to import the macro instead - /// --> src/main.rs:3:1 + /// error: zero-sized fields in repr(transparent) cannot contain external non-exhaustive types + /// --> src/main.rs:5:28 /// | - /// 3 | #[macro_use] - /// | ^^^^^^^^^^^^ + /// 5 | struct Bar(u32, ([u32; 0], NonExhaustiveZst)); + /// | ^^^^^^^^^^^^^^^^ /// | /// note: the lint level is defined here /// --> src/main.rs:1:9 /// | /// 1 | #![deny(repr_transparent_external_private_fields)] /// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + /// = 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. /// ``` /// /// ### Explanation