From 42c9c109fe1a794ff959111f6be52d0d2ec17642 Mon Sep 17 00:00:00 2001
From: Mu001999 <mu001999@outlook.com>
Date: Sat, 25 Jan 2025 14:25:10 +0800
Subject: [PATCH 01/19] Remove unused trait BoundedSize

---
 library/core/src/iter/adapters/flatten.rs | 55 -----------------------
 1 file changed, 55 deletions(-)

diff --git a/library/core/src/iter/adapters/flatten.rs b/library/core/src/iter/adapters/flatten.rs
index 9b9353b800a98..a820045521b9f 100644
--- a/library/core/src/iter/adapters/flatten.rs
+++ b/library/core/src/iter/adapters/flatten.rs
@@ -172,61 +172,6 @@ where
     }
 }
 
-/// Marker trait for iterators/iterables which have a statically known upper
-/// bound of the number of items they can produce.
-///
-/// # Safety
-///
-/// Implementations must not yield more elements than indicated by UPPER_BOUND if it is `Some`.
-/// Used in specializations.  Implementations must not be conditional on lifetimes or
-/// user-implementable traits.
-#[rustc_specialization_trait]
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe trait BoundedSize {
-    const UPPER_BOUND: Option<NonZero<usize>> = NonZero::new(1);
-}
-
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<T> BoundedSize for Option<T> {}
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<T> BoundedSize for option::IntoIter<T> {}
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<T, U> BoundedSize for Result<T, U> {}
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<T> BoundedSize for result::IntoIter<T> {}
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<T> BoundedSize for Once<T> {}
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<T> BoundedSize for OnceWith<T> {}
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<T, const N: usize> BoundedSize for [T; N] {
-    const UPPER_BOUND: Option<NonZero<usize>> = NonZero::new(N);
-}
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<T, const N: usize> BoundedSize for array::IntoIter<T, N> {
-    const UPPER_BOUND: Option<NonZero<usize>> = NonZero::new(N);
-}
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<I: BoundedSize, P> BoundedSize for Filter<I, P> {
-    const UPPER_BOUND: Option<NonZero<usize>> = I::UPPER_BOUND;
-}
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<I: BoundedSize, P> BoundedSize for FilterMap<I, P> {
-    const UPPER_BOUND: Option<NonZero<usize>> = I::UPPER_BOUND;
-}
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<I: BoundedSize, F> BoundedSize for Map<I, F> {
-    const UPPER_BOUND: Option<NonZero<usize>> = I::UPPER_BOUND;
-}
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<I: BoundedSize> BoundedSize for Copied<I> {
-    const UPPER_BOUND: Option<NonZero<usize>> = I::UPPER_BOUND;
-}
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<I: BoundedSize> BoundedSize for Cloned<I> {
-    const UPPER_BOUND: Option<NonZero<usize>> = I::UPPER_BOUND;
-}
-
 /// An iterator that flattens one level of nesting in an iterator of things
 /// that can be turned into iterators.
 ///

From 28bd22c3d9a477ff9b7b85782fb517c29b58ed88 Mon Sep 17 00:00:00 2001
From: clubby789 <jamie@hill-daniel.co.uk>
Date: Sun, 9 Mar 2025 23:42:48 +0000
Subject: [PATCH 02/19] rustdoc: Gate unstable `doc(cfg())` predicates

---
 src/librustdoc/clean/cfg.rs              | 14 ++++----------
 src/librustdoc/clean/types.rs            |  7 +++++++
 src/librustdoc/doctest/rust.rs           |  2 +-
 tests/rustdoc-ui/doc-cfg-unstable.rs     | 10 ++++++++++
 tests/rustdoc-ui/doc-cfg-unstable.stderr | 23 +++++++++++++++++++++++
 5 files changed, 45 insertions(+), 11 deletions(-)
 create mode 100644 tests/rustdoc-ui/doc-cfg-unstable.rs
 create mode 100644 tests/rustdoc-ui/doc-cfg-unstable.stderr

diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs
index ab169f3c2a4d5..1541e7201cefd 100644
--- a/src/librustdoc/clean/cfg.rs
+++ b/src/librustdoc/clean/cfg.rs
@@ -8,7 +8,6 @@ use std::{mem, ops};
 
 use rustc_ast::{LitKind, MetaItem, MetaItemInner, MetaItemKind, MetaItemLit};
 use rustc_data_structures::fx::FxHashSet;
-use rustc_feature::Features;
 use rustc_session::parse::ParseSess;
 use rustc_span::Span;
 use rustc_span::symbol::{Symbol, sym};
