From a175e8d90312a113869d366ba7dde0742df7f5e2 Mon Sep 17 00:00:00 2001
From: MarcoIeni <11428655+MarcoIeni@users.noreply.github.com>
Date: Mon, 20 Jan 2025 17:38:17 +0100
Subject: [PATCH 01/12] CI: free disk on linux arm runner

---
 src/ci/github-actions/jobs.yml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml
index 799ea3e9ad2df..ecd8642d76674 100644
--- a/src/ci/github-actions/jobs.yml
+++ b/src/ci/github-actions/jobs.yml
@@ -44,6 +44,8 @@ runners:
     <<: *base-job
 
   - &job-aarch64-linux
+    # Free some disk space to avoid running out of space during the build.
+    free_disk: true
     os: ubuntu-22.04-arm
 
 envs:

From fdb636e88b48ef8b3166d71ddca7332b625334c5 Mon Sep 17 00:00:00 2001
From: Wesley Wiser <wwiser@gmail.com>
Date: Mon, 20 Jan 2025 13:07:27 -0600
Subject: [PATCH 02/12] Add tests for windows-gnu split-debuginfo options

---
 .../windows_gnu_split_debuginfo_off.rs        | 29 +++++++++++++++++++
 ...u_split_debuginfo_packed.aarch64_gl.stderr |  4 +++
 ...s_gnu_split_debuginfo_packed.i686_g.stderr |  4 +++
 ..._gnu_split_debuginfo_packed.i686_gl.stderr |  4 +++
 ...u_split_debuginfo_packed.i686_uwp_g.stderr |  4 +++
 .../windows_gnu_split_debuginfo_packed.rs     | 29 +++++++++++++++++++
 ...gnu_split_debuginfo_packed.x86_64_g.stderr |  4 +++
 ...nu_split_debuginfo_packed.x86_64_gl.stderr |  4 +++
 ...split_debuginfo_packed.x86_64_uwp_g.stderr |  4 +++
 ...split_debuginfo_unpacked.aarch64_gl.stderr |  4 +++
 ...gnu_split_debuginfo_unpacked.i686_g.stderr |  4 +++
 ...nu_split_debuginfo_unpacked.i686_gl.stderr |  4 +++
 ...split_debuginfo_unpacked.i686_uwp_g.stderr |  4 +++
 .../windows_gnu_split_debuginfo_unpacked.rs   | 29 +++++++++++++++++++
 ...u_split_debuginfo_unpacked.x86_64_g.stderr |  4 +++
 ..._split_debuginfo_unpacked.x86_64_gl.stderr |  4 +++
 ...lit_debuginfo_unpacked.x86_64_uwp_g.stderr |  4 +++
 17 files changed, 143 insertions(+)
 create mode 100644 tests/ui/debuginfo/windows_gnu_split_debuginfo_off.rs
 create mode 100644 tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.aarch64_gl.stderr
 create mode 100644 tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.i686_g.stderr
 create mode 100644 tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.i686_gl.stderr
 create mode 100644 tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.i686_uwp_g.stderr
 create mode 100644 tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.rs
 create mode 100644 tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.x86_64_g.stderr
 create mode 100644 tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.x86_64_gl.stderr
 create mode 100644 tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.x86_64_uwp_g.stderr
 create mode 100644 tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.aarch64_gl.stderr
 create mode 100644 tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.i686_g.stderr
 create mode 100644 tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.i686_gl.stderr
 create mode 100644 tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.i686_uwp_g.stderr
 create mode 100644 tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.rs
 create mode 100644 tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.x86_64_g.stderr
 create mode 100644 tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.x86_64_gl.stderr
 create mode 100644 tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.x86_64_uwp_g.stderr

diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_off.rs b/tests/ui/debuginfo/windows_gnu_split_debuginfo_off.rs
new file mode 100644
index 0000000000000..3a8d9c998cf74
--- /dev/null
+++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_off.rs
@@ -0,0 +1,29 @@
+//@ revisions: aarch64_gl i686_g i686_gl i686_uwp_g x86_64_g x86_64_gl x86_64_uwp_g
+//@ compile-flags: --crate-type cdylib -Csplit-debuginfo=off
+//@ check-pass
+
+//@[aarch64_gl] compile-flags: --target aarch64-pc-windows-gnullvm
+//@[aarch64_gl] needs-llvm-components: aarch64
+
+//@[i686_g] compile-flags: --target i686-pc-windows-gnu
+//@[i686_g] needs-llvm-components: x86
+
+//@[i686_gl] compile-flags: --target i686-pc-windows-gnullvm
+//@[i686_gl] needs-llvm-components: x86
+
+//@[i686_uwp_g] compile-flags: --target i686-uwp-windows-gnu
+//@[i686_uwp_g] needs-llvm-components: x86
+
+//@[x86_64_g] compile-flags: --target x86_64-pc-windows-gnu
+//@[x86_64_g] needs-llvm-components: x86
+
+//@[x86_64_gl] compile-flags: --target x86_64-pc-windows-gnullvm
+//@[x86_64_gl] needs-llvm-components: x86
+
+//@[x86_64_uwp_g] compile-flags: --target x86_64-uwp-windows-gnu
+//@[x86_64_uwp_g] needs-llvm-components: x86
+
+#![feature(no_core)]
+
+#![no_core]
+#![no_std]
diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.aarch64_gl.stderr b/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.aarch64_gl.stderr
new file mode 100644
index 0000000000000..f3465e64976ea
--- /dev/null
+++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.aarch64_gl.stderr
@@ -0,0 +1,4 @@
+error: `-Csplit-debuginfo=packed` is unstable on this platform
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.i686_g.stderr b/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.i686_g.stderr
new file mode 100644
index 0000000000000..f3465e64976ea
--- /dev/null
+++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.i686_g.stderr
@@ -0,0 +1,4 @@
+error: `-Csplit-debuginfo=packed` is unstable on this platform
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.i686_gl.stderr b/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.i686_gl.stderr
new file mode 100644
index 0000000000000..f3465e64976ea
--- /dev/null
+++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.i686_gl.stderr
@@ -0,0 +1,4 @@
+error: `-Csplit-debuginfo=packed` is unstable on this platform
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.i686_uwp_g.stderr b/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.i686_uwp_g.stderr
new file mode 100644
index 0000000000000..f3465e64976ea
--- /dev/null
+++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.i686_uwp_g.stderr
@@ -0,0 +1,4 @@
+error: `-Csplit-debuginfo=packed` is unstable on this platform
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.rs b/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.rs
new file mode 100644
index 0000000000000..896bbac7d8e1e
--- /dev/null
+++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.rs
@@ -0,0 +1,29 @@
+//@ revisions: aarch64_gl i686_g i686_gl i686_uwp_g x86_64_g x86_64_gl x86_64_uwp_g
+//@ compile-flags: --crate-type cdylib -Csplit-debuginfo=packed
+//@ error-pattern: error: `-Csplit-debuginfo=packed` is unstable on this platform
+
+//@[aarch64_gl] compile-flags: --target aarch64-pc-windows-gnullvm
+//@[aarch64_gl] needs-llvm-components: aarch64
+
+//@[i686_g] compile-flags: --target i686-pc-windows-gnu
+//@[i686_g] needs-llvm-components: x86
+
+//@[i686_gl] compile-flags: --target i686-pc-windows-gnullvm
+//@[i686_gl] needs-llvm-components: x86
+
+//@[i686_uwp_g] compile-flags: --target i686-uwp-windows-gnu
+//@[i686_uwp_g] needs-llvm-components: x86
+
+//@[x86_64_g] compile-flags: --target x86_64-pc-windows-gnu
+//@[x86_64_g] needs-llvm-components: x86
+
+//@[x86_64_gl] compile-flags: --target x86_64-pc-windows-gnullvm
+//@[x86_64_gl] needs-llvm-components: x86
+
+//@[x86_64_uwp_g] compile-flags: --target x86_64-uwp-windows-gnu
+//@[x86_64_uwp_g] needs-llvm-components: x86
+
+#![feature(no_core)]
+
+#![no_core]
+#![no_std]
diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.x86_64_g.stderr b/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.x86_64_g.stderr
new file mode 100644
index 0000000000000..f3465e64976ea
--- /dev/null
+++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.x86_64_g.stderr
@@ -0,0 +1,4 @@
+error: `-Csplit-debuginfo=packed` is unstable on this platform
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.x86_64_gl.stderr b/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.x86_64_gl.stderr
new file mode 100644
index 0000000000000..f3465e64976ea
--- /dev/null
+++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.x86_64_gl.stderr
@@ -0,0 +1,4 @@
+error: `-Csplit-debuginfo=packed` is unstable on this platform
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.x86_64_uwp_g.stderr b/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.x86_64_uwp_g.stderr
new file mode 100644
index 0000000000000..f3465e64976ea
--- /dev/null
+++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.x86_64_uwp_g.stderr
@@ -0,0 +1,4 @@
+error: `-Csplit-debuginfo=packed` is unstable on this platform
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.aarch64_gl.stderr b/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.aarch64_gl.stderr
new file mode 100644
index 0000000000000..0964e21b13bc1
--- /dev/null
+++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.aarch64_gl.stderr
@@ -0,0 +1,4 @@
+error: `-Csplit-debuginfo=unpacked` is unstable on this platform
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.i686_g.stderr b/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.i686_g.stderr
new file mode 100644
index 0000000000000..0964e21b13bc1
--- /dev/null
+++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.i686_g.stderr
@@ -0,0 +1,4 @@
+error: `-Csplit-debuginfo=unpacked` is unstable on this platform
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.i686_gl.stderr b/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.i686_gl.stderr
new file mode 100644
index 0000000000000..0964e21b13bc1
--- /dev/null
+++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.i686_gl.stderr
@@ -0,0 +1,4 @@
+error: `-Csplit-debuginfo=unpacked` is unstable on this platform
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.i686_uwp_g.stderr b/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.i686_uwp_g.stderr
new file mode 100644
index 0000000000000..0964e21b13bc1
--- /dev/null
+++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.i686_uwp_g.stderr
@@ -0,0 +1,4 @@
+error: `-Csplit-debuginfo=unpacked` is unstable on this platform
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.rs b/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.rs
new file mode 100644
index 0000000000000..54a88c9121734
--- /dev/null
+++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.rs
@@ -0,0 +1,29 @@
+//@ revisions: aarch64_gl i686_g i686_gl i686_uwp_g x86_64_g x86_64_gl x86_64_uwp_g
+//@ compile-flags: --crate-type cdylib -Csplit-debuginfo=unpacked
+//@ error-pattern: error: `-Csplit-debuginfo=unpacked` is unstable on this platform
+
+//@[aarch64_gl] compile-flags: --target aarch64-pc-windows-gnullvm
+//@[aarch64_gl] needs-llvm-components: aarch64
+
+//@[i686_g] compile-flags: --target i686-pc-windows-gnu
+//@[i686_g] needs-llvm-components: x86
+
+//@[i686_gl] compile-flags: --target i686-pc-windows-gnullvm
+//@[i686_gl] needs-llvm-components: x86
+
+//@[i686_uwp_g] compile-flags: --target i686-uwp-windows-gnu
+//@[i686_uwp_g] needs-llvm-components: x86
+
+//@[x86_64_g] compile-flags: --target x86_64-pc-windows-gnu
+//@[x86_64_g] needs-llvm-components: x86
+
+//@[x86_64_gl] compile-flags: --target x86_64-pc-windows-gnullvm
+//@[x86_64_gl] needs-llvm-components: x86
+
+//@[x86_64_uwp_g] compile-flags: --target x86_64-uwp-windows-gnu
+//@[x86_64_uwp_g] needs-llvm-components: x86
+
+#![feature(no_core)]
+
+#![no_core]
+#![no_std]
diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.x86_64_g.stderr b/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.x86_64_g.stderr
new file mode 100644
index 0000000000000..0964e21b13bc1
--- /dev/null
+++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.x86_64_g.stderr
@@ -0,0 +1,4 @@
+error: `-Csplit-debuginfo=unpacked` is unstable on this platform
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.x86_64_gl.stderr b/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.x86_64_gl.stderr
new file mode 100644
index 0000000000000..0964e21b13bc1
--- /dev/null
+++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.x86_64_gl.stderr
@@ -0,0 +1,4 @@
+error: `-Csplit-debuginfo=unpacked` is unstable on this platform
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.x86_64_uwp_g.stderr b/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.x86_64_uwp_g.stderr
new file mode 100644
index 0000000000000..0964e21b13bc1
--- /dev/null
+++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.x86_64_uwp_g.stderr
@@ -0,0 +1,4 @@
+error: `-Csplit-debuginfo=unpacked` is unstable on this platform
+
+error: aborting due to 1 previous error
+

From 0b24fc99368ebfe9fa58e9b70785dc30ad2049bc Mon Sep 17 00:00:00 2001
From: Wesley Wiser <wwiser@gmail.com>
Date: Mon, 20 Jan 2025 14:02:35 -0600
Subject: [PATCH 03/12] Set `DebuginfoKind::Dwarf` for `*-windows-gnu` and
 `*-windows-gnullvm`

These targets have always generated DWARF debuginfo and not CodeView/PDB debuginfo
like the MSVC Windows targets. Correct their target definitions to reflect this.

The newly added tests for the various combinations of `*-windows-gnu*` targets and
`-Csplit-debuginfo` show that this does not change any stable behavior.
---
 compiler/rustc_target/src/spec/base/windows_gnu.rs     | 2 +-
 compiler/rustc_target/src/spec/base/windows_gnullvm.rs | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/compiler/rustc_target/src/spec/base/windows_gnu.rs b/compiler/rustc_target/src/spec/base/windows_gnu.rs
index e975102e2389a..d8b6ae8cf324e 100644
--- a/compiler/rustc_target/src/spec/base/windows_gnu.rs
+++ b/compiler/rustc_target/src/spec/base/windows_gnu.rs
@@ -97,9 +97,9 @@ pub(crate) fn opts() -> TargetOptions {
         emit_debug_gdb_scripts: false,
         requires_uwtable: true,
         eh_frame_header: false,
+        debuginfo_kind: DebuginfoKind::Dwarf,
         // FIXME(davidtwco): Support Split DWARF on Windows GNU - may require LLVM changes to
         // output DWO, despite using DWARF, doesn't use ELF..
-        debuginfo_kind: DebuginfoKind::Pdb,
         supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]),
         ..Default::default()
     }
diff --git a/compiler/rustc_target/src/spec/base/windows_gnullvm.rs b/compiler/rustc_target/src/spec/base/windows_gnullvm.rs
index 4f370ec8bd032..86e52117dbf75 100644
--- a/compiler/rustc_target/src/spec/base/windows_gnullvm.rs
+++ b/compiler/rustc_target/src/spec/base/windows_gnullvm.rs
@@ -44,9 +44,9 @@ pub(crate) fn opts() -> TargetOptions {
         has_thread_local: true,
         crt_static_allows_dylibs: true,
         crt_static_respected: true,
+        debuginfo_kind: DebuginfoKind::Dwarf,
         // FIXME(davidtwco): Support Split DWARF on Windows GNU - may require LLVM changes to
         // output DWO, despite using DWARF, doesn't use ELF..
-        debuginfo_kind: DebuginfoKind::Pdb,
         supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]),
         ..Default::default()
     }

