Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

repr_transparent_external_private_fields: special-case some std types #129487

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions compiler/rustc_feature/src/builtin_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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",
),


// ==========================================================================
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_hir_analysis/src/check/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_passes/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
13 changes: 13 additions & 0 deletions compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -2381,6 +2382,18 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
}
}

fn check_rustc_pub_transparent(&self, attr_span: Span, span: Span, attrs: &[Attribute]) {
compiler-errors marked this conversation as resolved.
Show resolved Hide resolved
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> {
Expand Down
9 changes: 9 additions & 0 deletions compiler/rustc_passes/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -622,6 +622,15 @@ pub struct RustcStdInternalSymbol {
pub span: Span,
}

#[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 {
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1672,6 +1672,7 @@ symbols! {
rustc_private,
rustc_proc_macro_decls,
rustc_promotable,
rustc_pub_transparent,
rustc_reallocator,
rustc_regions,
rustc_reservation_impl,
Expand Down
3 changes: 3 additions & 0 deletions library/core/src/cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>,
}
Expand Down Expand Up @@ -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,
}
Expand Down Expand Up @@ -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>,
}
Expand Down
1 change: 1 addition & 0 deletions library/core/src/mem/manually_drop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
Expand Down
1 change: 1 addition & 0 deletions library/core/src/mem/maybe_uninit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>,
Expand Down
1 change: 1 addition & 0 deletions library/core/src/pin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
25 changes: 25 additions & 0 deletions tests/ui/attributes/rustc_pub_transparent.rs
Original file line number Diff line number Diff line change
@@ -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() {}
23 changes: 23 additions & 0 deletions tests/ui/attributes/rustc_pub_transparent.stderr
Original file line number Diff line number Diff line change
@@ -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

Original file line number Diff line number Diff line change
@@ -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() {}
Loading