about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2024-08-25 16:51:05 +0200
committerGitHub <noreply@github.com>2024-08-25 16:51:05 +0200
commit9c59e97dedcbeb747fb34a849ce445d836424f04 (patch)
tree0f28cb6f74943b8230650f9ff84bb5517d7b3a3f
parenta44e5a94ababe626281ab5187b389cd73ae1fdb3 (diff)
parent06f2d73b2bd6f290a72d8041c957a08b3f6d50c7 (diff)
downloadrust-9c59e97dedcbeb747fb34a849ce445d836424f04.tar.gz
rust-9c59e97dedcbeb747fb34a849ce445d836424f04.zip
Rollup merge of #129487 - GrigorenkoPV:repr_transparent_external_private_fields, r=compiler-errors
repr_transparent_external_private_fields: special-case some std types

Fixes #129470

```@rustbot``` label +A-lint +L-repr_transparent_external_private_fields
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs5
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs3
-rw-r--r--compiler/rustc_passes/messages.ftl4
-rw-r--r--compiler/rustc_passes/src/check_attr.rs13
-rw-r--r--compiler/rustc_passes/src/errors.rs9
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--library/core/src/cell.rs3
-rw-r--r--library/core/src/mem/manually_drop.rs1
-rw-r--r--library/core/src/mem/maybe_uninit.rs1
-rw-r--r--library/core/src/pin.rs1
-rw-r--r--tests/ui/attributes/rustc_pub_transparent.rs25
-rw-r--r--tests/ui/attributes/rustc_pub_transparent.stderr23
-rw-r--r--tests/ui/repr/repr-transparent-non-exhaustive-transparent-in-prose.rs25
13 files changed, 113 insertions, 1 deletions
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index d4c54b67f24..2747a14d60a 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -641,6 +641,11 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
         ErrorFollowing, EncodeCrossCrate::Yes,
         "rustc_deprecated_safe_2024 is supposed to be used in libstd only",
     ),
+    rustc_attr!(
+        rustc_pub_transparent, Normal, template!(Word),
+        WarnFollowing, EncodeCrossCrate::Yes,
+        "used internally to mark types with a `transparent` representation when it is guaranteed by the documentation",
+    ),
 
 
     // ==========================================================================
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 14c5f8d9f16..728c3790098 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -1259,7 +1259,8 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
                 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, args) => {
-                    if !def.did().is_local() {
+                    if !def.did().is_local() && !tcx.has_attr(def.did(), sym::rustc_pub_transparent)
+                    {
                         let non_exhaustive = def.is_variant_list_non_exhaustive()
                             || def
                                 .variants()
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index dfc726efeb9..b377c9f52d6 100644
--- a/compiler/rustc_passes/messages.ftl
+++ b/compiler/rustc_passes/messages.ftl
@@ -657,6 +657,10 @@ passes_rustc_lint_opt_ty =
     `#[rustc_lint_opt_ty]` should be applied to a struct
     .label = not a struct
 
+passes_rustc_pub_transparent =
+    attribute should be applied to `#[repr(transparent)]` types
+    .label = not a `#[repr(transparent)]` type
+
 passes_rustc_safe_intrinsic =
     attribute should be applied to intrinsic functions
     .label = not an intrinsic function
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index c93fb5c23b1..9ca4bb09b3e 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -245,6 +245,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                     self.check_coroutine(attr, target);
                 }
                 [sym::linkage, ..] => self.check_linkage(attr, span, target),
+                [sym::rustc_pub_transparent, ..] => self.check_rustc_pub_transparent( attr.span, span, attrs),
                 [
                     // ok
                     sym::allow
@@ -2381,6 +2382,18 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
             }
         }
     }
