about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2024-01-19 08:15:05 +0100
committerGitHub <noreply@github.com>2024-01-19 08:15:05 +0100
commit332f8f73ea581fd5cb2ee94c1b9ae31dd61d4d67 (patch)
tree56a33d8bd48cb41e8ee6071ffa81c3b030da48ed
parent987445cd42f1235c7599db9752f693459de31330 (diff)
parentaeeaed9ce137d489f7157202548d2ce3d65c60ae (diff)
downloadrust-332f8f73ea581fd5cb2ee94c1b9ae31dd61d4d67.tar.gz
rust-332f8f73ea581fd5cb2ee94c1b9ae31dd61d4d67.zip
Rollup merge of #120107 - shepmaster:dead-code-repr-transparent, r=Nilstrieb
dead_code treats #[repr(transparent)] the same as #[repr(C)]

In #92972 we enabled linting on unused fields in tuple structs. In #118297 that lint was enabled by default. That exposed issues like #119659, where the fields of a struct marked `#[repr(transparent)]` were reported by the `dead_code` lint. The language team [decided](https://github.com/rust-lang/rust/issues/119659#issuecomment-1885172045) that the lint should treat `repr(transparent)` the same as `#[repr(C)]`.

Fixes #119659
-rw-r--r--compiler/rustc_passes/src/dead.rs18
-rw-r--r--library/alloc/src/boxed/thin.rs1
-rw-r--r--src/tools/miri/tests/fail/issue-miri-1112.rs2
-rw-r--r--src/tools/miri/tests/fail/unaligned_pointers/drop_in_place.rs2
-rw-r--r--tests/ui/consts/transmute-const.rs2
-rw-r--r--tests/ui/layout/unsafe-cell-hides-niche.rs2
-rw-r--r--tests/ui/lint/dead-code/type-in-transparent.rs14
-rw-r--r--tests/ui/packed/packed-struct-drop-aligned.rs2
8 files changed, 29 insertions, 14 deletions
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index 9422a594488..d7f17ac4547 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -57,7 +57,7 @@ struct MarkSymbolVisitor<'tcx> {
     tcx: TyCtxt<'tcx>,
     maybe_typeck_results: Option<&'tcx ty::TypeckResults<'tcx>>,
     live_symbols: LocalDefIdSet,
-    repr_has_repr_c: bool,
+    repr_unconditionally_treats_fields_as_live: bool,
     repr_has_repr_simd: bool,
     in_pat: bool,
     ignore_variant_stack: Vec<DefId>,
@@ -365,15 +365,17 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
             return;
         }
 
-        let had_repr_c = self.repr_has_repr_c;
+        let unconditionally_treated_fields_as_live =
+            self.repr_unconditionally_treats_fields_as_live;
         let had_repr_simd = self.repr_has_repr_simd;