From f0dfda124d436f01c57f70f26efc22d35ef3a9fa Mon Sep 17 00:00:00 2001
From: onur-ozkan <work@onurozkan.dev>
Date: Wed, 22 Jan 2025 16:50:15 +0300
Subject: [PATCH 04/12] fix outdated file path ref in llvm

This was added years ago and is outdated today.

Signed-off-by: onur-ozkan <work@onurozkan.dev>
---
 src/bootstrap/src/core/build_steps/llvm.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs
index cf55fff4078ac..3cf25373b8963 100644
--- a/src/bootstrap/src/core/build_steps/llvm.rs
+++ b/src/bootstrap/src/core/build_steps/llvm.rs
@@ -1338,7 +1338,7 @@ impl Step for CrtBeginEnd {
             .file(crtbegin_src)
             .file(crtend_src);
 
-        // Those flags are defined in src/llvm-project/compiler-rt/lib/crt/CMakeLists.txt
+        // Those flags are defined in src/llvm-project/compiler-rt/lib/builtins/CMakeLists.txt
         // Currently only consumer of those objects is musl, which use .init_array/.fini_array
         // instead of .ctors/.dtors
         cfg.flag("-std=c11")

From bae2a2f3b56b4540bf21e2aab888a945f38e1fe3 Mon Sep 17 00:00:00 2001
From: Pavel Grigorenko <GrigorenkoPV@ya.ru>
Date: Wed, 22 Jan 2025 18:36:33 +0300
Subject: [PATCH 05/12] Remove erroneous `unsafe` in
 `BTreeSet::upper_bound_mut`

---
 library/alloc/src/collections/btree/set.rs | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs
index 9660023d6945e..041f80c1f2c52 100644
--- a/library/alloc/src/collections/btree/set.rs
+++ b/library/alloc/src/collections/btree/set.rs
@@ -1442,20 +1442,20 @@ impl<T, A: Allocator + Clone> BTreeSet<T, A> {
     ///
     /// let mut set = BTreeSet::from([1, 2, 3, 4]);
     ///
-    /// let mut cursor = unsafe { set.upper_bound_mut(Bound::Included(&3)) };
+    /// let mut cursor = set.upper_bound_mut(Bound::Included(&3));
     /// assert_eq!(cursor.peek_prev(), Some(&3));
     /// assert_eq!(cursor.peek_next(), Some(&4));
     ///
-    /// let mut cursor = unsafe { set.upper_bound_mut(Bound::Excluded(&3)) };
+    /// let mut cursor = set.upper_bound_mut(Bound::Excluded(&3));
     /// assert_eq!(cursor.peek_prev(), Some(&2));
     /// assert_eq!(cursor.peek_next(), Some(&3));
     ///
-    /// let mut cursor = unsafe { set.upper_bound_mut(Bound::Unbounded) };
+    /// let mut cursor = set.upper_bound_mut(Bound::Unbounded);
     /// assert_eq!(cursor.peek_prev(), Some(&4));
     /// assert_eq!(cursor.peek_next(), None);
     /// ```
     #[unstable(feature = "btree_cursors", issue = "107540")]
-    pub unsafe fn upper_bound_mut<Q: ?Sized>(&mut self, bound: Bound<&Q>) -> CursorMut<'_, T, A>
+    pub fn upper_bound_mut<Q: ?Sized>(&mut self, bound: Bound<&Q>) -> CursorMut<'_, T, A>
     where
         T: Borrow<Q> + Ord,
         Q: Ord,

From 53578bdd194d41ac24fd4a5474601e3af2cb029d Mon Sep 17 00:00:00 2001
From: Marijn Schouten <hkBst@users.noreply.github.com>
Date: Wed, 22 Jan 2025 16:46:40 +0100
Subject: [PATCH 06/12] remove implied end of slice

---
 compiler/rustc_parse_format/src/lib.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs
index 9eb335cb34cc2..9a3e79c16b4df 100644
--- a/compiler/rustc_parse_format/src/lib.rs
+++ b/compiler/rustc_parse_format/src/lib.rs
@@ -545,7 +545,7 @@ impl<'a> Parser<'a> {
                 }
             }
         }
-        &self.input[start..self.input.len()]
+        &self.input[start..]
     }
 
     /// Parses an `Argument` structure, or what's contained within braces inside the format string.

From c568da9f161d1180fddbdfdcc1d1864ffa7619aa Mon Sep 17 00:00:00 2001
From: onur-ozkan <work@onurozkan.dev>
Date: Wed, 22 Jan 2025 19:36:17 +0300
Subject: [PATCH 07/12] make bootstrap self test to use bootstrap cargo

Signed-off-by: onur-ozkan <work@onurozkan.dev>
---
 src/bootstrap/src/core/build_steps/test.rs | 39 ++++++++++++++--------
 src/bootstrap/src/core/config/tests.rs     |  2 +-
 2 files changed, 26 insertions(+), 15 deletions(-)

diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index 9f3e4d9cc8995..5f9279624b383 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -3113,23 +3113,34 @@ impl Step for Bootstrap {
         // Use `python -m unittest` manually if you want to pass arguments.
         check_bootstrap.delay_failure().run(builder);
 
-        let mut cmd = command(&builder.initial_cargo);
-        cmd.arg("test")
-            .current_dir(builder.src.join("src/bootstrap"))
-            .env("RUSTFLAGS", "--cfg test -Cdebuginfo=2")
+        let mut cargo = tool::prepare_tool_cargo(
+            builder,
+            compiler,
+            Mode::ToolBootstrap,
+            host,
+            Kind::Test,
+            "src/bootstrap",
+            SourceType::InTree,
+            &[],
+        );
+
+        cargo
+            .rustflag("-Cdebuginfo=2")
             .env("CARGO_TARGET_DIR", builder.out.join("bootstrap"))
-            .env("RUSTC_BOOTSTRAP", "1")
-            .env("RUSTDOC", builder.rustdoc(compiler))
-            .env("RUSTC", &builder.initial_rustc);
-        if let Some(flags) = option_env!("RUSTFLAGS") {
-            // Use the same rustc flags for testing as for "normal" compilation,
-            // so that Cargo doesn’t recompile the entire dependency graph every time:
-            // https://github.com/rust-lang/rust/issues/49215
-            cmd.env("RUSTFLAGS", flags);
-        }
+            .env("RUSTC_BOOTSTRAP", "1");
+
         // bootstrap tests are racy on directory creation so just run them one at a time.
         // Since there's not many this shouldn't be a problem.
-        run_cargo_test(cmd, &["--test-threads=1"], &[], "bootstrap", None, compiler, host, builder);
+        run_cargo_test(
+            cargo,
+            &["--test-threads=1"],
+            &[],
+            "bootstrap",
+            None,
+            compiler,
+            host,
+            builder,
+        );
     }
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
diff --git a/src/bootstrap/src/core/config/tests.rs b/src/bootstrap/src/core/config/tests.rs
index c5e578ff351ef..f0a185ee3a7eb 100644
--- a/src/bootstrap/src/core/config/tests.rs
+++ b/src/bootstrap/src/core/config/tests.rs
@@ -92,7 +92,7 @@ fn detect_src_and_out() {
             //     `{build-dir}/bootstrap/debug/deps/bootstrap-c7ee91d5661e2804`
             // `{build-dir}` can be anywhere, not just in the rust project directory.
             let dep = Path::new(args.first().unwrap());
-            let expected_out = dep.ancestors().nth(4).unwrap();
+            let expected_out = dep.ancestors().nth(5).unwrap();
 
             assert_eq!(&cfg.out, expected_out);
         }

