From efdf2192d0005b6ae6dd56bd0a2b04ebd04244eb Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Tue, 30 Jul 2024 12:28:57 -0400
Subject: [PATCH] Revert "Rollup merge of #128104 -
 mu001999-contrib:fix/128053, r=petrochenkov"

This reverts commit 91b18a058c4661f82e420b633dc0a3e1ccd14b88, reversing
changes made to 9aedec9313dc8ecf9bdcb5f09c4eb0ad8b9a4875.
---
 compiler/rustc_passes/src/dead.rs             | 36 +++++++++----------
 ...lone-debug-dead-code-in-the-same-struct.rs |  4 +--
 ...-debug-dead-code-in-the-same-struct.stderr | 16 ++-------
 .../dead-code/unconstructible-pub-struct.rs   | 35 ------------------
 .../unconstructible-pub-struct.stderr         | 14 --------
 5 files changed, 22 insertions(+), 83 deletions(-)
 delete mode 100644 tests/ui/lint/dead-code/unconstructible-pub-struct.rs
 delete mode 100644 tests/ui/lint/dead-code/unconstructible-pub-struct.stderr

diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index 8a931fc4158e3..3b1a796130c43 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -73,26 +73,24 @@ fn adt_of<'tcx>(ty: &hir::Ty<'tcx>) -> Option<(LocalDefId, DefKind)> {
 }
 
 fn struct_all_fields_are_public(tcx: TyCtxt<'_>, id: LocalDefId) -> bool {
-    let adt_def = tcx.adt_def(id);
-
-    // skip types contain fields of unit and never type,
-    // it's usually intentional to make the type not constructible
-    let not_require_constructor = adt_def.all_fields().any(|field| {
+    // treat PhantomData and positional ZST as public,
+    // we don't want to lint types which only have them,
+    // cause it's a common way to use such types to check things like well-formedness
+    tcx.adt_def(id).all_fields().all(|field| {
         let field_type = tcx.type_of(field.did).instantiate_identity();
-        field_type.is_unit() || field_type.is_never()
-    });
-
-    not_require_constructor
-        || adt_def.all_fields().all(|field| {
-            let field_type = tcx.type_of(field.did).instantiate_identity();
-            // skip fields of PhantomData,
-            // cause it's a common way to check things like well-formedness
-            if field_type.is_phantom_data() {
-                return true;
-            }
-
-            field.vis.is_public()
-        })
+        if field_type.is_phantom_data() {
+            return true;
+        }
+        let is_positional = field.name.as_str().starts_with(|c: char| c.is_ascii_digit());
+        if is_positional
+            && tcx
+                .layout_of(tcx.param_env(field.did).and(field_type))
+                .map_or(true, |layout| layout.is_zst())
+        {
+            return true;
+        }
+        field.vis.is_public()
+    })
 }
 
 /// check struct and its fields are public or not,
diff --git a/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.rs b/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.rs
index 6ab1fb7b039bd..885dacc727af6 100644
--- a/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.rs
+++ b/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.rs
@@ -1,9 +1,9 @@
 #![forbid(dead_code)]
 
 #[derive(Debug)]
-pub struct Whatever {
+pub struct Whatever { //~ ERROR struct `Whatever` is never constructed
     pub field0: (),
-    field1: (), //~ ERROR fields `field1`, `field2`, `field3`, and `field4` are never read
+    field1: (),
     field2: (),
     field3: (),
     field4: (),
diff --git a/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr b/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr
index e9b757b6bae72..e10d28ad03a4e 100644
--- a/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr
+++ b/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr
@@ -1,19 +1,9 @@
-error: fields `field1`, `field2`, `field3`, and `field4` are never read
-  --> $DIR/clone-debug-dead-code-in-the-same-struct.rs:6:5
+error: struct `Whatever` is never constructed
+  --> $DIR/clone-debug-dead-code-in-the-same-struct.rs:4:12
    |
 LL | pub struct Whatever {
-   |            -------- fields in this struct
-LL |     pub field0: (),
-LL |     field1: (),
-   |     ^^^^^^
-LL |     field2: (),
-   |     ^^^^^^
-LL |     field3: (),
-   |     ^^^^^^
-LL |     field4: (),
-   |     ^^^^^^
+   |            ^^^^^^^^
    |
-   = note: `Whatever` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis
 note: the lint level is defined here
   --> $DIR/clone-debug-dead-code-in-the-same-struct.rs:1:11
    |
diff --git a/tests/ui/lint/dead-code/unconstructible-pub-struct.rs b/tests/ui/lint/dead-code/unconstructible-pub-struct.rs
deleted file mode 100644
index 2202cbb673098..0000000000000
--- a/tests/ui/lint/dead-code/unconstructible-pub-struct.rs
+++ /dev/null
@@ -1,35 +0,0 @@
-#![feature(never_type)]
-#![deny(dead_code)]
-
-pub struct T1(!);
-pub struct T2(());
-pub struct T3<X>(std::marker::PhantomData<X>);
-
-pub struct T4 {
-    _x: !,
-}
-
-pub struct T5<X> {
-    _x: !,
-    _y: X,
-}
-
-pub struct T6 {
-    _x: (),
-}
-
-pub struct T7<X> {
-    _x: (),
-    _y: X,
-}
-
-pub struct T8<X> {
-    _x: std::marker::PhantomData<X>,
-}
-
-pub struct T9<X> { //~ ERROR struct `T9` is never constructed
-    _x: std::marker::PhantomData<X>,
-    _y: i32,
-}
-
-fn main() {}
diff --git a/tests/ui/lint/dead-code/unconstructible-pub-struct.stderr b/tests/ui/lint/dead-code/unconstructible-pub-struct.stderr
deleted file mode 100644
index a3dde042bbe15..0000000000000
--- a/tests/ui/lint/dead-code/unconstructible-pub-struct.stderr
+++ /dev/null
@@ -1,14 +0,0 @@
-error: struct `T9` is never constructed
-  --> $DIR/unconstructible-pub-struct.rs:30:12
-   |
-LL | pub struct T9<X> {
-   |            ^^
-   |
-note: the lint level is defined here
-  --> $DIR/unconstructible-pub-struct.rs:2:9
-   |
-LL | #![deny(dead_code)]
-   |         ^^^^^^^^^
-
-error: aborting due to 1 previous error
-