-        self.repr_has_repr_c = false;
+        self.repr_unconditionally_treats_fields_as_live = false;
         self.repr_has_repr_simd = false;
         match node {
             Node::Item(item) => match item.kind {
                 hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => {
                     let def = self.tcx.adt_def(item.owner_id);
-                    self.repr_has_repr_c = def.repr().c();
+                    self.repr_unconditionally_treats_fields_as_live =
+                        def.repr().c() || def.repr().transparent();
                     self.repr_has_repr_simd = def.repr().simd();
 
                     intravisit::walk_item(self, item)
@@ -411,7 +413,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
             _ => {}
         }
         self.repr_has_repr_simd = had_repr_simd;
-        self.repr_has_repr_c = had_repr_c;
+        self.repr_unconditionally_treats_fields_as_live = unconditionally_treated_fields_as_live;
     }
 
     fn mark_as_used_if_union(&mut self, adt: ty::AdtDef<'tcx>, fields: &[hir::ExprField<'_>]) {
@@ -435,11 +437,11 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
 
     fn visit_variant_data(&mut self, def: &'tcx hir::VariantData<'tcx>) {
         let tcx = self.tcx;
-        let has_repr_c = self.repr_has_repr_c;
+        let unconditionally_treat_fields_as_live = self.repr_unconditionally_treats_fields_as_live;
         let has_repr_simd = self.repr_has_repr_simd;
         let live_fields = def.fields().iter().filter_map(|f| {
             let def_id = f.def_id;
-            if has_repr_c || (f.is_positional() && has_repr_simd) {
+            if unconditionally_treat_fields_as_live || (f.is_positional() && has_repr_simd) {
                 return Some(def_id);
             }
             if !tcx.visibility(f.hir_id.owner.def_id).is_public() {
@@ -741,7 +743,7 @@ fn live_symbols_and_ignored_derived_traits(
         tcx,
         maybe_typeck_results: None,
         live_symbols: Default::default(),
-        repr_has_repr_c: false,
+        repr_unconditionally_treats_fields_as_live: false,
         repr_has_repr_simd: false,
         in_pat: false,
         ignore_variant_stack: vec![],
diff --git a/library/alloc/src/boxed/thin.rs b/library/alloc/src/boxed/thin.rs
index 9463b73b574..f83c8f83cc9 100644
--- a/library/alloc/src/boxed/thin.rs
+++ b/library/alloc/src/boxed/thin.rs
@@ -171,7 +171,6 @@ struct WithHeader<H>(NonNull<u8>, PhantomData<H>);
 /// An opaque representation of `WithHeader<H>` to avoid the
 /// projection invariance of `<T as Pointee>::Metadata`.
 #[repr(transparent)]
-#[allow(dead_code)] // Field only used through `WithHeader` type above.
 struct WithOpaqueHeader(NonNull<u8>);
 
 impl WithOpaqueHeader {
diff --git a/src/tools/miri/tests/fail/issue-miri-1112.rs b/src/tools/miri/tests/fail/issue-miri-1112.rs
index 9542673b0d9..387253a3f98 100644
--- a/src/tools/miri/tests/fail/issue-miri-1112.rs
+++ b/src/tools/miri/tests/fail/issue-miri-1112.rs
@@ -1,7 +1,7 @@
 trait Empty {}
 
 #[repr(transparent)]
-pub struct FunnyPointer(#[allow(dead_code)] dyn Empty);
+pub struct FunnyPointer(dyn Empty);
 
 #[repr(C)]
 pub struct Meta {
diff --git a/src/tools/miri/tests/fail/unaligned_pointers/drop_in_place.rs b/src/tools/miri/tests/fail/unaligned_pointers/drop_in_place.rs
index 2283231eb01..d71d5954a40 100644
--- a/src/tools/miri/tests/fail/unaligned_pointers/drop_in_place.rs
+++ b/src/tools/miri/tests/fail/unaligned_pointers/drop_in_place.rs
@@ -1,7 +1,7 @@
 //@compile-flags: -Cdebug-assertions=no
 
 #[repr(transparent)]
-struct HasDrop(#[allow(dead_code)] u8);
+struct HasDrop(u8);
 
 impl Drop for HasDrop {
     fn drop(&mut self) {}
diff --git a/tests/ui/consts/transmute-const.rs b/tests/ui/consts/transmute-const.rs
index 65e5700d083..5044d99ec51 100644
--- a/tests/ui/consts/transmute-const.rs
+++ b/tests/ui/consts/transmute-const.rs
@@ -3,7 +3,7 @@
 use std::mem;
 
 #[repr(transparent)]
-struct Foo(#[allow(dead_code)] u32);
+struct Foo(u32);
 
 const TRANSMUTED_U32: u32 = unsafe { mem::transmute(Foo(3)) };
 
diff --git a/tests/ui/layout/unsafe-cell-hides-niche.rs b/tests/ui/layout/unsafe-cell-hides-niche.rs
index 8d6cea10933..e87c402f8f9 100644
--- a/tests/ui/layout/unsafe-cell-hides-niche.rs
+++ b/tests/ui/layout/unsafe-cell-hides-niche.rs
@@ -17,7 +17,7 @@ use std::sync::{Mutex, RwLock};
 struct Wrapper<T>(#[allow(dead_code)] T);
 
 #[repr(transparent)]
-struct Transparent<T>(#[allow(dead_code)] T);
+struct Transparent<T>(T);
 
 struct NoNiche<T>(UnsafeCell<T>);
 
diff --git a/tests/ui/lint/dead-code/type-in-transparent.rs b/tests/ui/lint/dead-code/type-in-transparent.rs
new file mode 100644
index 00000000000..5dd6f93fd03
--- /dev/null
+++ b/tests/ui/lint/dead-code/type-in-transparent.rs
@@ -0,0 +1,14 @@
+// Verify that we do not warn on fields that are part of transparent types.
+// check-pass
+#![deny(dead_code)]
+
+#[repr(transparent)]
+struct NamedStruct { field: u8 }
+
+#[repr(transparent)]
+struct TupleStruct(u8);
+
+fn main() {
+    let _ = NamedStruct { field: 1 };
+    let _ = TupleStruct(1);
+}
diff --git a/tests/ui/packed/packed-struct-drop-aligned.rs b/tests/ui/packed/packed-struct-drop-aligned.rs
index 6c2907c86e9..ddfc86f74d3 100644
--- a/tests/ui/packed/packed-struct-drop-aligned.rs
+++ b/tests/ui/packed/packed-struct-drop-aligned.rs
@@ -24,7 +24,7 @@ impl<'a> Drop for Aligned<'a> {
 }
 
 #[repr(transparent)]
-struct NotCopy(#[allow(dead_code)] u8);
+struct NotCopy(u8);
 
 #[repr(packed)]
 struct Packed<'a>(NotCopy, Aligned<'a>);