From 17b2ede40d61da7c699b47b522cb9909950c5dff Mon Sep 17 00:00:00 2001
From: onur-ozkan <work@onurozkan.dev>
Date: Wed, 22 Jan 2025 19:45:52 +0300
Subject: [PATCH 08/12] resolve clippy FIXME

Signed-off-by: onur-ozkan <work@onurozkan.dev>
---
 src/bootstrap/src/core/build_steps/test.rs | 62 ++++------------------
 src/bootstrap/src/core/builder/cargo.rs    |  4 ++
 2 files changed, 14 insertions(+), 52 deletions(-)

diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index 5f9279624b383..285376431b1bb 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -87,7 +87,7 @@ impl Step for CrateBootstrap {
             &[],
         );
         let crate_name = path.rsplit_once('/').unwrap().1;
-        run_cargo_test(cargo, &[], &[], crate_name, crate_name, compiler, bootstrap_host, builder);
+        run_cargo_test(cargo, &[], &[], crate_name, crate_name, bootstrap_host, builder);
     }
 }
 
@@ -143,7 +143,6 @@ You can skip linkcheck with --skip src/tools/linkchecker"
             &[],
             "linkchecker",
             "linkchecker self tests",
-            compiler,
             bootstrap_host,
             builder,
         );
@@ -397,7 +396,7 @@ impl Step for RustAnalyzer {
         cargo.env("SKIP_SLOW_TESTS", "1");
 
         cargo.add_rustc_lib_path(builder);
-        run_cargo_test(cargo, &[], &[], "rust-analyzer", "rust-analyzer", compiler, host, builder);
+        run_cargo_test(cargo, &[], &[], "rust-analyzer", "rust-analyzer", host, builder);
     }
 }
 
@@ -445,7 +444,7 @@ impl Step for Rustfmt {
 
         cargo.add_rustc_lib_path(builder);
 
-        run_cargo_test(cargo, &[], &[], "rustfmt", "rustfmt", compiler, host, builder);
+        run_cargo_test(cargo, &[], &[], "rustfmt", "rustfmt", host, builder);
     }
 }
 
@@ -713,16 +712,7 @@ impl Step for CompiletestTest {
             &[],
         );
         cargo.allow_features("test");
-        run_cargo_test(
-            cargo,
-            &[],
-            &[],
-            "compiletest",
-            "compiletest self test",
-            compiler,
-            host,
-            builder,
-        );
+        run_cargo_test(cargo, &[], &[], "compiletest", "compiletest self test", host, builder);
     }
 }
 
@@ -1294,7 +1284,6 @@ impl Step for CrateRunMakeSupport {
             &[],
             "run-make-support",
             "run-make-support self test",
-            compiler,
             host,
             builder,
         );
@@ -1334,16 +1323,7 @@ impl Step for CrateBuildHelper {
             &[],
         );
         cargo.allow_features("test");
-        run_cargo_test(
-            cargo,
-            &[],
-            &[],
-            "build_helper",
-            "build_helper self test",
-            compiler,
-            host,
-            builder,
-        );
+        run_cargo_test(cargo, &[], &[], "build_helper", "build_helper self test", host, builder);
     }
 }
 