@@ -132,18 +131,13 @@ impl Cfg {
     /// Checks whether the given configuration can be matched in the current session.
     ///
     /// Equivalent to `attr::cfg_matches`.
-    // FIXME: Actually make use of `features`.
-    pub(crate) fn matches(&self, psess: &ParseSess, features: Option<&Features>) -> bool {
+    pub(crate) fn matches(&self, psess: &ParseSess) -> bool {
         match *self {
             Cfg::False => false,
             Cfg::True => true,
-            Cfg::Not(ref child) => !child.matches(psess, features),
-            Cfg::All(ref sub_cfgs) => {
-                sub_cfgs.iter().all(|sub_cfg| sub_cfg.matches(psess, features))
-            }
-            Cfg::Any(ref sub_cfgs) => {
-                sub_cfgs.iter().any(|sub_cfg| sub_cfg.matches(psess, features))
-            }
+            Cfg::Not(ref child) => !child.matches(psess),
+            Cfg::All(ref sub_cfgs) => sub_cfgs.iter().all(|sub_cfg| sub_cfg.matches(psess)),
+            Cfg::Any(ref sub_cfgs) => sub_cfgs.iter().any(|sub_cfg| sub_cfg.matches(psess)),
             Cfg::Cfg(name, value) => psess.config.contains(&(name, value)),
         }
     }
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 9e9cd52883491..e70511a798a3f 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -1056,6 +1056,13 @@ pub(crate) fn extract_cfg_from_attrs<'a, I: Iterator<Item = &'a hir::Attribute>
                         .meta_item()
                         .and_then(|item| rustc_expand::config::parse_cfg(item, sess))
                     {
+                        // The result is unused here but we can gate unstable predicates
+                        rustc_attr_parsing::cfg_matches(
+                            cfg_mi,
+                            tcx.sess,
+                            rustc_ast::CRATE_NODE_ID,
+                            Some(tcx.features()),
+                        );
                         match Cfg::parse(cfg_mi) {
                             Ok(new_cfg) => cfg &= new_cfg,
                             Err(e) => {
diff --git a/src/librustdoc/doctest/rust.rs b/src/librustdoc/doctest/rust.rs
index 907e2a3eb2fcd..b12c516a827d6 100644
--- a/src/librustdoc/doctest/rust.rs
+++ b/src/librustdoc/doctest/rust.rs
@@ -98,7 +98,7 @@ impl HirCollector<'_> {
         let ast_attrs = self.tcx.hir().attrs(self.tcx.local_def_id_to_hir_id(def_id));
         if let Some(ref cfg) =
             extract_cfg_from_attrs(ast_attrs.iter(), self.tcx, &FxHashSet::default())
-            && !cfg.matches(&self.tcx.sess.psess, Some(self.tcx.features()))
+            && !cfg.matches(&self.tcx.sess.psess)
         {
             return;
         }
diff --git a/tests/rustdoc-ui/doc-cfg-unstable.rs b/tests/rustdoc-ui/doc-cfg-unstable.rs
new file mode 100644
index 0000000000000..14c2e83ec8540
--- /dev/null
+++ b/tests/rustdoc-ui/doc-cfg-unstable.rs
@@ -0,0 +1,10 @@
+// #138113: rustdoc didn't gate unstable predicates inside `doc(cfg(..))`
+#![feature(doc_cfg)]
+
+// `cfg_boolean_literals`
+#[doc(cfg(false))] //~ ERROR `cfg(false)` is experimental and subject to change
+pub fn cfg_boolean_literals() {}
+
+// `cfg_version`
+#[doc(cfg(sanitize = "thread"))] //~ ERROR `cfg(sanitize)` is experimental and subject to change
+pub fn cfg_sanitize() {}
diff --git a/tests/rustdoc-ui/doc-cfg-unstable.stderr b/tests/rustdoc-ui/doc-cfg-unstable.stderr
new file mode 100644
index 0000000000000..54de3b178edb6
--- /dev/null
+++ b/tests/rustdoc-ui/doc-cfg-unstable.stderr
@@ -0,0 +1,23 @@
+error[E0658]: `cfg(false)` is experimental and subject to change
+  --> $DIR/doc-cfg-unstable.rs:5:11
+   |
+LL | #[doc(cfg(false))]
+   |           ^^^^^
+   |
+   = note: see issue #131204 <https://github.com/rust-lang/rust/issues/131204> for more information
+   = help: add `#![feature(cfg_boolean_literals)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: `cfg(sanitize)` is experimental and subject to change
+  --> $DIR/doc-cfg-unstable.rs:9:11
+   |
+LL | #[doc(cfg(sanitize = "thread"))]
+   |           ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #39699 <https://github.com/rust-lang/rust/issues/39699> for more information
+   = help: add `#![feature(cfg_sanitize)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.

From 85b1116a18595794da07c53642eefd81ff775faf Mon Sep 17 00:00:00 2001
From: clubby789 <jamie@hill-daniel.co.uk>
Date: Mon, 10 Mar 2025 15:58:41 +0000
Subject: [PATCH 03/19] rustdoc: Add FIXME test for `doc_cfg` interaction with
 `check_cfg`

---
 tests/rustdoc-ui/doc-cfg-check-cfg.rs | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)
 create mode 100644 tests/rustdoc-ui/doc-cfg-check-cfg.rs

diff --git a/tests/rustdoc-ui/doc-cfg-check-cfg.rs b/tests/rustdoc-ui/doc-cfg-check-cfg.rs
new file mode 100644
index 0000000000000..e3420dc078978
--- /dev/null
+++ b/tests/rustdoc-ui/doc-cfg-check-cfg.rs
@@ -0,0 +1,16 @@
+// Ensure that `doc(cfg())` respects `check-cfg`
+// Currently not properly working
+#![feature(doc_cfg)]
+#![deny(unexpected_cfgs)]
+
+//@revisions: no_check cfg_empty cfg_foo
+//@[cfg_empty] compile-flags: --check-cfg cfg()
+//@[cfg_foo] compile-flags: --check-cfg cfg(foo)
+
+//@[no_check] check-pass
+//@[cfg_empty] check-pass
+//@[cfg_empty] known-bug: #138358
+//@[cfg_foo] check-pass
+
+#[doc(cfg(foo))]
+pub fn foo() {}

From 1cdddd67a333fd8e70334395ad33694a575037b4 Mon Sep 17 00:00:00 2001
From: Scott McMurray <scottmcm@users.noreply.github.com>
Date: Wed, 26 Feb 2025 17:40:06 -0800
Subject: [PATCH 04/19] Add MIR pre-codegen tests to track 138544

---
 tests/mir-opt/pre-codegen/checked_ops.rs      | 39 ++++++++++-
 ...b_at_home.PreCodegen.after.panic-abort.mir | 48 +++++++++++++
 ..._at_home.PreCodegen.after.panic-unwind.mir | 48 +++++++++++++
 ...ecked_sub.PreCodegen.after.panic-abort.mir | 44 ++++++++++++
 ...cked_sub.PreCodegen.after.panic-unwind.mir | 44 ++++++++++++
 ...mple_option_map.ezmap.PreCodegen.after.mir |  2 +-
 ...map_via_question_mark.PreCodegen.after.mir | 70 +++++++++++++++++++
 .../mir-opt/pre-codegen/simple_option_map.rs  | 24 ++++++-
 8 files changed, 315 insertions(+), 4 deletions(-)
 create mode 100644 tests/mir-opt/pre-codegen/checked_ops.saturating_sub_at_home.PreCodegen.after.panic-abort.mir
 create mode 100644 tests/mir-opt/pre-codegen/checked_ops.saturating_sub_at_home.PreCodegen.after.panic-unwind.mir
 create mode 100644 tests/mir-opt/pre-codegen/checked_ops.use_checked_sub.PreCodegen.after.panic-abort.mir
 create mode 100644 tests/mir-opt/pre-codegen/checked_ops.use_checked_sub.PreCodegen.after.panic-unwind.mir
 create mode 100644 tests/mir-opt/pre-codegen/simple_option_map.map_via_question_mark.PreCodegen.after.mir

diff --git a/tests/mir-opt/pre-codegen/checked_ops.rs b/tests/mir-opt/pre-codegen/checked_ops.rs
index 56f8e3f833845..8fd340503f548 100644
--- a/tests/mir-opt/pre-codegen/checked_ops.rs
+++ b/tests/mir-opt/pre-codegen/checked_ops.rs
@@ -1,4 +1,3 @@
-// skip-filecheck
 //@ compile-flags: -O -Zmir-opt-level=2
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 
@@ -8,10 +7,48 @@
 // EMIT_MIR checked_ops.step_forward.PreCodegen.after.mir
 pub fn step_forward(x: u16, n: usize) -> u16 {
     // This uses `u16` so that the conversion to usize is always widening.
+
+    // CHECK-LABEL: fn step_forward
+    // CHECK: inlined{{.+}}forward
     std::iter::Step::forward(x, n)
 }
 
 // EMIT_MIR checked_ops.checked_shl.PreCodegen.after.mir
 pub fn checked_shl(x: u32, rhs: u32) -> Option<u32> {
+    // CHECK-LABEL: fn checked_shl
+    // CHECK: [[TEMP:_[0-9]+]] = ShlUnchecked(copy _1, copy _2)
+    // CHECK: _0 = Option::<u32>::Some({{move|copy}} [[TEMP]])
     x.checked_shl(rhs)
 }
+
+// EMIT_MIR checked_ops.use_checked_sub.PreCodegen.after.mir
+pub fn use_checked_sub(x: u32, rhs: u32) {
+    // We want this to be equivalent to open-coding it, leaving no `Option`s around.
+    // FIXME(#138544): It's not yet.
+
+    // CHECK-LABEL: fn use_checked_sub
+    // CHECK: inlined{{.+}}u32{{.+}}checked_sub
+    // CHECK: [[DELTA:_[0-9]+]] = SubUnchecked(copy _1, copy _2)
+    // CHECK: [[TEMP1:_.+]] = Option::<u32>::Some(move [[DELTA]]);
+    // CHECK: [[TEMP2:_.+]] = {{move|copy}} (([[TEMP1]] as Some).0: u32);
+    // CHECK: do_something({{move|copy}} [[TEMP2]])
+    if let Some(delta) = x.checked_sub(rhs) {
+        do_something(delta);
+    }
+}
+
+// EMIT_MIR checked_ops.saturating_sub_at_home.PreCodegen.after.mir
+pub fn saturating_sub_at_home(lhs: u32, rhs: u32) -> u32 {
+    // FIXME(#138544): Similarly here, the `Option` ought to optimize away
+
+    // CHECK-LABEL: fn saturating_sub_at_home
+    // CHECK: [[DELTA:_[0-9]+]] = SubUnchecked(copy _1, copy _2)
+    // CHECK: [[TEMP1:_.+]] = Option::<u32>::Some({{move|copy}} [[DELTA]]);
+    // CHECK: [[TEMP2:_.+]] = {{move|copy}} (([[TEMP1]] as Some).0: u32);
+    // CHECK: _0 = {{move|copy}} [[TEMP2]];
+    u32::checked_sub(lhs, rhs).unwrap_or(0)
+}
+
+unsafe extern "Rust" {
+    safe fn do_something(_: u32);
+}
diff --git a/tests/mir-opt/pre-codegen/checked_ops.saturating_sub_at_home.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/checked_ops.saturating_sub_at_home.PreCodegen.after.panic-abort.mir
new file mode 100644
index 0000000000000..5b4fdeda85731
--- /dev/null
+++ b/tests/mir-opt/pre-codegen/checked_ops.saturating_sub_at_home.PreCodegen.after.panic-abort.mir
@@ -0,0 +1,48 @@
+// MIR for `saturating_sub_at_home` after PreCodegen
+
+fn saturating_sub_at_home(_1: u32, _2: u32) -> u32 {
+    debug lhs => _1;
+    debug rhs => _2;
+    let mut _0: u32;
+    let mut _5: std::option::Option<u32>;
+    scope 1 (inlined core::num::<impl u32>::checked_sub) {
+        let mut _3: bool;
+        let mut _4: u32;
+    }
+    scope 2 (inlined Option::<u32>::unwrap_or) {
+        let _6: u32;
+        scope 3 {
+        }
+    }
+
+    bb0: {
+        StorageLive(_5);
+        StorageLive(_3);
+        _3 = Lt(copy _1, copy _2);
+        switchInt(move _3) -> [0: bb1, otherwise: bb2];
+    }
+
+    bb1: {
+        StorageLive(_4);
+        _4 = SubUnchecked(copy _1, copy _2);
+        _5 = Option::<u32>::Some(move _4);
+        StorageDead(_4);
+        StorageDead(_3);
+        StorageLive(_6);
+        _6 = move ((_5 as Some).0: u32);
+        _0 = move _6;
+        StorageDead(_6);
+        goto -> bb3;
+    }
+
+    bb2: {
+        StorageDead(_3);
+        _0 = const 0_u32;
+        goto -> bb3;
+    }
+
+    bb3: {
+        StorageDead(_5);
+        return;
+    }
+}
diff --git a/tests/mir-opt/pre-codegen/checked_ops.saturating_sub_at_home.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/checked_ops.saturating_sub_at_home.PreCodegen.after.panic-unwind.mir
new file mode 100644
index 0000000000000..5b4fdeda85731
--- /dev/null
+++ b/tests/mir-opt/pre-codegen/checked_ops.saturating_sub_at_home.PreCodegen.after.panic-unwind.mir
@@ -0,0 +1,48 @@
+// MIR for `saturating_sub_at_home` after PreCodegen
+
+fn saturating_sub_at_home(_1: u32, _2: u32) -> u32 {
+    debug lhs => _1;
+    debug rhs => _2;
+    let mut _0: u32;
+    let mut _5: std::option::Option<u32>;
+    scope 1 (inlined core::num::<impl u32>::checked_sub) {
+        let mut _3: bool;
+        let mut _4: u32;
+    }
+    scope 2 (inlined Option::<u32>::unwrap_or) {
+        let _6: u32;
+        scope 3 {
+        }
+    }
+
+    bb0: {
+        StorageLive(_5);
+        StorageLive(_3);
+        _3 = Lt(copy _1, copy _2);
+        switchInt(move _3) -> [0: bb1, otherwise: bb2];
+    }
+
+    bb1: {
+        StorageLive(_4);
+        _4 = SubUnchecked(copy _1, copy _2);
+        _5 = Option::<u32>::Some(move _4);
+        StorageDead(_4);
+        StorageDead(_3);
+        StorageLive(_6);
+        _6 = move ((_5 as Some).0: u32);
+        _0 = move _6;
+        StorageDead(_6);
+        goto -> bb3;
+    }
+
+    bb2: {
+        StorageDead(_3);
+        _0 = const 0_u32;
+        goto -> bb3;
+    }
+
+    bb3: {
+        StorageDead(_5);
+        return;
+    }
+}
diff --git a/tests/mir-opt/pre-codegen/checked_ops.use_checked_sub.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/checked_ops.use_checked_sub.PreCodegen.after.panic-abort.mir
new file mode 100644
index 0000000000000..3c475cd403091
--- /dev/null
+++ b/tests/mir-opt/pre-codegen/checked_ops.use_checked_sub.PreCodegen.after.panic-abort.mir
@@ -0,0 +1,44 @@
+// MIR for `use_checked_sub` after PreCodegen
+
+fn use_checked_sub(_1: u32, _2: u32) -> () {
+    debug x => _1;
+    debug rhs => _2;
+    let mut _0: ();
+    let mut _5: std::option::Option<u32>;
+    let _7: ();
+    scope 1 {
+        debug delta => _6;
+        let _6: u32;
+        scope 2 (inlined core::num::<impl u32>::checked_sub) {
+            let mut _3: bool;
+            let mut _4: u32;
+        }
+    }
+
+    bb0: {
+        StorageLive(_5);
+        StorageLive(_3);
+        _3 = Lt(copy _1, copy _2);
+        switchInt(move _3) -> [0: bb1, otherwise: bb2];
+    }
+
+    bb1: {
+        StorageLive(_4);
+        _4 = SubUnchecked(copy _1, copy _2);
+        _5 = Option::<u32>::Some(move _4);
+        StorageDead(_4);
+        StorageDead(_3);
+        _6 = copy ((_5 as Some).0: u32);
+        _7 = do_something(move _6) -> [return: bb3, unwind unreachable];
+    }
+
+    bb2: {
+        StorageDead(_3);
+        goto -> bb3;
+    }
+
+    bb3: {
+        StorageDead(_5);
+        return;
+    }
+}
diff --git a/tests/mir-opt/pre-codegen/checked_ops.use_checked_sub.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/checked_ops.use_checked_sub.PreCodegen.after.panic-unwind.mir
new file mode 100644
index 0000000000000..3ef09764b1c5b
--- /dev/null
+++ b/tests/mir-opt/pre-codegen/checked_ops.use_checked_sub.PreCodegen.after.panic-unwind.mir
@@ -0,0 +1,44 @@
+// MIR for `use_checked_sub` after PreCodegen
+
+fn use_checked_sub(_1: u32, _2: u32) -> () {
+    debug x => _1;
+    debug rhs => _2;
+    let mut _0: ();
+    let mut _5: std::option::Option<u32>;
+    let _7: ();
+    scope 1 {
+        debug delta => _6;
+        let _6: u32;
+        scope 2 (inlined core::num::<impl u32>::checked_sub) {
+            let mut _3: bool;
+            let mut _4: u32;
+        }
+    }
+
+    bb0: {
+        StorageLive(_5);
+        StorageLive(_3);
+        _3 = Lt(copy _1, copy _2);
+        switchInt(move _3) -> [0: bb1, otherwise: bb2];
+    }
+
+    bb1: {
+        StorageLive(_4);
+        _4 = SubUnchecked(copy _1, copy _2);
+        _5 = Option::<u32>::Some(move _4);
+        StorageDead(_4);
+        StorageDead(_3);
+        _6 = copy ((_5 as Some).0: u32);
+        _7 = do_something(move _6) -> [return: bb3, unwind continue];
+    }
+
+    bb2: {
+        StorageDead(_3);
+        goto -> bb3;
+    }
+
+    bb3: {
+        StorageDead(_5);
+        return;
+    }
+}
diff --git a/tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir
index cbfc58194cc1f..7595ad88d9df4 100644
--- a/tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir
@@ -3,7 +3,7 @@
 fn ezmap(_1: Option<i32>) -> Option<i32> {
     debug x => _1;
     let mut _0: std::option::Option<i32>;
-    scope 1 (inlined map::<i32, i32, {closure@$DIR/simple_option_map.rs:17:12: 17:15}>) {
+    scope 1 (inlined map::<i32, i32, {closure@$DIR/simple_option_map.rs:23:12: 23:15}>) {
         let mut _2: isize;
         let _3: i32;
         let mut _4: i32;
diff --git a/tests/mir-opt/pre-codegen/simple_option_map.map_via_question_mark.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/simple_option_map.map_via_question_mark.PreCodegen.after.mir
new file mode 100644
index 0000000000000..b921b96966b29
--- /dev/null
+++ b/tests/mir-opt/pre-codegen/simple_option_map.map_via_question_mark.PreCodegen.after.mir
@@ -0,0 +1,70 @@
+// MIR for `map_via_question_mark` after PreCodegen
+
+fn map_via_question_mark(_1: Option<i32>) -> Option<i32> {
+    debug x => _1;
+    let mut _0: std::option::Option<i32>;
+    let mut _4: std::ops::ControlFlow<std::option::Option<std::convert::Infallible>, i32>;
+    let _5: i32;
+    let mut _6: i32;
+    scope 1 {
+        debug residual => const Option::<Infallible>::None;
+        scope 2 {
+            scope 7 (inlined <Option<i32> as FromResidual<Option<Infallible>>>::from_residual) {
+            }
+        }
+    }
+    scope 3 {
+        debug val => _5;
+        scope 4 {
+        }
+    }
+    scope 5 (inlined <Option<i32> as Try>::branch) {
+        let mut _2: isize;
+        let _3: i32;
+        scope 6 {
+        }
+    }
+
+    bb0: {
+        StorageLive(_6);
+        StorageLive(_4);
+        StorageLive(_2);
+        StorageLive(_3);
+        _2 = discriminant(_1);
+        switchInt(move _2) -> [0: bb1, 1: bb2, otherwise: bb4];
+    }
+
+    bb1: {
+        StorageDead(_3);
+        StorageDead(_2);
+        _0 = const Option::<i32>::None;
+        StorageDead(_6);
+        StorageDead(_4);
+        goto -> bb3;
+    }
+
+    bb2: {
+        _3 = copy ((_1 as Some).0: i32);
+        _4 = ControlFlow::<Option<Infallible>, i32>::Continue(copy _3);
+        StorageDead(_3);
+        StorageDead(_2);
+        _5 = copy ((_4 as Continue).0: i32);
+        _6 = Add(copy _5, const 1_i32);
+        _0 = Option::<i32>::Some(move _6);
+        StorageDead(_6);
+        StorageDead(_4);
+        goto -> bb3;
+    }
+
+    bb3: {
+        return;
+    }
+
+    bb4: {
+        unreachable;
+    }
+}
+
+ALLOC0 (size: 8, align: 4) {
+    00 00 00 00 __ __ __ __                         │ ....░░░░
+}
diff --git a/tests/mir-opt/pre-codegen/simple_option_map.rs b/tests/mir-opt/pre-codegen/simple_option_map.rs
index 0c432be0419bc..f0d7b51a64397 100644
--- a/tests/mir-opt/pre-codegen/simple_option_map.rs
+++ b/tests/mir-opt/pre-codegen/simple_option_map.rs
@@ -1,7 +1,6 @@
-// skip-filecheck
 //@ compile-flags: -O -C debuginfo=0 -Zmir-opt-level=2
 
-#[inline(always)]
+#[inline]
 fn map<T, U, F>(slf: Option<T>, f: F) -> Option<U>
 where
     F: FnOnce(T) -> U,
@@ -14,9 +13,30 @@ where
 
 // EMIT_MIR simple_option_map.ezmap.PreCodegen.after.mir
 pub fn ezmap(x: Option<i32>) -> Option<i32> {
+    // We expect this to all be inlined, as though it was written without the
+    // combinator and without the closure, using just a plain match.
+
+    // CHECK-LABEL: fn ezmap
+    // CHECK: [[INNER:_.+]] = copy ((_1 as Some).0: i32);
+    // CHECK: [[SUCC:_.+]] = Add({{copy|move}} [[INNER]], const 1_i32);
+    // CHECK: _0 = Option::<i32>::Some({{copy|move}} [[SUCC]]);
     map(x, |n| n + 1)
 }
 
+// EMIT_MIR simple_option_map.map_via_question_mark.PreCodegen.after.mir
+pub fn map_via_question_mark(x: Option<i32>) -> Option<i32> {
+    // FIXME(#138544): Ideally this would optimize out the `ControlFlow` local.
+
+    // CHECK-LABEL: fn map_via_question_mark
+    // CHECK: [[INNER:_.+]] = copy ((_1 as Some).0: i32);
+    // CHECK: [[TEMP1:_.+]] = ControlFlow::<Option<Infallible>, i32>::Continue(copy [[INNER]]);
+    // CHECK: [[TEMP2:_.+]] = copy (([[TEMP1]] as Continue).0: i32);
+    // CHECK: [[SUCC:_.+]] = Add({{copy|move}} [[TEMP2]], const 1_i32);
+    // CHECK: _0 = Option::<i32>::Some({{copy|move}} [[SUCC]]);
+    Some(x? + 1)
+}
+
 fn main() {
     assert_eq!(None, ezmap(None));
+    assert_eq!(None, map_via_question_mark(None));
 }

From aa2c24b03b893f7e65e1755a237ffe0387509b25 Mon Sep 17 00:00:00 2001
From: Ayush Singh <ayush@beagleboard.org>
Date: Sun, 9 Mar 2025 01:03:11 +0530
Subject: [PATCH 05/19] uefi: Add OwnedEvent abstraction

- Events are going to become quite important for Networking, so needed
  owned abstractions.
- Switch to OwnedEvent abstraction for Exit boot services event.

Signed-off-by: Ayush Singh <ayush@beagleboard.org>
---
 library/std/src/sys/pal/uefi/helpers.rs | 86 +++++++++++++++----------
 library/std/src/sys/pal/uefi/mod.rs     | 10 +--
 2 files changed, 58 insertions(+), 38 deletions(-)

diff --git a/library/std/src/sys/pal/uefi/helpers.rs b/library/std/src/sys/pal/uefi/helpers.rs
index 0a2a8f5ef67be..a0433ddfd9679 100644
--- a/library/std/src/sys/pal/uefi/helpers.rs
+++ b/library/std/src/sys/pal/uefi/helpers.rs
@@ -120,39 +120,6 @@ pub(crate) fn open_protocol<T>(
     }
 }
 
-pub(crate) fn create_event(
-    signal: u32,
-    tpl: efi::Tpl,
-    handler: Option<efi::EventNotify>,
-    context: *mut crate::ffi::c_void,
-) -> io::Result<NonNull<crate::ffi::c_void>> {
-    let boot_services: NonNull<efi::BootServices> =
-        boot_services().ok_or(BOOT_SERVICES_UNAVAILABLE)?.cast();
-    let mut event: r_efi::efi::Event = crate::ptr::null_mut();
-    let r = unsafe {
-        let create_event = (*boot_services.as_ptr()).create_event;
-        (create_event)(signal, tpl, handler, context, &mut event)
-    };
-    if r.is_error() {
-        Err(crate::io::Error::from_raw_os_error(r.as_usize()))
-    } else {
-        NonNull::new(event).ok_or(const_error!(io::ErrorKind::Other, "null protocol"))
-    }
-}
-
-/// # SAFETY
-/// - The supplied event must be valid
-pub(crate) unsafe fn close_event(evt: NonNull<crate::ffi::c_void>) -> io::Result<()> {
-    let boot_services: NonNull<efi::BootServices> =
-        boot_services().ok_or(BOOT_SERVICES_UNAVAILABLE)?.cast();
-    let r = unsafe {
-        let close_event = (*boot_services.as_ptr()).close_event;
-        (close_event)(evt.as_ptr())
-    };
-
-    if r.is_error() { Err(crate::io::Error::from_raw_os_error(r.as_usize())) } else { Ok(()) }
-}
-
 /// Gets the Protocol for current system handle.
 ///
 /// Note: Some protocols need to be manually freed. It is the caller's responsibility to do so.
@@ -559,3 +526,56 @@ impl Drop for ServiceProtocol {
         }
     }
 }
+
+#[repr(transparent)]
+pub(crate) struct OwnedEvent(NonNull<crate::ffi::c_void>);
+
+impl OwnedEvent {
+    pub(crate) fn new(
+        signal: u32,
+        tpl: efi::Tpl,
+        handler: Option<efi::EventNotify>,
+        context: Option<NonNull<crate::ffi::c_void>>,
+    ) -> io::Result<Self> {
+        let boot_services: NonNull<efi::BootServices> =
+            boot_services().ok_or(BOOT_SERVICES_UNAVAILABLE)?.cast();
+        let mut event: r_efi::efi::Event = crate::ptr::null_mut();
+        let context = context.map(NonNull::as_ptr).unwrap_or(crate::ptr::null_mut());
+
+        let r = unsafe {
+            let create_event = (*boot_services.as_ptr()).create_event;
+            (create_event)(signal, tpl, handler, context, &mut event)
+        };
+
+        if r.is_error() {
+            Err(crate::io::Error::from_raw_os_error(r.as_usize()))
+        } else {
+            NonNull::new(event)
+                .ok_or(const_error!(io::ErrorKind::Other, "failed to create event"))
+                .map(Self)
+        }
+    }
+
+    pub(crate) fn into_raw(self) -> *mut crate::ffi::c_void {
+        let r = self.0.as_ptr();
+        crate::mem::forget(self);
+        r
+    }
+
+    /// SAFETY: Assumes that ptr is a non-null valid UEFI event
+    pub(crate) unsafe fn from_raw(ptr: *mut crate::ffi::c_void) -> Self {
+        Self(unsafe { NonNull::new_unchecked(ptr) })
+    }
+}
+
+impl Drop for OwnedEvent {
+    fn drop(&mut self) {
+        if let Some(boot_services) = boot_services() {
+            let bt: NonNull<r_efi::efi::BootServices> = boot_services.cast();
+            unsafe {
+                let close_event = (*bt.as_ptr()).close_event;
+                (close_event)(self.0.as_ptr())
+            };
+        }
+    }
+}
diff --git a/library/std/src/sys/pal/uefi/mod.rs b/library/std/src/sys/pal/uefi/mod.rs
index 6a03e240c6bd4..ed39130ab41b6 100644
--- a/library/std/src/sys/pal/uefi/mod.rs
+++ b/library/std/src/sys/pal/uefi/mod.rs
@@ -49,17 +49,17 @@ pub(crate) unsafe fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) {
     unsafe { uefi::env::init_globals(image_handle, system_table) };
 
     // Register exit boot services handler
-    match helpers::create_event(
+    match helpers::OwnedEvent::new(
         r_efi::efi::EVT_SIGNAL_EXIT_BOOT_SERVICES,
         r_efi::efi::TPL_NOTIFY,
         Some(exit_boot_service_handler),
-        crate::ptr::null_mut(),
+        None,
     ) {
         Ok(x) => {
             if EXIT_BOOT_SERVICE_EVENT
                 .compare_exchange(
                     crate::ptr::null_mut(),
-                    x.as_ptr(),
+                    x.into_raw(),
                     Ordering::Release,
                     Ordering::Acquire,
                 )
@@ -79,7 +79,7 @@ pub unsafe fn cleanup() {
     if let Some(exit_boot_service_event) =
         NonNull::new(EXIT_BOOT_SERVICE_EVENT.swap(crate::ptr::null_mut(), Ordering::Acquire))
     {
-        let _ = unsafe { helpers::close_event(exit_boot_service_event) };
+        let _ = unsafe { helpers::OwnedEvent::from_raw(exit_boot_service_event.as_ptr()) };
     }
 }
 
@@ -145,7 +145,7 @@ pub fn abort_internal() -> ! {
     if let Some(exit_boot_service_event) =
         NonNull::new(EXIT_BOOT_SERVICE_EVENT.load(Ordering::Acquire))
     {
-        let _ = unsafe { helpers::close_event(exit_boot_service_event) };
+        let _ = unsafe { helpers::OwnedEvent::from_raw(exit_boot_service_event.as_ptr()) };
     }
 
     if let (Some(boot_services), Some(handle)) =

From bcac931956f7a5c271914f8e1973b8195eedb498 Mon Sep 17 00:00:00 2001
From: Thalia Archibald <thalia@archibald.dev>
Date: Mon, 17 Mar 2025 17:18:05 -0700
Subject: [PATCH 06/19] Update test for SGX now implementing read_buf

In #108326, `read_buf` was implemented for a variety of types, but SGX
was saved for later. Update a test from then, now that #137355
implemented it for SGX types.
---
 library/std/src/net/tcp/tests.rs | 8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/library/std/src/net/tcp/tests.rs b/library/std/src/net/tcp/tests.rs
index a7b5cdf4ec061..03003037b295c 100644
--- a/library/std/src/net/tcp/tests.rs
+++ b/library/std/src/net/tcp/tests.rs
@@ -315,12 +315,8 @@ fn read_buf() {
         let mut buf = BorrowedBuf::from(buf.as_mut_slice());
         t!(s.read_buf(buf.unfilled()));
         assert_eq!(buf.filled(), &[1, 2, 3, 4]);
-
-        // FIXME: sgx uses default_read_buf that initializes the buffer.
-        if cfg!(not(target_env = "sgx")) {
-            // TcpStream::read_buf should omit buffer initialization.
-            assert_eq!(buf.init_len(), 4);
-        }
+        // TcpStream::read_buf should omit buffer initialization.
+        assert_eq!(buf.init_len(), 4);
 
         t.join().ok().expect("thread panicked");
     })

From 9fa158d70a75ce116e87b03d913104474af0e381 Mon Sep 17 00:00:00 2001
From: Ayush Singh <ayush@beagleboard.org>
Date: Tue, 18 Mar 2025 19:27:53 +0530
Subject: [PATCH 07/19] std: uefi: fs: Implement mkdir

- Since there is no direct mkdir in UEFI, first check if a file/dir with
  same path exists and then create the directory.

Signed-off-by: Ayush Singh <ayush@beagleboard.org>
---
 library/std/src/sys/fs/uefi.rs | 34 ++++++++++++++++++++++++++++++----
 1 file changed, 30 insertions(+), 4 deletions(-)

diff --git a/library/std/src/sys/fs/uefi.rs b/library/std/src/sys/fs/uefi.rs
index defc1681d38a4..54acd4c27b334 100644
--- a/library/std/src/sys/fs/uefi.rs
+++ b/library/std/src/sys/fs/uefi.rs
@@ -36,7 +36,7 @@ pub struct FilePermissions(bool);
 pub struct FileType(bool);
 
 #[derive(Debug)]
-pub struct DirBuilder {}
+pub struct DirBuilder;
 
 impl FileAttr {
     pub fn size(&self) -> u64 {
@@ -248,11 +248,11 @@ impl File {
 
 impl DirBuilder {
     pub fn new() -> DirBuilder {
-        DirBuilder {}
+        DirBuilder
     }
 
-    pub fn mkdir(&self, _p: &Path) -> io::Result<()> {
-        unsupported()
+    pub fn mkdir(&self, p: &Path) -> io::Result<()> {
+        uefi_fs::mkdir(p)
     }
 }
 
@@ -452,4 +452,30 @@ mod uefi_fs {
             }
         }
     }
+
+    /// An implementation of mkdir to allow creating new directory without having to open the
+    /// volume twice (once for checking and once for creating)
+    pub(crate) fn mkdir(path: &Path) -> io::Result<()> {
+        let absolute = crate::path::absolute(path)?;
+
+        let p = helpers::OwnedDevicePath::from_text(absolute.as_os_str())?;
+        let (vol, mut path_remaining) = File::open_volume_from_device_path(p.borrow())?;
+
+        // Check if file exists
+        match vol.open(&mut path_remaining, file::MODE_READ, 0) {
+            Ok(_) => {
+                return Err(io::Error::new(io::ErrorKind::AlreadyExists, "Path already exists"));
+            }
+            Err(e) if e.kind() == io::ErrorKind::NotFound => {}
+            Err(e) => return Err(e),
+        }
+
+        let _ = vol.open(
+            &mut path_remaining,
+            file::MODE_READ | file::MODE_WRITE | file::MODE_CREATE,
+            file::DIRECTORY,
+        )?;
+
+        Ok(())
+    }
 }

From b52330136837aadf977b1f188cb5d60a264900d6 Mon Sep 17 00:00:00 2001
From: Redddy <78539407+reddevilmidzy@users.noreply.github.com>
Date: Sat, 15 Mar 2025 02:11:38 +0900
Subject: [PATCH 08/19] Add test to ensure no index out of bounds panic
 (#135474)

---
 tests/ui/fn/trait-fn-generic-mismatch.rs     | 12 ++++++++
 tests/ui/fn/trait-fn-generic-mismatch.stderr | 32 ++++++++++++++++++++
 2 files changed, 44 insertions(+)
 create mode 100644 tests/ui/fn/trait-fn-generic-mismatch.rs
 create mode 100644 tests/ui/fn/trait-fn-generic-mismatch.stderr

diff --git a/tests/ui/fn/trait-fn-generic-mismatch.rs b/tests/ui/fn/trait-fn-generic-mismatch.rs
new file mode 100644
index 0000000000000..dc8222e967e4c
--- /dev/null
+++ b/tests/ui/fn/trait-fn-generic-mismatch.rs
@@ -0,0 +1,12 @@
+fn retry() -> impl Sized {}
+
+struct Core<T>(T);
+
+impl Core<XXX> { //~ ERROR cannot find type `XXX` in this scope
+    pub fn spawn(self) {}
+}
+
+fn main() {
+    let core = Core(1);
+    core.spawn(retry()); //~ ERROR this method takes 0 arguments but 1 argument was supplied
+}
diff --git a/tests/ui/fn/trait-fn-generic-mismatch.stderr b/tests/ui/fn/trait-fn-generic-mismatch.stderr
new file mode 100644
index 0000000000000..8384d74e225aa
--- /dev/null
+++ b/tests/ui/fn/trait-fn-generic-mismatch.stderr
@@ -0,0 +1,32 @@
+error[E0412]: cannot find type `XXX` in this scope
+  --> $DIR/trait-fn-generic-mismatch.rs:5:11
+   |
+LL | impl Core<XXX> {
+   |           ^^^ not found in this scope
+   |
+help: you might be missing a type parameter
+   |
+LL | impl<XXX> Core<XXX> {
+   |     +++++
+
+error[E0061]: this method takes 0 arguments but 1 argument was supplied
+  --> $DIR/trait-fn-generic-mismatch.rs:11:10
+   |
+LL |     core.spawn(retry());
+   |          ^^^^^ ------- unexpected argument of type `impl Sized`
+   |
+note: method defined here
+  --> $DIR/trait-fn-generic-mismatch.rs:6:12
+   |
+LL |     pub fn spawn(self) {}
+   |            ^^^^^
+help: remove the extra argument
+   |
+LL -     core.spawn(retry());
+LL +     core.spawn();
+   |
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0061, E0412.
+For more information about an error, try `rustc --explain E0061`.

From fa0c951a2795a0e1e5caa94317309a8bdb9b94a5 Mon Sep 17 00:00:00 2001
From: Chiichen <chiichen@qq.com>
Date: Sun, 23 Mar 2025 12:41:23 +0800
Subject: [PATCH 09/19] doc: rename reference #create-a-configtoml to
 #create-a-bootstraptoml

---
 bootstrap.example.toml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/bootstrap.example.toml b/bootstrap.example.toml
index 294d9780716eb..caffe1a93712f 100644
--- a/bootstrap.example.toml
+++ b/bootstrap.example.toml
@@ -1,7 +1,7 @@
 # Sample TOML configuration file for building Rust.
 #
 # To configure bootstrap, run `./configure` or `./x.py setup`.
-# See https://rustc-dev-guide.rust-lang.org/building/how-to-build-and-run.html#create-a-configtoml for more information.
+# See https://rustc-dev-guide.rust-lang.org/building/how-to-build-and-run.html#create-a-bootstraptoml for more information.
 #
 # All options are commented out by default in this file, and they're commented
 # out with their default values. The build system by default looks for
@@ -446,7 +446,7 @@
 # a specific version.
 #ccache = false
 
-# List of paths to exclude from the build and test processes. 
+# List of paths to exclude from the build and test processes.
 # For example, exclude = ["tests/ui", "src/tools/tidy"].
 #exclude = []
 

From 20f4a0d586fcb27936f07f001bf128b2f407b018 Mon Sep 17 00:00:00 2001
From: Takayuki Maeda <takoyaki0316@gmail.com>
Date: Sun, 23 Mar 2025 17:02:42 +0900
Subject: [PATCH 10/19] fix ICE #138415

---
 compiler/rustc_ast_lowering/src/item.rs       |  4 ++--
 .../invalid-extern-fn-body.rs                 | 11 ++++++++++
 .../invalid-extern-fn-body.stderr             | 20 +++++++++++++++++++
 3 files changed, 33 insertions(+), 2 deletions(-)
 create mode 100644 tests/ui/type-alias-impl-trait/define_opaques_attr/invalid-extern-fn-body.rs
 create mode 100644 tests/ui/type-alias-impl-trait/define_opaques_attr/invalid-extern-fn-body.stderr

diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index bd011d59aaa7d..518349343b3a1 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -1724,8 +1724,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
             return;
         };
         let define_opaque = define_opaque.iter().filter_map(|(id, path)| {
-            let res = self.resolver.get_partial_res(*id).unwrap();
-            let Some(did) = res.expect_full_res().opt_def_id() else {
+            let res = self.resolver.get_partial_res(*id);
+            let Some(did) = res.and_then(|res| res.expect_full_res().opt_def_id()) else {
                 self.dcx().span_delayed_bug(path.span, "should have errored in resolve");
                 return None;
             };
diff --git a/tests/ui/type-alias-impl-trait/define_opaques_attr/invalid-extern-fn-body.rs b/tests/ui/type-alias-impl-trait/define_opaques_attr/invalid-extern-fn-body.rs
new file mode 100644
index 0000000000000..d873af44adf9b
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/define_opaques_attr/invalid-extern-fn-body.rs
@@ -0,0 +1,11 @@
+#![feature(type_alias_impl_trait)]
+
+extern "C" {
+    fn a() {
+        //~^ ERROR incorrect function inside `extern` block
+        #[define_opaque(String)]
+        fn c() {}
+    }
+}
+
+pub fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/define_opaques_attr/invalid-extern-fn-body.stderr b/tests/ui/type-alias-impl-trait/define_opaques_attr/invalid-extern-fn-body.stderr
new file mode 100644
index 0000000000000..2e944257d8f65
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/define_opaques_attr/invalid-extern-fn-body.stderr
@@ -0,0 +1,20 @@
+error: incorrect function inside `extern` block
+  --> $DIR/invalid-extern-fn-body.rs:4:8
+   |
+LL |   extern "C" {
+   |   ---------- `extern` blocks define existing foreign functions and functions inside of them cannot have a body
+LL |       fn a() {
+   |  ________^___-
+   | |        |
+   | |        cannot have a body
+LL | |
+LL | |         #[define_opaque(String)]
+LL | |         fn c() {}
+LL | |     }
+   | |_____- help: remove the invalid body: `;`
+   |
+   = help: you might have meant to write a function accessible through FFI, which can be done by writing `extern fn` outside of the `extern` block
+   = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html
+
+error: aborting due to 1 previous error
+

From 34b7d51b95663071729b83a2127bdd6a98b9ca08 Mon Sep 17 00:00:00 2001
From: Takayuki Maeda <takoyaki0316@gmail.com>
Date: Sun, 23 Mar 2025 17:47:10 +0900
Subject: [PATCH 11/19] fix typo

---
 library/core/src/macros/mod.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs
index fa0d882181a51..5f200b31d1ae7 100644
--- a/library/core/src/macros/mod.rs
+++ b/library/core/src/macros/mod.rs
@@ -1744,7 +1744,7 @@ pub(crate) mod builtin {
     }
 
     /// Provide a list of type aliases and other opaque-type-containing type definitions.
-    /// This list will be used in the body of the item it is applied to to define opaque
+    /// This list will be used in the body of the item it is applied to define opaque
     /// types' hidden types.
     /// Can only be applied to things that have bodies.
     #[unstable(

From 0e7dbab1fc4a2cfc63bac4f5c4d283d2504f1547 Mon Sep 17 00:00:00 2001
From: Jieyou Xu <jieyouxu@outlook.com>
Date: Tue, 18 Mar 2025 13:16:01 +0800
Subject: [PATCH 12/19] Implement `supported-crate-types` print request

As an unstable print request.
---
 compiler/rustc_driver_impl/src/lib.rs         | 14 +++++++++++--
 compiler/rustc_session/src/config.rs          |  7 ++++++-
 tests/ui/print-request/stability.rs           |  4 ++++
 .../supported-crate-types.linux.stdout        |  7 +++++++
 .../supported-crate-types.musl.stdout         |  5 +++++
 .../ui/print-request/supported-crate-types.rs | 20 +++++++++++++++++++
 .../supported-crate-types.wasm.stdout         |  5 +++++
 7 files changed, 59 insertions(+), 3 deletions(-)
 create mode 100644 tests/ui/print-request/supported-crate-types.linux.stdout
 create mode 100644 tests/ui/print-request/supported-crate-types.musl.stdout
 create mode 100644 tests/ui/print-request/supported-crate-types.rs
 create mode 100644 tests/ui/print-request/supported-crate-types.wasm.stdout

diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index 4ba076c64e104..37755e7d61db1 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -20,7 +20,7 @@
 // tidy-alphabetical-end
 
 use std::cmp::max;
-use std::collections::BTreeMap;
+use std::collections::{BTreeMap, BTreeSet};
 use std::ffi::OsString;
 use std::fmt::Write as _;
 use std::fs::{self, File};
@@ -61,7 +61,7 @@ use rustc_session::config::{
 };
 use rustc_session::getopts::{self, Matches};
 use rustc_session::lint::{Lint, LintId};
-use rustc_session::output::collect_crate_types;
+use rustc_session::output::{CRATE_TYPES, collect_crate_types, invalid_output_for_target};
 use rustc_session::{EarlyDiagCtxt, Session, config, filesearch};
 use rustc_span::FileName;
 use rustc_target::json::ToJson;
@@ -790,6 +790,16 @@ fn print_crate_info(
                     sess.dcx().fatal("only Apple targets currently support deployment version info")
                 }
             }
+            SupportedCrateTypes => {
+                let supported_crate_types = CRATE_TYPES
+                    .iter()
+                    .filter(|(_, crate_type)| !invalid_output_for_target(&sess, *crate_type))
+                    .map(|(crate_type_sym, _)| *crate_type_sym)
+                    .collect::<BTreeSet<_>>();
+                for supported_crate_type in supported_crate_types {
+                    println_info!("{}", supported_crate_type.as_str());
+                }
+            }
         }
 
         req.out.overwrite(&crate_info, sess);
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 43b78423c727f..ed336cc559612 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -58,6 +58,7 @@ pub const PRINT_KINDS: &[(&str, PrintKind)] = &[
     ("relocation-models", PrintKind::RelocationModels),
     ("split-debuginfo", PrintKind::SplitDebuginfo),
     ("stack-protector-strategies", PrintKind::StackProtectorStrategies),
+    ("supported-crate-types", PrintKind::SupportedCrateTypes),
     ("sysroot", PrintKind::Sysroot),
     ("target-cpus", PrintKind::TargetCPUs),
     ("target-features", PrintKind::TargetFeatures),
@@ -888,6 +889,7 @@ pub enum PrintKind {
     RelocationModels,
     SplitDebuginfo,
     StackProtectorStrategies,
+    SupportedCrateTypes,
     Sysroot,
     TargetCPUs,
     TargetFeatures,
@@ -2063,7 +2065,10 @@ fn check_print_request_stability(
     (print_name, print_kind): (&str, PrintKind),
 ) {
     match print_kind {
-        PrintKind::AllTargetSpecsJson | PrintKind::CheckCfg | PrintKind::TargetSpecJson
+        PrintKind::AllTargetSpecsJson
+        | PrintKind::CheckCfg
+        | PrintKind::SupportedCrateTypes
+        | PrintKind::TargetSpecJson
             if !unstable_opts.unstable_options =>
         {
             early_dcx.early_fatal(format!(
diff --git a/tests/ui/print-request/stability.rs b/tests/ui/print-request/stability.rs
index b205b05556912..c3421224d7206 100644
--- a/tests/ui/print-request/stability.rs
+++ b/tests/ui/print-request/stability.rs
@@ -22,6 +22,10 @@
 //@[check_cfg] compile-flags: --print=check-cfg
 //@[check_cfg] error-pattern: the `-Z unstable-options` flag must also be passed
 
+//@ revisions: supported_crate_types
+//@[supported_crate_types] compile-flags: --print=supported-crate-types
+//@[supported_crate_types] error-pattern: the `-Z unstable-options` flag must also be passed
+
 //@ revisions: target_spec_json
 //@[target_spec_json] compile-flags: --print=target-spec-json
 //@[target_spec_json] error-pattern: the `-Z unstable-options` flag must also be passed
diff --git a/tests/ui/print-request/supported-crate-types.linux.stdout b/tests/ui/print-request/supported-crate-types.linux.stdout
new file mode 100644
index 0000000000000..721adb432e7a1
--- /dev/null
+++ b/tests/ui/print-request/supported-crate-types.linux.stdout
@@ -0,0 +1,7 @@
+bin
+cdylib
+dylib
+lib
+proc-macro
+rlib
+staticlib
diff --git a/tests/ui/print-request/supported-crate-types.musl.stdout b/tests/ui/print-request/supported-crate-types.musl.stdout
new file mode 100644
index 0000000000000..1f4b991e49fd2
--- /dev/null
+++ b/tests/ui/print-request/supported-crate-types.musl.stdout
@@ -0,0 +1,5 @@
+bin
+lib
+proc-macro
+rlib
+staticlib
diff --git a/tests/ui/print-request/supported-crate-types.rs b/tests/ui/print-request/supported-crate-types.rs
new file mode 100644
index 0000000000000..c8b4c0c1a4164
--- /dev/null
+++ b/tests/ui/print-request/supported-crate-types.rs
@@ -0,0 +1,20 @@
+//! Basic smoke test for `--print=supported-crate-types`, which should print a newline delimited
+//! list of crate types supported by the given target. This test cherry-picks a few well-known
+//! targets as examples.
+//!
+//! Tracking issue: <https://github.com/rust-lang/rust/issues/138640>
+
+// ignore-tidy-linelength
+
+//@ check-pass
+
+//@ revisions: wasm musl linux
+
+//@[wasm] compile-flags: --target=wasm32-unknown-unknown --print=supported-crate-types -Zunstable-options
+//@[wasm] needs-llvm-components: webassembly
+
+//@[musl] compile-flags: --target=x86_64-unknown-linux-musl --print=supported-crate-types -Zunstable-options
+//@[musl] needs-llvm-components: x86
+
+//@[linux] compile-flags: --target=x86_64-unknown-linux-gnu --print=supported-crate-types -Zunstable-options
+//@[linux] needs-llvm-components: x86
diff --git a/tests/ui/print-request/supported-crate-types.wasm.stdout b/tests/ui/print-request/supported-crate-types.wasm.stdout
new file mode 100644
index 0000000000000..ca1de519598af
--- /dev/null
+++ b/tests/ui/print-request/supported-crate-types.wasm.stdout
@@ -0,0 +1,5 @@
+bin
+cdylib
+lib
+rlib
+staticlib

From 13530afc08909a44874dc1e8667747fddb48e3c7 Mon Sep 17 00:00:00 2001
From: Jieyou Xu <jieyouxu@outlook.com>
Date: Tue, 18 Mar 2025 13:37:36 +0800
Subject: [PATCH 13/19] Document `supported-crate-types` print request in
 unstable book

---
 .../print-supported-crate-types.md            | 27 +++++++++++++++++++
 1 file changed, 27 insertions(+)
 create mode 100644 src/doc/unstable-book/src/compiler-flags/print-supported-crate-types.md

diff --git a/src/doc/unstable-book/src/compiler-flags/print-supported-crate-types.md b/src/doc/unstable-book/src/compiler-flags/print-supported-crate-types.md
new file mode 100644
index 0000000000000..f285d6e717510
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/print-supported-crate-types.md
@@ -0,0 +1,27 @@
+# `print=supported-crate-types`
+
+The tracking issue for this feature is: [#138640](https://github.com/rust-lang/rust/issues/138640).
+
+------------------------
+
+This option of the `--print` flag produces a list of crate types (delimited by newlines) supported for the given target.
+
+The crate type strings correspond to the values accepted by the `--crate-type` flag.
+
+Intended to be used like this:
+
+```bash
+rustc --print=supported-crate-types -Zunstable-options --target=x86_64-unknown-linux-gnu
+```
+
+Example output for `x86_64-unknown-linux-gnu`:
+
+```text
+bin
+cdylib
+dylib
+lib
+proc-macro
+rlib
+staticlib
+```

From f1b8d896597534af16e3c1e540c336b9b444af0a Mon Sep 17 00:00:00 2001
From: Jieyou Xu <jieyouxu@outlook.com>
Date: Tue, 18 Mar 2025 14:39:46 +0800
Subject: [PATCH 14/19] Rebless tests with changed help due to new print
 request option

---
 tests/run-make/rustc-help/help-v.stdout                 | 2 +-
 tests/run-make/rustc-help/help.stdout                   | 2 +-
 tests/ui/invalid-compile-flags/print-without-arg.stderr | 2 +-
 tests/ui/invalid-compile-flags/print.stderr             | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/tests/run-make/rustc-help/help-v.stdout b/tests/run-make/rustc-help/help-v.stdout
index c8ea09ee2c8a0..98e56735082d1 100644
--- a/tests/run-make/rustc-help/help-v.stdout
+++ b/tests/run-make/rustc-help/help-v.stdout
@@ -29,7 +29,7 @@ Options:
         --emit [asm|llvm-bc|llvm-ir|obj|metadata|link|dep-info|mir]
                         Comma separated list of types of output for the
                         compiler to emit
-        --print [all-target-specs-json|calling-conventions|cfg|check-cfg|code-models|crate-name|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|tls-models]
+        --print [all-target-specs-json|calling-conventions|cfg|check-cfg|code-models|crate-name|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|supported-crate-types|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|tls-models]
                         Compiler information to print on stdout
     -g                  Equivalent to -C debuginfo=2
     -O                  Equivalent to -C opt-level=3
diff --git a/tests/run-make/rustc-help/help.stdout b/tests/run-make/rustc-help/help.stdout
index 434e71e901e47..040555f1d04fe 100644
--- a/tests/run-make/rustc-help/help.stdout
+++ b/tests/run-make/rustc-help/help.stdout
@@ -29,7 +29,7 @@ Options:
         --emit [asm|llvm-bc|llvm-ir|obj|metadata|link|dep-info|mir]
                         Comma separated list of types of output for the
                         compiler to emit
-        --print [all-target-specs-json|calling-conventions|cfg|check-cfg|code-models|crate-name|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|tls-models]
+        --print [all-target-specs-json|calling-conventions|cfg|check-cfg|code-models|crate-name|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|supported-crate-types|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|tls-models]
                         Compiler information to print on stdout
     -g                  Equivalent to -C debuginfo=2
     -O                  Equivalent to -C opt-level=3
diff --git a/tests/ui/invalid-compile-flags/print-without-arg.stderr b/tests/ui/invalid-compile-flags/print-without-arg.stderr
index 05d42247d419e..aa8a2ae42db29 100644
--- a/tests/ui/invalid-compile-flags/print-without-arg.stderr
+++ b/tests/ui/invalid-compile-flags/print-without-arg.stderr
@@ -1,5 +1,5 @@
 error: Argument to option 'print' missing
        Usage:
-           --print [all-target-specs-json|calling-conventions|cfg|check-cfg|code-models|crate-name|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|tls-models]
+           --print [all-target-specs-json|calling-conventions|cfg|check-cfg|code-models|crate-name|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|supported-crate-types|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|tls-models]
                                Compiler information to print on stdout
 
diff --git a/tests/ui/invalid-compile-flags/print.stderr b/tests/ui/invalid-compile-flags/print.stderr
index 4ea06a06539af..f9cfb1616ce5a 100644
--- a/tests/ui/invalid-compile-flags/print.stderr
+++ b/tests/ui/invalid-compile-flags/print.stderr
@@ -1,5 +1,5 @@
 error: unknown print request: `yyyy`
   |
-  = help: valid print requests are: `all-target-specs-json`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `tls-models`
+  = help: valid print requests are: `all-target-specs-json`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `tls-models`
   = help: for more information, see the rustc book: https://doc.rust-lang.org/rustc/command-line-arguments.html#--print-print-compiler-information
 

From f2cde8eeb4378b99cb722a9ef4a2f6cc83b805e1 Mon Sep 17 00:00:00 2001
From: Jieyou Xu <jieyouxu@outlook.com>
Date: Fri, 21 Mar 2025 14:52:26 +0800
Subject: [PATCH 15/19] Adjust `rustc-print-info-issue-138612.rs`

- Document test intent to check for `-Whelp` suggestion if
  `--print=lints` was specified.
- Move this test under `tests/ui/print-request/` and rename it to
  `print-lints-help.rs` to better reflect what it is checking.
---
 tests/ui/print-request/print-lints-help.rs                 | 7 +++++++
 .../print-lints-help.stderr}                               | 2 +-
 tests/ui/rustc-print-info-issue-138612.rs                  | 2 --
 3 files changed, 8 insertions(+), 3 deletions(-)
 create mode 100644 tests/ui/print-request/print-lints-help.rs
 rename tests/ui/{rustc-print-info-issue-138612.stderr => print-request/print-lints-help.stderr} (74%)
 delete mode 100644 tests/ui/rustc-print-info-issue-138612.rs

diff --git a/tests/ui/print-request/print-lints-help.rs b/tests/ui/print-request/print-lints-help.rs
new file mode 100644
index 0000000000000..420eae27ed43e
--- /dev/null
+++ b/tests/ui/print-request/print-lints-help.rs
@@ -0,0 +1,7 @@
+//! Check that we point to `-Whelp` to guide the user to find the list of lints if the user requests
+//! `--print=lints` (which is not a valid print request).
+
+//@ compile-flags: --print lints
+//@ error-pattern: error: unknown print request: `lints`
+//@ error-pattern: help: use `-Whelp` to print a list of lints
+//@ error-pattern: help: for more information, see the rustc book
diff --git a/tests/ui/rustc-print-info-issue-138612.stderr b/tests/ui/print-request/print-lints-help.stderr
similarity index 74%
rename from tests/ui/rustc-print-info-issue-138612.stderr
rename to tests/ui/print-request/print-lints-help.stderr
index 4f7ed8219521d..0530d11f2e802 100644
--- a/tests/ui/rustc-print-info-issue-138612.stderr
+++ b/tests/ui/print-request/print-lints-help.stderr
@@ -1,6 +1,6 @@
 error: unknown print request: `lints`
   |
-  = help: valid print requests are: `all-target-specs-json`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `tls-models`
+  = help: valid print requests are: `all-target-specs-json`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `tls-models`
   = help: use `-Whelp` to print a list of lints
   = help: for more information, see the rustc book: https://doc.rust-lang.org/rustc/command-line-arguments.html#--print-print-compiler-information
 
diff --git a/tests/ui/rustc-print-info-issue-138612.rs b/tests/ui/rustc-print-info-issue-138612.rs
deleted file mode 100644
index 65b595635b158..0000000000000
--- a/tests/ui/rustc-print-info-issue-138612.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-//@ check-fail
-//@ compile-flags: /dev/null --print lints

From f10b58714e864ac7c1f6d6ac1666f26d4a1ca955 Mon Sep 17 00:00:00 2001
From: Jieyou Xu <jieyouxu@outlook.com>
Date: Sun, 23 Mar 2025 19:28:10 +0800
Subject: [PATCH 16/19] Say which test failed the
 `COMPILETEST_REQUIRE_ALL_LLVM_COMPONENTS` assertion

---
 src/tools/compiletest/src/header.rs | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index 7675e13990d6c..d7a5f304d2382 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -1385,7 +1385,7 @@ pub fn make_test_description<R: Read>(
             decision!(cfg::handle_ignore(config, ln));
             decision!(cfg::handle_only(config, ln));
             decision!(needs::handle_needs(&cache.needs, config, ln));
-            decision!(ignore_llvm(config, ln));
+            decision!(ignore_llvm(config, path, ln));
             decision!(ignore_cdb(config, ln));
             decision!(ignore_gdb(config, ln));
             decision!(ignore_lldb(config, ln));
@@ -1525,7 +1525,7 @@ fn ignore_lldb(config: &Config, line: &str) -> IgnoreDecision {
     IgnoreDecision::Continue
 }
 
-fn ignore_llvm(config: &Config, line: &str) -> IgnoreDecision {
+fn ignore_llvm(config: &Config, path: &Path, line: &str) -> IgnoreDecision {
     if let Some(needed_components) =
         config.parse_name_value_directive(line, "needs-llvm-components")
     {
@@ -1536,8 +1536,9 @@ fn ignore_llvm(config: &Config, line: &str) -> IgnoreDecision {
         {
             if env::var_os("COMPILETEST_REQUIRE_ALL_LLVM_COMPONENTS").is_some() {
                 panic!(
-                    "missing LLVM component {}, and COMPILETEST_REQUIRE_ALL_LLVM_COMPONENTS is set",
-                    missing_component
+                    "missing LLVM component {}, and COMPILETEST_REQUIRE_ALL_LLVM_COMPONENTS is set: {}",
+                    missing_component,
+                    path.display()
                 );
             }
             return IgnoreDecision::Ignore {

From e934975339d772c2018f558b0963108f12376255 Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Sun, 23 Mar 2025 16:24:39 +0000
Subject: [PATCH 17/19] Visit coroutine kind ty in FlagComputation

---
 compiler/rustc_middle/src/ty/flags.rs | 1 +
 1 file changed, 1 insertion(+)

diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs
index 0b8f0e8cd41d9..abfc5463c8ffb 100644
--- a/compiler/rustc_middle/src/ty/flags.rs
+++ b/compiler/rustc_middle/src/ty/flags.rs
@@ -113,6 +113,7 @@ impl FlagComputation {
                     self.flags -= TypeFlags::STILL_FURTHER_SPECIALIZABLE;
                 }
 
+                self.add_ty(args.kind_ty());
                 self.add_ty(args.resume_ty());
                 self.add_ty(args.return_ty());
                 self.add_ty(args.witness());

From e4f13e3ccd143b866044f7875d3caf866cfa66fd Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Sun, 23 Mar 2025 16:37:27 +0000
Subject: [PATCH 18/19] Remove HAS_TY_COROUTINE

---
 compiler/rustc_middle/src/ty/flags.rs | 1 -
 compiler/rustc_type_ir/src/flags.rs   | 5 +----
 compiler/rustc_type_ir/src/visit.rs   | 4 ----
 3 files changed, 1 insertion(+), 9 deletions(-)

diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs
index abfc5463c8ffb..8d5a213b74604 100644
--- a/compiler/rustc_middle/src/ty/flags.rs
+++ b/compiler/rustc_middle/src/ty/flags.rs
@@ -128,7 +128,6 @@ impl FlagComputation {
                 if should_remove_further_specializable {
                     self.flags -= TypeFlags::STILL_FURTHER_SPECIALIZABLE;
                 }
-                self.add_flags(TypeFlags::HAS_TY_COROUTINE);
             }
 
             &ty::Closure(_, args) => {
diff --git a/compiler/rustc_type_ir/src/flags.rs b/compiler/rustc_type_ir/src/flags.rs
index 81aa4a1f19ee0..fe401b11f3965 100644
--- a/compiler/rustc_type_ir/src/flags.rs
+++ b/compiler/rustc_type_ir/src/flags.rs
@@ -119,10 +119,7 @@ bitflags::bitflags! {
         /// Does this value have `InferConst::Fresh`?
         const HAS_CT_FRESH                = 1 << 23;
 
-        /// Does this have `Coroutine` or `CoroutineWitness`?
-        const HAS_TY_COROUTINE            = 1 << 24;
-
         /// Does this have any binders with bound vars (e.g. that need to be anonymized)?
-        const HAS_BINDER_VARS             = 1 << 25;
+        const HAS_BINDER_VARS             = 1 << 24;
     }
 }
diff --git a/compiler/rustc_type_ir/src/visit.rs b/compiler/rustc_type_ir/src/visit.rs
index 119b658a2bf3f..2285e0e75de04 100644
--- a/compiler/rustc_type_ir/src/visit.rs
+++ b/compiler/rustc_type_ir/src/visit.rs
@@ -269,10 +269,6 @@ pub trait TypeVisitableExt<I: Interner>: TypeVisitable<I> {
         self.has_type_flags(TypeFlags::HAS_TY_OPAQUE)
     }
 
-    fn has_coroutines(&self) -> bool {
-        self.has_type_flags(TypeFlags::HAS_TY_COROUTINE)
-    }
-
     fn references_error(&self) -> bool {
         self.has_type_flags(TypeFlags::HAS_ERROR)
     }

From 77a106e61fe8331e646212382cd2ee5d2bbcd149 Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Sun, 23 Mar 2025 16:44:30 +0000
Subject: [PATCH 19/19] Remove STILL_FURTHER_SPECIALIZABLE special casing

---
 compiler/rustc_middle/src/ty/flags.rs | 89 +++++----------------------
 compiler/rustc_type_ir/src/flags.rs   | 13 ++--
 2 files changed, 24 insertions(+), 78 deletions(-)

diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs
index 8d5a213b74604..b0c442d28f0a0 100644
--- a/compiler/rustc_middle/src/ty/flags.rs
+++ b/compiler/rustc_middle/src/ty/flags.rs
@@ -101,63 +101,13 @@ impl FlagComputation {
 
             &ty::Param(_) => {
                 self.add_flags(TypeFlags::HAS_TY_PARAM);
-                self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
             }
 
-            ty::Coroutine(_, args) => {
-                let args = args.as_coroutine();
-                let should_remove_further_specializable =
-                    !self.flags.contains(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
-                self.add_args(args.parent_args());
-                if should_remove_further_specializable {
-                    self.flags -= TypeFlags::STILL_FURTHER_SPECIALIZABLE;
-                }
-
-                self.add_ty(args.kind_ty());
-                self.add_ty(args.resume_ty());
-                self.add_ty(args.return_ty());
-                self.add_ty(args.witness());
-                self.add_ty(args.yield_ty());
-                self.add_ty(args.tupled_upvars_ty());
-            }
-
-            ty::CoroutineWitness(_, args) => {
-                let should_remove_further_specializable =
-                    !self.flags.contains(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
+            &ty::Closure(_, args)
+            | &ty::Coroutine(_, args)
+            | &ty::CoroutineClosure(_, args)
+            | &ty::CoroutineWitness(_, args) => {
                 self.add_args(args);
-                if should_remove_further_specializable {
-                    self.flags -= TypeFlags::STILL_FURTHER_SPECIALIZABLE;
-                }
-            }
-
-            &ty::Closure(_, args) => {
-                let args = args.as_closure();
-                let should_remove_further_specializable =
-                    !self.flags.contains(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
-                self.add_args(args.parent_args());
-                if should_remove_further_specializable {
-                    self.flags -= TypeFlags::STILL_FURTHER_SPECIALIZABLE;
-                }
-
-                self.add_ty(args.sig_as_fn_ptr_ty());
-                self.add_ty(args.kind_ty());
-                self.add_ty(args.tupled_upvars_ty());
-            }
-
-            &ty::CoroutineClosure(_, args) => {
-                let args = args.as_coroutine_closure();
-                let should_remove_further_specializable =
-                    !self.flags.contains(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
-                self.add_args(args.parent_args());
-                if should_remove_further_specializable {
-                    self.flags -= TypeFlags::STILL_FURTHER_SPECIALIZABLE;
-                }
-
-                self.add_ty(args.kind_ty());
-                self.add_ty(args.signature_parts_ty());
-                self.add_ty(args.tupled_upvars_ty());
-                self.add_ty(args.coroutine_captures_by_ref_ty());
-                self.add_ty(args.coroutine_witness_ty());
             }
 
             &ty::Bound(debruijn, _) => {
@@ -167,21 +117,17 @@ impl FlagComputation {
 
             &ty::Placeholder(..) => {
                 self.add_flags(TypeFlags::HAS_TY_PLACEHOLDER);
-                self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
             }
 
-            &ty::Infer(infer) => {
-                self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
-                match infer {
-                    ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => {
-                        self.add_flags(TypeFlags::HAS_TY_FRESH)
-                    }
+            &ty::Infer(infer) => match infer {
+                ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => {
+                    self.add_flags(TypeFlags::HAS_TY_FRESH)
+                }
 
-                    ty::TyVar(_) | ty::IntVar(_) | ty::FloatVar(_) => {
-                        self.add_flags(TypeFlags::HAS_TY_INFER)
-                    }
+                ty::TyVar(_) | ty::IntVar(_) | ty::FloatVar(_) => {
+                    self.add_flags(TypeFlags::HAS_TY_INFER)
                 }
-            }
+            },
 
             &ty::Adt(_, args) => {
                 self.add_args(args);
@@ -358,24 +304,19 @@ impl FlagComputation {
                 self.add_args(uv.args);
                 self.add_flags(TypeFlags::HAS_CT_PROJECTION);
             }
-            ty::ConstKind::Infer(infer) => {
-                self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
-                match infer {
-                    InferConst::Fresh(_) => self.add_flags(TypeFlags::HAS_CT_FRESH),
-                    InferConst::Var(_) => self.add_flags(TypeFlags::HAS_CT_INFER),
-                }
-            }
+            ty::ConstKind::Infer(infer) => match infer {
+                InferConst::Fresh(_) => self.add_flags(TypeFlags::HAS_CT_FRESH),
+                InferConst::Var(_) => self.add_flags(TypeFlags::HAS_CT_INFER),
+            },
             ty::ConstKind::Bound(debruijn, _) => {
                 self.add_bound_var(debruijn);
                 self.add_flags(TypeFlags::HAS_CT_BOUND);
             }
             ty::ConstKind::Param(_) => {
                 self.add_flags(TypeFlags::HAS_CT_PARAM);
-                self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
             }
             ty::ConstKind::Placeholder(_) => {
                 self.add_flags(TypeFlags::HAS_CT_PLACEHOLDER);
-                self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
             }
             ty::ConstKind::Value(cv) => self.add_ty(cv.ty),
             ty::ConstKind::Expr(e) => self.add_args(e.args()),
diff --git a/compiler/rustc_type_ir/src/flags.rs b/compiler/rustc_type_ir/src/flags.rs
index fe401b11f3965..6a2498242feeb 100644
--- a/compiler/rustc_type_ir/src/flags.rs
+++ b/compiler/rustc_type_ir/src/flags.rs
@@ -111,15 +111,20 @@ bitflags::bitflags! {
 
         /// Does this value have parameters/placeholders/inference variables which could be
         /// replaced later, in a way that would change the results of `impl` specialization?
-        const STILL_FURTHER_SPECIALIZABLE = 1 << 21;
+        const STILL_FURTHER_SPECIALIZABLE = TypeFlags::HAS_TY_PARAM.bits()
+                                          | TypeFlags::HAS_TY_PLACEHOLDER.bits()
+                                          | TypeFlags::HAS_TY_INFER.bits()
+                                          | TypeFlags::HAS_CT_PARAM.bits()
+                                          | TypeFlags::HAS_CT_PLACEHOLDER.bits()
+                                          | TypeFlags::HAS_CT_INFER.bits();
 
         /// Does this value have `InferTy::FreshTy/FreshIntTy/FreshFloatTy`?
-        const HAS_TY_FRESH                = 1 << 22;
+        const HAS_TY_FRESH                = 1 << 21;
 
         /// Does this value have `InferConst::Fresh`?
-        const HAS_CT_FRESH                = 1 << 23;
+        const HAS_CT_FRESH                = 1 << 22;
 
         /// Does this have any binders with bound vars (e.g. that need to be anonymized)?
-        const HAS_BINDER_VARS             = 1 << 24;
+        const HAS_BINDER_VARS             = 1 << 23;
     }
 }