+
+    fn check_rustc_pub_transparent(&self, attr_span: Span, span: Span, attrs: &[Attribute]) {
+        if !attrs
+            .iter()
+            .filter(|attr| attr.has_name(sym::repr))
+            .filter_map(|attr| attr.meta_item_list())
+            .flatten()
+            .any(|nmi| nmi.has_name(sym::transparent))
+        {
+            self.dcx().emit_err(errors::RustcPubTransparent { span, attr_span });
+        }
+    }
 }
 
 impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> {
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index 1190e60f41f..f6a57b7d098 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -623,6 +623,15 @@ pub struct RustcStdInternalSymbol {
 }
 
 #[derive(Diagnostic)]
+#[diag(passes_rustc_pub_transparent)]
+pub struct RustcPubTransparent {
+    #[primary_span]
+    pub attr_span: Span,
+    #[label]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
 #[diag(passes_link_ordinal)]
 pub struct LinkOrdinal {
     #[primary_span]
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index db09c948a8e..2957105288b 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1674,6 +1674,7 @@ symbols! {
         rustc_private,
         rustc_proc_macro_decls,
         rustc_promotable,
+        rustc_pub_transparent,
         rustc_reallocator,
         rustc_regions,
         rustc_reservation_impl,
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index d860f3415d9..5dd9721d3fe 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -306,6 +306,7 @@ pub use once::OnceCell;
 /// See the [module-level documentation](self) for more.
 #[stable(feature = "rust1", since = "1.0.0")]
 #[repr(transparent)]
+#[cfg_attr(not(bootstrap), rustc_pub_transparent)]
 pub struct Cell<T: ?Sized> {
     value: UnsafeCell<T>,
 }
@@ -2055,6 +2056,7 @@ impl<T: ?Sized + fmt::Display> fmt::Display for RefMut<'_, T> {
 #[lang = "unsafe_cell"]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[repr(transparent)]
+#[cfg_attr(not(bootstrap), rustc_pub_transparent)]
 pub struct UnsafeCell<T: ?Sized> {
     value: T,
 }
@@ -2297,6 +2299,7 @@ impl<T> UnsafeCell<*mut T> {
 /// See [`UnsafeCell`] for details.
 #[unstable(feature = "sync_unsafe_cell", issue = "95439")]
 #[repr(transparent)]
+#[cfg_attr(not(bootstrap), rustc_pub_transparent)]
 pub struct SyncUnsafeCell<T: ?Sized> {
     value: UnsafeCell<T>,
 }
diff --git a/library/core/src/mem/manually_drop.rs b/library/core/src/mem/manually_drop.rs
index 00c837041b6..be5cee2e852 100644
--- a/library/core/src/mem/manually_drop.rs
+++ b/library/core/src/mem/manually_drop.rs
@@ -47,6 +47,7 @@ use crate::ptr;
 #[lang = "manually_drop"]
 #[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
 #[repr(transparent)]
+#[cfg_attr(not(bootstrap), rustc_pub_transparent)]
 pub struct ManuallyDrop<T: ?Sized> {
     value: T,
 }
diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs
index f920ab1792d..c308def2f57 100644
--- a/library/core/src/mem/maybe_uninit.rs
+++ b/library/core/src/mem/maybe_uninit.rs
@@ -237,6 +237,7 @@ use crate::{fmt, intrinsics, ptr, slice};
 #[lang = "maybe_uninit"]
 #[derive(Copy)]
 #[repr(transparent)]
+#[cfg_attr(not(bootstrap), rustc_pub_transparent)]
 pub union MaybeUninit<T> {
     uninit: (),
     value: ManuallyDrop<T>,
diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs
index 0f9e6061c32..780e476f531 100644
--- a/library/core/src/pin.rs
+++ b/library/core/src/pin.rs
@@ -1084,6 +1084,7 @@ use crate::{cmp, fmt};
 #[lang = "pin"]
 #[fundamental]
 #[repr(transparent)]
+#[cfg_attr(not(bootstrap), rustc_pub_transparent)]
 #[derive(Copy, Clone)]
 pub struct Pin<Ptr> {
     // FIXME(#93176): this field is made `#[unstable] #[doc(hidden)] pub` to:
diff --git a/tests/ui/attributes/rustc_pub_transparent.rs b/tests/ui/attributes/rustc_pub_transparent.rs
new file mode 100644
index 00000000000..4508fa39baf
--- /dev/null
+++ b/tests/ui/attributes/rustc_pub_transparent.rs
@@ -0,0 +1,25 @@
+#![feature(rustc_attrs, transparent_unions)]
+
+#[rustc_pub_transparent]
+#[repr(transparent)]
+union E<T: Copy> {
+    value: T,
+    uninit: (),
+}
+
+#[repr(transparent)]
+#[rustc_pub_transparent]
+struct S<T>(T);
+
+#[rustc_pub_transparent] //~ ERROR attribute should be applied to `#[repr(transparent)]` types
+#[repr(C)]
+struct S1 {
+    A: u8,
+}
+
+#[rustc_pub_transparent] //~ ERROR attribute should be applied to `#[repr(transparent)]` types
+struct S2<T> {
+    value: T,
+}
+
+fn main() {}
diff --git a/tests/ui/attributes/rustc_pub_transparent.stderr b/tests/ui/attributes/rustc_pub_transparent.stderr
new file mode 100644
index 00000000000..1d1f9437cb2
--- /dev/null
+++ b/tests/ui/attributes/rustc_pub_transparent.stderr
@@ -0,0 +1,23 @@
+error: attribute should be applied to `#[repr(transparent)]` types
+  --> $DIR/rustc_pub_transparent.rs:14:1
+   |
+LL |   #[rustc_pub_transparent]
+   |   ^^^^^^^^^^^^^^^^^^^^^^^^
+LL |   #[repr(C)]
+LL | / struct S1 {
+LL | |     A: u8,
+LL | | }
+   | |_- not a `#[repr(transparent)]` type
+
+error: attribute should be applied to `#[repr(transparent)]` types
+  --> $DIR/rustc_pub_transparent.rs:20:1
+   |
+LL |   #[rustc_pub_transparent]
+   |   ^^^^^^^^^^^^^^^^^^^^^^^^
+LL | / struct S2<T> {
+LL | |     value: T,
+LL | | }
+   | |_- not a `#[repr(transparent)]` type
+
+error: aborting due to 2 previous errors
+
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
new file mode 100644
index 00000000000..6ab34719f06
--- /dev/null
+++ b/tests/ui/repr/repr-transparent-non-exhaustive-transparent-in-prose.rs
@@ -0,0 +1,25 @@
+//@ check-pass
+
+#![feature(sync_unsafe_cell)]
+#![allow(unused)]
+#![deny(repr_transparent_external_private_fields)]
+
+// https://github.com/rust-lang/rust/issues/129470
+
+struct ZST;
+
+#[repr(transparent)]
+struct TransparentWithManuallyDropZST {
+    value: i32,
+    md: std::mem::ManuallyDrop<ZST>,
+    mu: std::mem::MaybeUninit<ZST>,
+    p: std::pin::Pin<ZST>,
+    pd: std::marker::PhantomData<ZST>,
+    pp: std::marker::PhantomPinned,
+    c: std::cell::Cell<ZST>,
+    uc: std::cell::UnsafeCell<ZST>,
+    suc: std::cell::SyncUnsafeCell<ZST>,
+    zst: ZST,
+}
+
+fn main() {}