@@ -2540,17 +2520,16 @@ impl Step for CrateLibrustc {
 /// Given a `cargo test` subcommand, add the appropriate flags and run it.
 ///
 /// Returns whether the test succeeded.
-#[allow(clippy::too_many_arguments)] // FIXME: reduce the number of args and remove this.
 fn run_cargo_test<'a>(
-    cargo: impl Into<BootstrapCommand>,
+    cargo: builder::Cargo,
     libtest_args: &[&str],
     crates: &[String],
     primary_crate: &str,
     description: impl Into<Option<&'a str>>,
-    compiler: Compiler,
     target: TargetSelection,
     builder: &Builder<'_>,
 ) -> bool {
+    let compiler = cargo.compiler();
     let mut cargo =
         prepare_cargo_test(cargo, libtest_args, crates, primary_crate, compiler, target, builder);
     let _time = helpers::timeit(builder);
@@ -2793,7 +2772,6 @@ impl Step for Crate {
             &self.crates,
             &self.crates[0],
             &*crate_description(&self.crates),
-            compiler,
             target,
             builder,
         );
@@ -2895,7 +2873,6 @@ impl Step for CrateRustdoc {
             &["rustdoc:0.0.0".to_string()],
             "rustdoc",
             "rustdoc",
-            compiler,
             target,
             builder,
         );
@@ -2956,7 +2933,6 @@ impl Step for CrateRustdocJsonTypes {
             &["rustdoc-json-types".to_string()],
             "rustdoc-json-types",
             "rustdoc-json-types",
-            compiler,
             target,
             builder,
         );
@@ -3131,16 +3107,7 @@ impl Step for Bootstrap {
 
         // bootstrap tests are racy on directory creation so just run them one at a time.
         // Since there's not many this shouldn't be a problem.
-        run_cargo_test(
-            cargo,
-            &["--test-threads=1"],
-            &[],
-            "bootstrap",
-            None,
-            compiler,
-            host,
-            builder,
-        );
+        run_cargo_test(cargo, &["--test-threads=1"], &[], "bootstrap", None, host, builder);
     }
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
@@ -3265,7 +3232,7 @@ impl Step for RustInstaller {
             bootstrap_host,
             bootstrap_host,
         );
-        run_cargo_test(cargo, &[], &[], "installer", None, compiler, bootstrap_host, builder);
+        run_cargo_test(cargo, &[], &[], "installer", None, bootstrap_host, builder);
 
         // We currently don't support running the test.sh script outside linux(?) environments.
         // Eventually this should likely migrate to #[test]s in rust-installer proper rather than a
@@ -3650,16 +3617,7 @@ impl Step for TestFloatParse {
             &[],
         );
 
-        run_cargo_test(
-            cargo_test,
-            &[],
-            &[],
-            crate_name,
-            crate_name,
-            compiler,
-            bootstrap_host,
-            builder,
-        );
+        run_cargo_test(cargo_test, &[], &[], crate_name, crate_name, bootstrap_host, builder);
 
         // Run the actual parse tests.
         let mut cargo_run = tool::prepare_tool_cargo(
diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs
index f9fb19ddb0952..6b792108784d9 100644
--- a/src/bootstrap/src/core/builder/cargo.rs
+++ b/src/bootstrap/src/core/builder/cargo.rs
@@ -121,6 +121,10 @@ impl Cargo {
         cargo
     }
 
+    pub fn compiler(&self) -> Compiler {
+        self.compiler
+    }
+
     pub fn into_cmd(self) -> BootstrapCommand {
         self.into()
     }

From e3a5314e0af1d802b01f26afaf983f7cba5e6003 Mon Sep 17 00:00:00 2001
From: onur-ozkan <work@onurozkan.dev>
Date: Wed, 22 Jan 2025 19:48:44 +0300
Subject: [PATCH 09/12] reduce number of `prepare_cargo_test` args

Signed-off-by: onur-ozkan <work@onurozkan.dev>
---
 src/bootstrap/src/core/build_steps/test.rs | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index 285376431b1bb..0d3ab6ad97d31 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -311,7 +311,7 @@ impl Step for Cargo {
         );
 
         // NOTE: can't use `run_cargo_test` because we need to overwrite `PATH`
-        let mut cargo = prepare_cargo_test(cargo, &[], &[], "cargo", compiler, self.host, builder);
+        let mut cargo = prepare_cargo_test(cargo, &[], &[], "cargo", self.host, builder);
 
         // Don't run cross-compile tests, we may not have cross-compiled libstd libs
         // available.
@@ -564,7 +564,7 @@ impl Step for Miri {
 
         // We can NOT use `run_cargo_test` since Miri's integration tests do not use the usual test
         // harness and therefore do not understand the flags added by `add_flags_and_try_run_test`.
-        let mut cargo = prepare_cargo_test(cargo, &[], &[], "miri", host_compiler, host, builder);
+        let mut cargo = prepare_cargo_test(cargo, &[], &[], "miri", host, builder);
 
         // miri tests need to know about the stage sysroot
         cargo.env("MIRI_SYSROOT", &miri_sysroot);
@@ -759,7 +759,7 @@ impl Step for Clippy {
         cargo.env("HOST_LIBS", host_libs);
 
         cargo.add_rustc_lib_path(builder);
-        let cargo = prepare_cargo_test(cargo, &[], &[], "clippy", compiler, host, builder);
+        let cargo = prepare_cargo_test(cargo, &[], &[], "clippy", host, builder);
 
         let _guard = builder.msg_sysroot_tool(Kind::Test, compiler.stage, "clippy", host, host);
 
@@ -2530,8 +2530,7 @@ fn run_cargo_test<'a>(
     builder: &Builder<'_>,
 ) -> bool {
     let compiler = cargo.compiler();
-    let mut cargo =
-        prepare_cargo_test(cargo, libtest_args, crates, primary_crate, compiler, target, builder);
+    let mut cargo = prepare_cargo_test(cargo, libtest_args, crates, primary_crate, target, builder);
     let _time = helpers::timeit(builder);
     let _group = description.into().and_then(|what| {
         builder.msg_sysroot_tool(Kind::Test, compiler.stage, what, compiler.host, target)
@@ -2552,15 +2551,15 @@ fn run_cargo_test<'a>(
 
 /// Given a `cargo test` subcommand, pass it the appropriate test flags given a `builder`.
 fn prepare_cargo_test(
-    cargo: impl Into<BootstrapCommand>,
+    cargo: builder::Cargo,
     libtest_args: &[&str],
     crates: &[String],
     primary_crate: &str,
-    compiler: Compiler,
     target: TargetSelection,
     builder: &Builder<'_>,
 ) -> BootstrapCommand {
-    let mut cargo = cargo.into();
+    let compiler = cargo.compiler();
+    let mut cargo: BootstrapCommand = cargo.into();
 
     // Propagate `--bless` if it has not already been set/unset
     // Any tools that want to use this should bless if `RUSTC_BLESS` is set to

From cd2ecc4b5007c128441d6fdc645a1e0f47808666 Mon Sep 17 00:00:00 2001
From: Amy Kwan <amy.kwan1@ibm.com>
Date: Wed, 15 Jan 2025 14:49:16 -0500
Subject: [PATCH 10/12] [AIX] Lint on structs that have a different alignment
 in AIX's C ABI

---
 compiler/rustc_lint/messages.ftl             |   2 +
 compiler/rustc_lint/src/lints.rs             |   4 +
 compiler/rustc_lint/src/types.rs             | 134 +++++++++++++++-
 tests/ui/layout/reprc-power-alignment.rs     | 152 +++++++++++++++++++
 tests/ui/layout/reprc-power-alignment.stderr | 112 ++++++++++++++
 tests/ui/lint/clashing-extern-fn.rs          |   1 +
 tests/ui/lint/clashing-extern-fn.stderr      |  22 +--
 7 files changed, 411 insertions(+), 16 deletions(-)
 create mode 100644 tests/ui/layout/reprc-power-alignment.rs
 create mode 100644 tests/ui/layout/reprc-power-alignment.stderr

diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index 7522e21d0ef09..868ffdc14238d 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -970,6 +970,8 @@ lint_unused_result = unused result of type `{$ty}`
 
 lint_use_let_underscore_ignore_suggestion = use `let _ = ...` to ignore the expression or result
 
+lint_uses_power_alignment = repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+
 lint_variant_size_differences =
     enum variant is more than three times larger ({$largest} bytes) than the next largest
 
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index ac995b59caff1..32af126f364f9 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -1692,6 +1692,10 @@ pub(crate) struct OverflowingLiteral<'a> {
     pub lit: String,
 }
 
+#[derive(LintDiagnostic)]
+#[diag(lint_uses_power_alignment)]
+pub(crate) struct UsesPowerAlignment;
+
 #[derive(LintDiagnostic)]
 #[diag(lint_unused_comparisons)]
 pub(crate) struct UnusedComparisons;
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index 3bd27a224e77c..0757e6840c6d0 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -1,14 +1,15 @@
 use std::iter;
 use std::ops::ControlFlow;
 
-use rustc_abi::{BackendRepr, ExternAbi, TagEncoding, Variants, WrappingRange};
+use rustc_abi::{BackendRepr, ExternAbi, TagEncoding, VariantIdx, Variants, WrappingRange};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::DiagMessage;
 use rustc_hir::{Expr, ExprKind, LangItem};
 use rustc_middle::bug;
 use rustc_middle::ty::layout::{LayoutOf, SizeSkeleton};
 use rustc_middle::ty::{
-    self, AdtKind, GenericArgsRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
+    self, Adt, AdtKind, GenericArgsRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable,
+    TypeVisitableExt,
 };
 use rustc_session::{declare_lint, declare_lint_pass, impl_lint_pass};
 use rustc_span::def_id::LocalDefId;
@@ -23,7 +24,7 @@ use crate::lints::{
     AmbiguousWidePointerComparisonsAddrSuggestion, AtomicOrderingFence, AtomicOrderingLoad,
     AtomicOrderingStore, ImproperCTypes, InvalidAtomicOrderingDiag, InvalidNanComparisons,
     InvalidNanComparisonsSuggestion, UnpredictableFunctionPointerComparisons,
-    UnpredictableFunctionPointerComparisonsSuggestion, UnusedComparisons,
+    UnpredictableFunctionPointerComparisonsSuggestion, UnusedComparisons, UsesPowerAlignment,
     VariantSizeDifferencesDiag,
 };
 use crate::{LateContext, LateLintPass, LintContext, fluent_generated as fluent};
@@ -727,7 +728,60 @@ declare_lint! {
     "proper use of libc types in foreign item definitions"
 }
 
-declare_lint_pass!(ImproperCTypesDefinitions => [IMPROPER_CTYPES_DEFINITIONS]);
+declare_lint! {
+    /// The `uses_power_alignment` lint detects specific `repr(C)`
+    /// aggregates on AIX.
+    /// In its platform C ABI, AIX uses the "power" (as in PowerPC) alignment
+    /// rule (detailed in https://www.ibm.com/docs/en/xl-c-and-cpp-aix/16.1?topic=data-using-alignment-modes#alignment),
+    /// which can also be set for XLC by `#pragma align(power)` or
+    /// `-qalign=power`. Aggregates with a floating-point type as the
+    /// recursively first field (as in "at offset 0") modify the layout of
+    /// *subsequent* fields of the associated structs to use an alignment value
+    /// where the floating-point type is aligned on a 4-byte boundary.
+    ///
+    /// The power alignment rule for structs needed for C compatibility is
+    /// unimplementable within `repr(C)` in the compiler without building in
+    /// handling of references to packed fields and infectious nested layouts,
+    /// so a warning is produced in these situations.
+    ///
+    /// ### Example
+    ///
+    /// ```rust,ignore (fails on non-powerpc64-ibm-aix)
+    /// #[repr(C)]
+    /// pub struct Floats {
+    ///     a: f64,
+    ///     b: u8,
+    ///     c: f64,
+    /// }
+    /// ```
+    ///
+    /// This will produce:
+    ///
+    /// ```text
+    /// warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+    ///  --> <source>:5:3
+    ///   |
+    /// 5 |   c: f64,
+    ///   |   ^^^^^^
+    ///   |
+    ///   = note: `#[warn(uses_power_alignment)]` on by default
+    /// ```
+    ///
+    /// ### Explanation
+    ///
+    /// The power alignment rule specifies that the above struct has the
+    /// following alignment:
+    ///  - offset_of!(Floats, a) == 0
+    ///  - offset_of!(Floats, b) == 8
+    ///  - offset_of!(Floats, c) == 12
+    /// However, rust currently aligns `c` at offset_of!(Floats, c) == 16.
+    /// Thus, a warning should be produced for the above struct in this case.
+    USES_POWER_ALIGNMENT,
+    Warn,
+    "Structs do not follow the power alignment rule under repr(C)"
+}
+
+declare_lint_pass!(ImproperCTypesDefinitions => [IMPROPER_CTYPES_DEFINITIONS, USES_POWER_ALIGNMENT]);
 
 #[derive(Clone, Copy)]
 pub(crate) enum CItemKind {
@@ -1539,6 +1593,71 @@ impl ImproperCTypesDefinitions {
             vis.check_type_for_ffi_and_report_errors(span, fn_ptr_ty, true, false);
         }
     }
+
+    fn check_arg_for_power_alignment<'tcx>(
+        &mut self,
+        cx: &LateContext<'tcx>,
+        ty: Ty<'tcx>,
+    ) -> bool {
+        // Structs (under repr(C)) follow the power alignment rule if:
+        //   - the first field of the struct is a floating-point type that
+        //     is greater than 4-bytes, or
+        //   - the first field of the struct is an aggregate whose
+        //     recursively first field is a floating-point type greater than
+        //     4 bytes.
+        if cx.tcx.sess.target.os != "aix" {
+            return false;
+        }
+        if ty.is_floating_point() && ty.primitive_size(cx.tcx).bytes() > 4 {
+            return true;
+        } else if let Adt(adt_def, _) = ty.kind()
+            && adt_def.is_struct()
+        {
+            let struct_variant = adt_def.variant(VariantIdx::ZERO);
+            // Within a nested struct, all fields are examined to correctly
+            // report if any fields after the nested struct within the
+            // original struct are misaligned.
+            for struct_field in &struct_variant.fields {
+                let field_ty = cx.tcx.type_of(struct_field.did).instantiate_identity();
+                if self.check_arg_for_power_alignment(cx, field_ty) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    fn check_struct_for_power_alignment<'tcx>(
+        &mut self,
+        cx: &LateContext<'tcx>,
+        item: &'tcx hir::Item<'tcx>,
+    ) {
+        let adt_def = cx.tcx.adt_def(item.owner_id.to_def_id());
+        if adt_def.repr().c()
+            && !adt_def.repr().packed()
+            && cx.tcx.sess.target.os == "aix"
+            && !adt_def.all_fields().next().is_none()
+        {
+            let struct_variant_data = item.expect_struct().0;
+            for (index, ..) in struct_variant_data.fields().iter().enumerate() {
+                // Struct fields (after the first field) are checked for the
+                // power alignment rule, as fields after the first are likely
+                // to be the fields that are misaligned.
+                if index != 0 {
+                    let first_field_def = struct_variant_data.fields()[index];
+                    let def_id = first_field_def.def_id;
+                    let ty = cx.tcx.type_of(def_id).instantiate_identity();
+                    if self.check_arg_for_power_alignment(cx, ty) {
+                        cx.emit_span_lint(
+                            USES_POWER_ALIGNMENT,
+                            first_field_def.span,
+                            UsesPowerAlignment,
+                        );
+                    }
+                }
+            }
+        }
+    }
 }
 
 /// `ImproperCTypesDefinitions` checks items outside of foreign items (e.g. stuff that isn't in
@@ -1562,8 +1681,13 @@ impl<'tcx> LateLintPass<'tcx> for ImproperCTypesDefinitions {
             }
             // See `check_fn`..
             hir::ItemKind::Fn { .. } => {}
+            // Structs are checked based on if they follow the power alignment
+            // rule (under repr(C)).
+            hir::ItemKind::Struct(..) => {
+                self.check_struct_for_power_alignment(cx, item);
+            }
             // See `check_field_def`..
-            hir::ItemKind::Union(..) | hir::ItemKind::Struct(..) | hir::ItemKind::Enum(..) => {}
+            hir::ItemKind::Union(..) | hir::ItemKind::Enum(..) => {}
             // Doesn't define something that can contain a external type to be checked.
             hir::ItemKind::Impl(..)
             | hir::ItemKind::TraitAlias(..)
diff --git a/tests/ui/layout/reprc-power-alignment.rs b/tests/ui/layout/reprc-power-alignment.rs
new file mode 100644
index 0000000000000..f6c1df55988ba
--- /dev/null
+++ b/tests/ui/layout/reprc-power-alignment.rs
@@ -0,0 +1,152 @@
+//@ check-pass
+//@ compile-flags: --target powerpc64-ibm-aix
+//@ needs-llvm-components: powerpc
+//@ add-core-stubs
+#![feature(no_core)]
+#![no_core]
+#![no_std]
+
+extern crate minicore;
+use minicore::*;
+
+#[warn(uses_power_alignment)]
+
+#[repr(C)]
+pub struct Floats {
+    a: f64,
+    b: u8,
+    c: f64, //~ WARNING repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+    d: f32,
+}
+
+pub struct Floats2 {
+    a: f64,
+    b: u32,
+    c: f64,
+}
+
+#[repr(C)]
+pub struct Floats3 {
+    a: f32,
+    b: f32,
+    c: i64,
+}
+
+#[repr(C)]
+pub struct Floats4 {
+    a: u64,
+    b: u32,
+    c: f32,
+}
+
+#[repr(C)]
+pub struct Floats5 {
+    a: f32,
+    b: f64, //~ WARNING repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+    c: f32,
+}
+
+#[repr(C)]
+pub struct FloatAgg1 {
+    x: Floats,
+    y: f64, //~ WARNING repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+}
+
+#[repr(C)]
+pub struct FloatAgg2 {
+    x: i64,
+    y: Floats, //~ WARNING repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+}
+
+#[repr(C)]
+pub struct FloatAgg3 {
+    x: FloatAgg1,
+    // NOTE: the "power" alignment rule is infectious to nested struct fields.
+    y: FloatAgg2, //~ WARNING repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+    z: FloatAgg2, //~ WARNING repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+}
+
+#[repr(C)]
+pub struct FloatAgg4 {
+    x: FloatAgg1,
+    y: FloatAgg2, //~ WARNING repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+}
+
+#[repr(C)]
+pub struct FloatAgg5 {
+    x: FloatAgg1,
+    y: FloatAgg2, //~ WARNING repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+    z: FloatAgg3, //~ WARNING repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+}
+
+#[repr(C)]
+pub struct FloatAgg6 {
+    x: i64,
+    y: Floats, //~ WARNING repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+    z: u8,
+}
+
+#[repr(C)]
+pub struct FloatAgg7 {
+    x: i64,
+    y: Floats, //~ WARNING repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+    z: u8,
+    zz: f32,
+}
+
+#[repr(C)]
+pub struct A {
+  d: f64,
+}
+#[repr(C)]
+pub struct B {
+  a: A,
+  f: f32,
+  d: f64, //~ WARNING repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+}
+#[repr(C)]
+pub struct C {
+  c: u8,
+  b: B, //~ WARNING repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+}
+#[repr(C)]
+pub struct D {
+  x: f64,
+}
+#[repr(C)]
+pub struct E {
+  x: i32,
+  d: D, //~ WARNING repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+}
+#[repr(C)]
+pub struct F {
+  a: u8,
+  b: f64, //~ WARNING repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+}
+#[repr(C)]
+pub struct G {
+    a: u8,
+    b: u8,
+    c: f64, //~ WARNING repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+    d: f32,
+    e: f64, //~ WARNING repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+}
+// Should not warn on #[repr(packed)].
+#[repr(packed)]
+pub struct H {
+    a: u8,
+    b: u8,
+    c: f64,
+    d: f32,
+    e: f64,
+}
+#[repr(C, packed)]
+pub struct I {
+    a: u8,
+    b: u8,
+    c: f64,
+    d: f32,
+    e: f64,
+}
+
+fn main() { }
diff --git a/tests/ui/layout/reprc-power-alignment.stderr b/tests/ui/layout/reprc-power-alignment.stderr
new file mode 100644
index 0000000000000..18664e4d655d3
--- /dev/null
+++ b/tests/ui/layout/reprc-power-alignment.stderr
@@ -0,0 +1,112 @@
+warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+  --> $DIR/reprc-power-alignment.rs:18:5
+   |
+LL |     c: f64,
+   |     ^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/reprc-power-alignment.rs:12:8
+   |
+LL | #[warn(uses_power_alignment)]
+   |        ^^^^^^^^^^^^^^^^^^^^
+
+warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+  --> $DIR/reprc-power-alignment.rs:45:5
+   |
+LL |     b: f64,
+   |     ^^^^^^
+   |
+   = note: `#[warn(uses_power_alignment)]` on by default
+
+warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+  --> $DIR/reprc-power-alignment.rs:52:5
+   |
+LL |     y: f64,
+   |     ^^^^^^
+
+warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+  --> $DIR/reprc-power-alignment.rs:58:5
+   |
+LL |     y: Floats,
+   |     ^^^^^^^^^
+
+warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+  --> $DIR/reprc-power-alignment.rs:65:5
+   |
+LL |     y: FloatAgg2,
+   |     ^^^^^^^^^^^^
+
+warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+  --> $DIR/reprc-power-alignment.rs:66:5
+   |
+LL |     z: FloatAgg2,
+   |     ^^^^^^^^^^^^
+
+warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+  --> $DIR/reprc-power-alignment.rs:72:5
+   |
+LL |     y: FloatAgg2,
+   |     ^^^^^^^^^^^^
+
+warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+  --> $DIR/reprc-power-alignment.rs:78:5
+   |
+LL |     y: FloatAgg2,
+   |     ^^^^^^^^^^^^
+
+warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+  --> $DIR/reprc-power-alignment.rs:79:5
+   |
+LL |     z: FloatAgg3,
+   |     ^^^^^^^^^^^^
+
+warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+  --> $DIR/reprc-power-alignment.rs:85:5
+   |
+LL |     y: Floats,
+   |     ^^^^^^^^^
+
+warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+  --> $DIR/reprc-power-alignment.rs:92:5
+   |
+LL |     y: Floats,
+   |     ^^^^^^^^^
+
+warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+  --> $DIR/reprc-power-alignment.rs:105:3
+   |
+LL |   d: f64,
+   |   ^^^^^^
+
+warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+  --> $DIR/reprc-power-alignment.rs:110:3
+   |
+LL |   b: B,
+   |   ^^^^
+
+warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+  --> $DIR/reprc-power-alignment.rs:119:3
+   |
+LL |   d: D,
+   |   ^^^^
+
+warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+  --> $DIR/reprc-power-alignment.rs:124:3
+   |
+LL |   b: f64,
+   |   ^^^^^^
+
+warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+  --> $DIR/reprc-power-alignment.rs:130:5
+   |
+LL |     c: f64,
+   |     ^^^^^^
+
+warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+  --> $DIR/reprc-power-alignment.rs:132:5
+   |
+LL |     e: f64,
+   |     ^^^^^^
+
+warning: 17 warnings emitted
+
diff --git a/tests/ui/lint/clashing-extern-fn.rs b/tests/ui/lint/clashing-extern-fn.rs
index a12fe81eecdaf..9bbb20246df9d 100644
--- a/tests/ui/lint/clashing-extern-fn.rs
+++ b/tests/ui/lint/clashing-extern-fn.rs
@@ -248,6 +248,7 @@ mod sameish_members {
 
 mod same_sized_members_clash {
     mod a {
+        #[allow(uses_power_alignment)]
         #[repr(C)]
         struct Point3 {
             x: f32,
diff --git a/tests/ui/lint/clashing-extern-fn.stderr b/tests/ui/lint/clashing-extern-fn.stderr
index b30dd476a1d74..48dd1adbc1fa2 100644
--- a/tests/ui/lint/clashing-extern-fn.stderr
+++ b/tests/ui/lint/clashing-extern-fn.stderr
@@ -1,5 +1,5 @@
 warning: `extern` block uses type `Option<TransparentNoNiche>`, which is not FFI-safe
-  --> $DIR/clashing-extern-fn.rs:482:55
+  --> $DIR/clashing-extern-fn.rs:483:55
    |
 LL |             fn hidden_niche_transparent_no_niche() -> Option<TransparentNoNiche>;
    |                                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -9,7 +9,7 @@ LL |             fn hidden_niche_transparent_no_niche() -> Option<TransparentNoN
    = note: `#[warn(improper_ctypes)]` on by default
 
 warning: `extern` block uses type `Option<UnsafeCell<NonZero<usize>>>`, which is not FFI-safe
-  --> $DIR/clashing-extern-fn.rs:486:46
+  --> $DIR/clashing-extern-fn.rs:487:46
    |
 LL |             fn hidden_niche_unsafe_cell() -> Option<UnsafeCell<NonZero<usize>>>;
    |                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -151,7 +151,7 @@ LL |             fn draw_point(p: Point);
               found `unsafe extern "C" fn(sameish_members::b::Point)`
 
 warning: `origin` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:269:13
+  --> $DIR/clashing-extern-fn.rs:270:13
    |
 LL |             fn origin() -> Point3;
    |             ---------------------- `origin` previously declared here
@@ -163,7 +163,7 @@ LL |             fn origin() -> Point3;
               found `unsafe extern "C" fn() -> same_sized_members_clash::b::Point3`
 
 warning: `transparent_incorrect` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:292:13
+  --> $DIR/clashing-extern-fn.rs:293:13
    |
 LL |             fn transparent_incorrect() -> T;
    |             -------------------------------- `transparent_incorrect` previously declared here
@@ -175,7 +175,7 @@ LL |             fn transparent_incorrect() -> isize;
               found `unsafe extern "C" fn() -> isize`
 
 warning: `missing_return_type` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:310:13
+  --> $DIR/clashing-extern-fn.rs:311:13
    |
 LL |             fn missing_return_type() -> usize;
    |             ---------------------------------- `missing_return_type` previously declared here
@@ -187,7 +187,7 @@ LL |             fn missing_return_type();
               found `unsafe extern "C" fn()`
 
 warning: `non_zero_usize` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:328:13
+  --> $DIR/clashing-extern-fn.rs:329:13
    |
 LL |             fn non_zero_usize() -> core::num::NonZero<usize>;
    |             ------------------------------------------------- `non_zero_usize` previously declared here
@@ -199,7 +199,7 @@ LL |             fn non_zero_usize() -> usize;
               found `unsafe extern "C" fn() -> usize`
 
 warning: `non_null_ptr` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:330:13
+  --> $DIR/clashing-extern-fn.rs:331:13
    |
 LL |             fn non_null_ptr() -> core::ptr::NonNull<usize>;
    |             ----------------------------------------------- `non_null_ptr` previously declared here
@@ -211,7 +211,7 @@ LL |             fn non_null_ptr() -> *const usize;
               found `unsafe extern "C" fn() -> *const usize`
 
 warning: `option_non_zero_usize_incorrect` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:424:13
+  --> $DIR/clashing-extern-fn.rs:425:13
    |
 LL |             fn option_non_zero_usize_incorrect() -> usize;
    |             ---------------------------------------------- `option_non_zero_usize_incorrect` previously declared here
@@ -223,7 +223,7 @@ LL |             fn option_non_zero_usize_incorrect() -> isize;
               found `unsafe extern "C" fn() -> isize`
 
 warning: `option_non_null_ptr_incorrect` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:426:13
+  --> $DIR/clashing-extern-fn.rs:427:13
    |
 LL |             fn option_non_null_ptr_incorrect() -> *const usize;
    |             --------------------------------------------------- `option_non_null_ptr_incorrect` previously declared here
@@ -235,7 +235,7 @@ LL |             fn option_non_null_ptr_incorrect() -> *const isize;
               found `unsafe extern "C" fn() -> *const isize`
 
 warning: `hidden_niche_transparent_no_niche` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:482:13
+  --> $DIR/clashing-extern-fn.rs:483:13
    |
 LL |             fn hidden_niche_transparent_no_niche() -> usize;
    |             ------------------------------------------------ `hidden_niche_transparent_no_niche` previously declared here
@@ -247,7 +247,7 @@ LL |             fn hidden_niche_transparent_no_niche() -> Option<TransparentNoN
               found `unsafe extern "C" fn() -> Option<TransparentNoNiche>`
 
 warning: `hidden_niche_unsafe_cell` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:486:13
+  --> $DIR/clashing-extern-fn.rs:487:13
    |
 LL |             fn hidden_niche_unsafe_cell() -> usize;
    |             --------------------------------------- `hidden_niche_unsafe_cell` previously declared here

From 72fa87445670046d64222980ec9988bf6975fc56 Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Wed, 25 Dec 2024 03:10:54 +0000
Subject: [PATCH 11/12] Don't ICE in coerce when autoderef fails to
 structurally normalize non-WF type in new solver

---
 compiler/rustc_hir_typeck/src/coercion.rs     | 14 +++++--
 .../next-solver/non-wf-in-coerce-pointers.rs  | 17 ++++++++
 .../non-wf-in-coerce-pointers.stderr          | 39 +++++++++++++++++++
 3 files changed, 67 insertions(+), 3 deletions(-)
 create mode 100644 tests/ui/traits/next-solver/non-wf-in-coerce-pointers.rs
 create mode 100644 tests/ui/traits/next-solver/non-wf-in-coerce-pointers.stderr

diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index 6945dbc321697..720f51c0be6f7 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -461,9 +461,17 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
         // to the target type), since that should be the least
         // confusing.
         let Some(InferOk { value: ty, mut obligations }) = found else {
-            let err = first_error.expect("coerce_borrowed_pointer had no error");
-            debug!("coerce_borrowed_pointer: failed with err = {:?}", err);
-            return Err(err);
+            if let Some(first_error) = first_error {
+                debug!("coerce_borrowed_pointer: failed with err = {:?}", first_error);
+                return Err(first_error);
+            } else {
+                // This may happen in the new trait solver since autoderef requires
+                // the pointee to be structurally normalizable, or else it'll just bail.
+                // So when we have a type like `&<not well formed>`, then we get no
+                // autoderef steps (even though there should be at least one). That means
+                // we get no type mismatches, since the loop above just exits early.
+                return Err(TypeError::Mismatch);
+            }
         };
 
         if ty == a && mt_a.mutbl.is_not() && autoderef.step_count() == 1 {
diff --git a/tests/ui/traits/next-solver/non-wf-in-coerce-pointers.rs b/tests/ui/traits/next-solver/non-wf-in-coerce-pointers.rs
new file mode 100644
index 0000000000000..d05def2cb757d
--- /dev/null
+++ b/tests/ui/traits/next-solver/non-wf-in-coerce-pointers.rs
@@ -0,0 +1,17 @@
+//@ compile-flags: -Znext-solver
+
+trait Wf {
+    type Assoc;
+}
+
+struct S {
+    f: &'static <() as Wf>::Assoc,
+    //~^ ERROR the trait bound `(): Wf` is not satisfied
+}
+
+fn main() {
+    let x: S = todo!();
+    let y: &() = x.f;
+    //~^ ERROR mismatched types
+    //~| ERROR the trait bound `(): Wf` is not satisfied
+}
diff --git a/tests/ui/traits/next-solver/non-wf-in-coerce-pointers.stderr b/tests/ui/traits/next-solver/non-wf-in-coerce-pointers.stderr
new file mode 100644
index 0000000000000..32a7766a638da
--- /dev/null
+++ b/tests/ui/traits/next-solver/non-wf-in-coerce-pointers.stderr
@@ -0,0 +1,39 @@
+error[E0277]: the trait bound `(): Wf` is not satisfied
+  --> $DIR/non-wf-in-coerce-pointers.rs:8:17
+   |
+LL |     f: &'static <() as Wf>::Assoc,
+   |                 ^^^^^^^^^^^^^^^^^ the trait `Wf` is not implemented for `()`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/non-wf-in-coerce-pointers.rs:3:1
+   |
+LL | trait Wf {
+   | ^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/non-wf-in-coerce-pointers.rs:14:18
+   |
+LL |     let y: &() = x.f;
+   |            ---   ^^^ types differ
+   |            |
+   |            expected due to this
+   |
+   = note: expected reference `&()`
+              found reference `&'static <() as Wf>::Assoc`
+
+error[E0277]: the trait bound `(): Wf` is not satisfied
+  --> $DIR/non-wf-in-coerce-pointers.rs:14:18
+   |
+LL |     let y: &() = x.f;
+   |                  ^^^ the trait `Wf` is not implemented for `()`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/non-wf-in-coerce-pointers.rs:3:1
+   |
+LL | trait Wf {
+   | ^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0277, E0308.
+For more information about an error, try `rustc --explain E0277`.

From 0149c0fdd8ca67ab0e6c1bca0fac0ad6eaa8c002 Mon Sep 17 00:00:00 2001
From: Alona Enraght-Moony <code@alona.page>
Date: Wed, 22 Jan 2025 20:01:17 +0000
Subject: [PATCH 12/12] rustdoc-json-types: Finalize dyn compatibility renaming

---
 src/rustdoc-json-types/lib.rs | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs
index 5a99977ded5eb..916f0ab3cc85b 100644
--- a/src/rustdoc-json-types/lib.rs
+++ b/src/rustdoc-json-types/lib.rs
@@ -1099,8 +1099,7 @@ pub struct Trait {
     pub is_auto: bool,
     /// Whether the trait is marked as `unsafe`.
     pub is_unsafe: bool,
-    // FIXME(dyn_compat_renaming): Update the URL once the Reference is updated and hits stable.
-    /// Whether the trait is [dyn compatible](https://doc.rust-lang.org/reference/items/traits.html#object-safety)[^1].
+    /// Whether the trait is [dyn compatible](https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility)[^1].
     ///
     /// [^1]: Formerly known as "object safe".
     pub is_dyn_compatible: bool,