diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index de04d882f51..79d52914381 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -556,6 +556,9 @@ lint_non_fmt_panic_unused =
     }
     .add_fmt_suggestion = or add a "{"{"}{"}"}" format string to use the message literally
 
+lint_non_glob_import_type_ir_inherent = non-glob import of `rustc_type_ir::inherent`
+    .suggestion = try using a glob import instead
+
 lint_non_local_definitions_cargo_update = the {$macro_kind} `{$macro_name}` may come from an old version of the `{$crate_name}` crate, try updating your dependency with `cargo update -p {$crate_name}`
 
 lint_non_local_definitions_deprecation = this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs
index 772cc2ff8b9..e15eb90f827 100644
--- a/compiler/rustc_lint/src/internal.rs
+++ b/compiler/rustc_lint/src/internal.rs
@@ -3,7 +3,8 @@
 
 use crate::lints::{
     BadOptAccessDiag, DefaultHashTypesDiag, DiagOutOfImpl, LintPassByHand, NonExistentDocKeyword,
-    QueryInstability, SpanUseEqCtxtDiag, TyQualified, TykindDiag, TykindKind, UntranslatableDiag,
+    NonGlobImportTypeIrInherent, QueryInstability, SpanUseEqCtxtDiag, TyQualified, TykindDiag,
+    TykindKind, UntranslatableDiag,
 };
 use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
 use rustc_ast as ast;
@@ -263,6 +264,49 @@ fn gen_args(segment: &PathSegment<'_>) -> String {
     String::new()
 }
 
+declare_tool_lint! {
+    /// The `non_glob_import_of_type_ir_inherent_item` lint detects
+    /// non-glob imports of module `rustc_type_ir::inherent`.
+    pub rustc::NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT,
+    Allow,
+    "non-glob import of `rustc_type_ir::inherent`",
+    report_in_external_macro: true
+}
+
+declare_lint_pass!(TypeIr => [NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT]);
+
+impl<'tcx> LateLintPass<'tcx> for TypeIr {
+    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
+        let rustc_hir::ItemKind::Use(path, kind) = item.kind else { return };
+
+        let is_mod_inherent = |def_id| cx.tcx.is_diagnostic_item(sym::type_ir_inherent, def_id);
+        let (lo, hi, snippet) = match path.segments {
+            [.., penultimate, segment]
+                if penultimate.res.opt_def_id().is_some_and(is_mod_inherent) =>
+            {
+                (segment.ident.span, item.ident.span, "*")
+            }
+            [.., segment]
+                if path.res.iter().flat_map(Res::opt_def_id).any(is_mod_inherent)
+                    && let rustc_hir::UseKind::Single = kind =>
+            {
+                let (lo, snippet) =
+                    match cx.tcx.sess.source_map().span_to_snippet(path.span).as_deref() {
+                        Ok("self") => (path.span, "*"),
+                        _ => (segment.ident.span.shrink_to_hi(), "::*"),
+                    };
+                (lo, if segment.ident == item.ident { lo } else { item.ident.span }, snippet)
+            }
+            _ => return,
+        };
+        cx.emit_span_lint(
+            NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT,
+            path.span,
+            NonGlobImportTypeIrInherent { suggestion: lo.eq_ctxt(hi).then(|| lo.to(hi)), snippet },
+        );
+    }
+}
+
 declare_tool_lint! {
     /// The `lint_pass_impl_without_macro` detects manual implementations of a lint
     /// pass, without using [`declare_lint_pass`] or [`impl_lint_pass`].
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index 4e83ef0c629..290f91045c4 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -572,6 +572,8 @@ fn register_internals(store: &mut LintStore) {
     store.register_late_mod_pass(|_| Box::new(ExistingDocKeyword));
     store.register_lints(&TyTyKind::get_lints());
     store.register_late_mod_pass(|_| Box::new(TyTyKind));
+    store.register_lints(&TypeIr::get_lints());
+    store.register_late_mod_pass(|_| Box::new(TypeIr));
     store.register_lints(&Diagnostics::get_lints());
     store.register_late_mod_pass(|_| Box::new(Diagnostics));
     store.register_lints(&BadOptAccess::get_lints());
@@ -595,6 +597,7 @@ fn register_internals(store: &mut LintStore) {
             LintId::of(PASS_BY_VALUE),
             LintId::of(LINT_PASS_IMPL_WITHOUT_MACRO),
             LintId::of(USAGE_OF_QUALIFIED_TY),
+            LintId::of(NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT),
             LintId::of(EXISTING_DOC_KEYWORD),
             LintId::of(BAD_OPT_ACCESS),
             LintId::of(SPAN_USE_EQ_CTXT),
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 308bb73f4ce..ac5511faf19 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -926,6 +926,14 @@ pub struct TyQualified {
     pub suggestion: Span,
 }
 
+#[derive(LintDiagnostic)]
+#[diag(lint_non_glob_import_type_ir_inherent)]
+pub struct NonGlobImportTypeIrInherent {
+    #[suggestion(code = "{snippet}", applicability = "maybe-incorrect")]
+    pub suggestion: Option<Span>,
+    pub snippet: &'static str,
+}
+
 #[derive(LintDiagnostic)]
 #[diag(lint_lintpass_by_hand)]
 #[help]
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index aa7844f4012..04764b71b10 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -1203,16 +1203,16 @@ declare_lint! {
     /// This was historically allowed, but is not the intended behavior
     /// according to the visibility rules. This is a [future-incompatible]
     /// lint to transition this to a hard error in the future. See [issue
-    /// #34537] for more details.
+    /// #127909] for more details.
     ///
-    /// [issue #34537]: https://github.com/rust-lang/rust/issues/34537
+    /// [issue #127909]: https://github.com/rust-lang/rust/issues/127909
     /// [future-incompatible]: ../index.md#future-incompatible-lints
     pub PUB_USE_OF_PRIVATE_EXTERN_CRATE,
     Deny,
     "detect public re-exports of private extern crates",
     @future_incompatible = FutureIncompatibleInfo {
-        reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
-        reference: "issue #34537 <https://github.com/rust-lang/rust/issues/34537>",
+        reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
+        reference: "issue #127909 <https://github.com/rust-lang/rust/issues/127909>",
     };
 }
 
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 2fe7c951793..b64efadb261 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1926,6 +1926,7 @@ symbols! {
         type_ascription,
         type_changing_struct_update,
         type_id,
+        type_ir_inherent,
         type_length_limit,
         type_macros,
         type_name,
diff --git a/compiler/rustc_type_ir/src/effects.rs b/compiler/rustc_type_ir/src/effects.rs
index d1c3c8e5223..a29e0a43bef 100644
--- a/compiler/rustc_type_ir/src/effects.rs
+++ b/compiler/rustc_type_ir/src/effects.rs
@@ -1,4 +1,4 @@
-use crate::inherent::{AdtDef, IntoKind, Ty};
+use crate::inherent::*;
 use crate::lang_items::TraitSolverLangItem::{EffectsMaybe, EffectsNoRuntime, EffectsRuntime};
 use crate::Interner;
 
diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs
index 37ee66fa222..80e970a23a9 100644
--- a/compiler/rustc_type_ir/src/lib.rs
+++ b/compiler/rustc_type_ir/src/lib.rs
@@ -24,6 +24,7 @@ pub mod elaborate;
 pub mod error;
 pub mod fast_reject;
 pub mod fold;
+#[cfg_attr(feature = "nightly", rustc_diagnostic_item = "type_ir_inherent")]
 pub mod inherent;
 pub mod ir_print;
 pub mod lang_items;
diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index 8ec7716012f..1a8fe1e6051 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -770,6 +770,13 @@ impl<T> Option<T> {
         }
     }
 
+    #[inline]
+    const fn len(&self) -> usize {
+        // Using the intrinsic avoids emitting a branch to get the 0 or 1.
+        let discriminant: isize = crate::intrinsics::discriminant_value(self);
+        discriminant as usize
+    }
+
     /// Returns a slice of the contained value, if any. If this is `None`, an
     /// empty slice is returned. This can be useful to have a single type of
     /// iterator over an `Option` or slice.
@@ -812,7 +819,7 @@ impl<T> Option<T> {
         unsafe {
             slice::from_raw_parts(
                 (self as *const Self).byte_add(core::mem::offset_of!(Self, Some.0)).cast(),
-                self.is_some() as usize,
+                self.len(),
             )
         }
     }
@@ -869,7 +876,7 @@ impl<T> Option<T> {
         unsafe {
             slice::from_raw_parts_mut(
                 (self as *mut Self).byte_add(core::mem::offset_of!(Self, Some.0)).cast(),
-                self.is_some() as usize,
+                self.len(),
             )
         }
     }
@@ -2242,10 +2249,8 @@ impl<A> Iterator for Item<A> {
 
     #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
-        match self.opt {
-            Some(_) => (1, Some(1)),
-            None => (0, Some(0)),
-        }
+        let len = self.len();
+        (len, Some(len))
     }
 }
 
@@ -2256,7 +2261,12 @@ impl<A> DoubleEndedIterator for Item<A> {
     }
 }
 
-impl<A> ExactSizeIterator for Item<A> {}
+impl<A> ExactSizeIterator for Item<A> {
+    #[inline]
+    fn len(&self) -> usize {
+        self.opt.len()
+    }
+}
 impl<A> FusedIterator for Item<A> {}
 unsafe impl<A> TrustedLen for Item<A> {}
 
diff --git a/library/std/src/sync/reentrant_lock.rs b/library/std/src/sync/reentrant_lock.rs
index 042c439394e..84a0b36db17 100644
--- a/library/std/src/sync/reentrant_lock.rs
+++ b/library/std/src/sync/reentrant_lock.rs
@@ -1,12 +1,14 @@
 #[cfg(all(test, not(target_os = "emscripten")))]
 mod tests;
 
+use cfg_if::cfg_if;
+
 use crate::cell::UnsafeCell;
 use crate::fmt;
 use crate::ops::Deref;
 use crate::panic::{RefUnwindSafe, UnwindSafe};
-use crate::sync::atomic::{AtomicUsize, Ordering::Relaxed};
 use crate::sys::sync as sys;
+use crate::thread::{current_id, ThreadId};
 
 /// A re-entrant mutual exclusion lock
 ///
@@ -53,8 +55,8 @@ use crate::sys::sync as sys;
 //
 // The 'owner' field tracks which thread has locked the mutex.
 //
-// We use current_thread_unique_ptr() as the thread identifier,
-// which is just the address of a thread local variable.
+// We use thread::current_id() as the thread identifier, which is just the
+// current thread's ThreadId, so it's unique across the process lifetime.
 //
 // If `owner` is set to the identifier of the current thread,
 // we assume the mutex is already locked and instead of locking it again,
@@ -72,14 +74,109 @@ use crate::sys::sync as sys;
 // since we're not dealing with multiple threads. If it's not equal,
 // synchronization is left to the mutex, making relaxed memory ordering for
 // the `owner` field fine in all cases.
+//
+// On systems without 64 bit atomics we also store the address of a TLS variable
+// along the 64-bit TID. We then first check that address against the address
+// of that variable on the current thread, and only if they compare equal do we
+// compare the actual TIDs. Because we only ever read the TID on the same thread
+// that it was written on (or a thread sharing the TLS block with that writer thread),
+// we don't need to further synchronize the TID accesses, so they can be regular 64-bit
+// non-atomic accesses.
 #[unstable(feature = "reentrant_lock", issue = "121440")]
 pub struct ReentrantLock<T: ?Sized> {
     mutex: sys::Mutex,
-    owner: AtomicUsize,
+    owner: Tid,
     lock_count: UnsafeCell<u32>,
     data: T,
 }
 
+cfg_if!(
+    if #[cfg(target_has_atomic = "64")] {
+        use crate::sync::atomic::{AtomicU64, Ordering::Relaxed};
+
+        struct Tid(AtomicU64);
+
+        impl Tid {
+            const fn new() -> Self {
+                Self(AtomicU64::new(0))
+            }
+
+            #[inline]
+            fn contains(&self, owner: ThreadId) -> bool {
+                owner.as_u64().get() == self.0.load(Relaxed)
+            }
+
+            #[inline]
+            // This is just unsafe to match the API of the Tid type below.
+            unsafe fn set(&self, tid: Option<ThreadId>) {
+                let value = tid.map_or(0, |tid| tid.as_u64().get());
+                self.0.store(value, Relaxed);
+            }
+        }
+    } else {
+        /// Returns the address of a TLS variable. This is guaranteed to
+        /// be unique across all currently alive threads.
+        fn tls_addr() -> usize {
+            thread_local! { static X: u8 = const { 0u8 } };
+
+            X.with(|p| <*const u8>::addr(p))
+        }
+
+        use crate::sync::atomic::{
+            AtomicUsize,
+            Ordering,
+        };
+
+        struct Tid {
+            // When a thread calls `set()`, this value gets updated to
+            // the address of a thread local on that thread. This is
+            // used as a first check in `contains()`; if the `tls_addr`
+            // doesn't match the TLS address of the current thread, then
+            // the ThreadId also can't match. Only if the TLS addresses do
+            // match do we read out the actual TID.
+            // Note also that we can use relaxed atomic operations here, because
+            // we only ever read from the tid if `tls_addr` matches the current
+            // TLS address. In that case, either the the tid has been set by
+            // the current thread, or by a thread that has terminated before
+            // the current thread was created. In either case, no further
+            // synchronization is needed (as per <https://github.com/rust-lang/miri/issues/3450>)
+            tls_addr: AtomicUsize,
+            tid: UnsafeCell<u64>,
+        }
+
+        unsafe impl Send for Tid {}
+        unsafe impl Sync for Tid {}
+
+        impl Tid {
+            const fn new() -> Self {
+                Self { tls_addr: AtomicUsize::new(0), tid: UnsafeCell::new(0) }
+            }
+
+            #[inline]
+            // NOTE: This assumes that `owner` is the ID of the current
+            // thread, and may spuriously return `false` if that's not the case.
+            fn contains(&self, owner: ThreadId) -> bool {
+                // SAFETY: See the comments in the struct definition.
+                self.tls_addr.load(Ordering::Relaxed) == tls_addr()
+                    && unsafe { *self.tid.get() } == owner.as_u64().get()
+            }
+
+            #[inline]
+            // This may only be called by one thread at a time, and can lead to
+            // race conditions otherwise.
+            unsafe fn set(&self, tid: Option<ThreadId>) {
+                // It's important that we set `self.tls_addr` to 0 if the tid is
+                // cleared. Otherwise, there might be race conditions between
+                // `set()` and `get()`.
+                let tls_addr = if tid.is_some() { tls_addr() } else { 0 };
+                let value = tid.map_or(0, |tid| tid.as_u64().get());
+                self.tls_addr.store(tls_addr, Ordering::Relaxed);
+                unsafe { *self.tid.get() = value };
+            }
+        }
+    }
+);
+
 #[unstable(feature = "reentrant_lock", issue = "121440")]
 unsafe impl<T: Send + ?Sized> Send for ReentrantLock<T> {}
 #[unstable(feature = "reentrant_lock", issue = "121440")]
@@ -134,7 +231,7 @@ impl<T> ReentrantLock<T> {
     pub const fn new(t: T) -> ReentrantLock<T> {
         ReentrantLock {
             mutex: sys::Mutex::new(),
-            owner: AtomicUsize::new(0),
+            owner: Tid::new(),
             lock_count: UnsafeCell::new(0),
             data: t,
         }
@@ -184,14 +281,16 @@ impl<T: ?Sized> ReentrantLock<T> {
     /// assert_eq!(lock.lock().get(), 10);
     /// ```
     pub fn lock(&self) -> ReentrantLockGuard<'_, T> {
-        let this_thread = current_thread_unique_ptr();
-        // Safety: We only touch lock_count when we own the lock.
+        let this_thread = current_id();
+        // Safety: We only touch lock_count when we own the inner mutex.
+        // Additionally, we only call `self.owner.set()` while holding
+        // the inner mutex, so no two threads can call it concurrently.
         unsafe {
-            if self.owner.load(Relaxed) == this_thread {
+            if self.owner.contains(this_thread) {
                 self.increment_lock_count().expect("lock count overflow in reentrant mutex");
             } else {
                 self.mutex.lock();
-                self.owner.store(this_thread, Relaxed);
+                self.owner.set(Some(this_thread));
                 debug_assert_eq!(*self.lock_count.get(), 0);
                 *self.lock_count.get() = 1;
             }
@@ -226,14 +325,16 @@ impl<T: ?Sized> ReentrantLock<T> {
     ///
     /// This function does not block.
     pub(crate) fn try_lock(&self) -> Option<ReentrantLockGuard<'_, T>> {
-        let this_thread = current_thread_unique_ptr();
-        // Safety: We only touch lock_count when we own the lock.
+        let this_thread = current_id();
+        // Safety: We only touch lock_count when we own the inner mutex.
+        // Additionally, we only call `self.owner.set()` while holding
+        // the inner mutex, so no two threads can call it concurrently.
         unsafe {
-            if self.owner.load(Relaxed) == this_thread {
+            if self.owner.contains(this_thread) {
                 self.increment_lock_count()?;
                 Some(ReentrantLockGuard { lock: self })
             } else if self.mutex.try_lock() {
-                self.owner.store(this_thread, Relaxed);
+                self.owner.set(Some(this_thread));
                 debug_assert_eq!(*self.lock_count.get(), 0);
                 *self.lock_count.get() = 1;
                 Some(ReentrantLockGuard { lock: self })
@@ -308,18 +409,9 @@ impl<T: ?Sized> Drop for ReentrantLockGuard<'_, T> {
         unsafe {
             *self.lock.lock_count.get() -= 1;
             if *self.lock.lock_count.get() == 0 {
-                self.lock.owner.store(0, Relaxed);
+                self.lock.owner.set(None);
                 self.lock.mutex.unlock();
             }
         }
     }
 }
-
-/// Get an address that is unique per running thread.
-///
-/// This can be used as a non-null usize-sized ID.
-pub(crate) fn current_thread_unique_ptr() -> usize {
-    // Use a non-drop type to make sure it's still available during thread destruction.
-    thread_local! { static X: u8 = const { 0 } }
-    X.with(|x| <*const _>::addr(x))
-}
diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs
index c8ee365392f..7b98f2ae763 100644
--- a/library/std/src/thread/mod.rs
+++ b/library/std/src/thread/mod.rs
@@ -159,7 +159,7 @@
 mod tests;
 
 use crate::any::Any;
-use crate::cell::{OnceCell, UnsafeCell};
+use crate::cell::{Cell, OnceCell, UnsafeCell};
 use crate::env;
 use crate::ffi::{CStr, CString};
 use crate::fmt;
@@ -699,17 +699,22 @@ where
 }
 
 thread_local! {
+    // Invariant: `CURRENT` and `CURRENT_ID` will always be initialized together.
+    // If `CURRENT` is initialized, then `CURRENT_ID` will hold the same value
+    // as `CURRENT.id()`.
     static CURRENT: OnceCell<Thread> = const { OnceCell::new() };
+    static CURRENT_ID: Cell<Option<ThreadId>> = const { Cell::new(None) };
 }
 
 /// Sets the thread handle for the current thread.
 ///
 /// Aborts if the handle has been set already to reduce code size.
 pub(crate) fn set_current(thread: Thread) {
+    let tid = thread.id();
     // Using `unwrap` here can add ~3kB to the binary size. We have complete
     // control over where this is called, so just abort if there is a bug.
     CURRENT.with(|current| match current.set(thread) {
-        Ok(()) => {}
+        Ok(()) => CURRENT_ID.set(Some(tid)),
         Err(_) => rtabort!("thread::set_current should only be called once per thread"),
     });
 }
@@ -719,7 +724,28 @@ pub(crate) fn set_current(thread: Thread) {
 /// In contrast to the public `current` function, this will not panic if called
 /// from inside a TLS destructor.
 pub(crate) fn try_current() -> Option<Thread> {
-    CURRENT.try_with(|current| current.get_or_init(|| Thread::new_unnamed()).clone()).ok()
+    CURRENT
+        .try_with(|current| {
+            current
+                .get_or_init(|| {
+                    let thread = Thread::new_unnamed();
+                    CURRENT_ID.set(Some(thread.id()));
+                    thread
+                })
+                .clone()
+        })
+        .ok()
+}
+
+/// Gets the id of the thread that invokes it.
+#[inline]
+pub(crate) fn current_id() -> ThreadId {
+    CURRENT_ID.get().unwrap_or_else(|| {
+        // If `CURRENT_ID` isn't initialized yet, then `CURRENT` must also not be initialized.
+        // `current()` will initialize both `CURRENT` and `CURRENT_ID` so subsequent calls to
+        // `current_id()` will succeed immediately.
+        current().id()
+    })
 }
 
 /// Gets a handle to the thread that invokes it.
diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs
index db1fa05a82c..a77c20067e6 100644
--- a/src/bootstrap/src/lib.rs
+++ b/src/bootstrap/src/lib.rs
@@ -535,6 +535,7 @@ impl Build {
             // even though that has no relation to the upstream for the submodule.
             let current_branch = helpers::git(Some(&self.src))
                 .capture_stdout()
+                .allow_failure()
                 .run_always()
                 .args(["symbolic-ref", "--short", "HEAD"])
                 .run(self)
diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md
index cd10168bc1c..cb43feca758 100644
--- a/src/doc/rustc/src/codegen-options/index.md
+++ b/src/doc/rustc/src/codegen-options/index.md
@@ -410,13 +410,16 @@ See also the [`no-prepopulate-passes`](#no-prepopulate-passes) flag.
 
 By default, `rustc` prefers to statically link dependencies. This option will
 indicate that dynamic linking should be used if possible if both a static and
-dynamic versions of a library are available. There is an internal algorithm
-for determining whether or not it is possible to statically or dynamically
-link with a dependency. For example, `cdylib` crate types may only use static
-linkage. This flag takes one of the following values:
+dynamic versions of a library are available.
 
-* `y`, `yes`, `on`, `true` or no value: use dynamic linking.
-* `n`, `no`, `off` or `false`: use static linking (the default).
+There is [an internal algorithm](https://github.com/rust-lang/rust/blob/master/compiler/rustc_metadata/src/dependency_format.rs)
+for determining whether or not it is possible to statically or dynamically link
+with a dependency.
+
+This flag takes one of the following values:
+
+* `y`, `yes`, `on`, `true` or no value: prefer dynamic linking.
+* `n`, `no`, `off` or `false`: prefer static linking (the default).
 
 ## profile-generate
 
diff --git a/tests/codegen/option-as-slice.rs b/tests/codegen/option-as-slice.rs
index 65637a2495d..cfa479aa4b2 100644
--- a/tests/codegen/option-as-slice.rs
+++ b/tests/codegen/option-as-slice.rs
@@ -14,6 +14,14 @@ pub fn u64_opt_as_slice(o: &Option<u64>) -> &[u64] {
     // CHECK-NOT: br
     // CHECK-NOT: switch
     // CHECK-NOT: icmp
+    // CHECK: %[[LEN:.+]] = load i64,{{.+}} !range ![[META_U64:.+]], !noundef
+    // CHECK-NOT: select
+    // CHECK-NOT: br
+    // CHECK-NOT: switch
+    // CHECK-NOT: icmp
+    // CHECK: %[[T0:.+]] = insertvalue { ptr, i64 } poison, ptr %{{.+}}, 0
+    // CHECK-NEXT: %[[T1:.+]] = insertvalue { ptr, i64 } %[[T0]], i64 %[[LEN]], 1
+    // CHECK-NEXT: ret { ptr, i64 } %[[T1]]
     o.as_slice()
 }
 
@@ -25,10 +33,35 @@ pub fn nonzero_u64_opt_as_slice(o: &Option<NonZero<u64>>) -> &[NonZero<u64>] {
     // CHECK-NOT: switch
     // CHECK-NOT: icmp
     // CHECK: %[[NZ:.+]] = icmp ne i64 %{{.+}}, 0
-    // CHECK-NEXT: zext i1 %[[NZ]] to i64
+    // CHECK-NEXT: %[[LEN:.+]] = zext i1 %[[NZ]] to i64
     // CHECK-NOT: select
     // CHECK-NOT: br
     // CHECK-NOT: switch
     // CHECK-NOT: icmp
+    // CHECK: %[[T0:.+]] = insertvalue { ptr, i64 } poison, ptr %o, 0
+    // CHECK-NEXT: %[[T1:.+]] = insertvalue { ptr, i64 } %[[T0]], i64 %[[LEN]], 1
+    // CHECK-NEXT: ret { ptr, i64 } %[[T1]]
     o.as_slice()
 }
+
+// CHECK-LABEL: @u8_opt_as_slice
+#[no_mangle]
+pub fn u8_opt_as_slice(o: &Option<u8>) -> &[u8] {
+    // CHECK-NOT: select
+    // CHECK-NOT: br
+    // CHECK-NOT: switch
+    // CHECK-NOT: icmp
+    // CHECK: %[[TAG:.+]] = load i8,{{.+}} !range ![[META_U8:.+]], !noundef
+    // CHECK: %[[LEN:.+]] = zext{{.*}} i8 %[[TAG]] to i64
+    // CHECK-NOT: select
+    // CHECK-NOT: br
+    // CHECK-NOT: switch
+    // CHECK-NOT: icmp
+    // CHECK: %[[T0:.+]] = insertvalue { ptr, i64 } poison, ptr %{{.+}}, 0
+    // CHECK-NEXT: %[[T1:.+]] = insertvalue { ptr, i64 } %[[T0]], i64 %[[LEN]], 1
+    // CHECK-NEXT: ret { ptr, i64 } %[[T1]]
+    o.as_slice()
+}
+
+// CHECK: ![[META_U64]] = !{i64 0, i64 2}
+// CHECK: ![[META_U8]] = !{i8 0, i8 2}
diff --git a/tests/ui-fulldeps/internal-lints/non_glob_import_of_type_ir_inherent.rs b/tests/ui-fulldeps/internal-lints/non_glob_import_of_type_ir_inherent.rs
new file mode 100644
index 00000000000..33e10a00713
--- /dev/null
+++ b/tests/ui-fulldeps/internal-lints/non_glob_import_of_type_ir_inherent.rs
@@ -0,0 +1,38 @@
+//@ compile-flags: -Z unstable-options
+//@ ignore-stage1 (can be removed after beta bump, #[cfg(bootstrap)])
+#![feature(rustc_private)]
+#![deny(rustc::non_glob_import_of_type_ir_inherent)]
+
+extern crate rustc_type_ir;
+
+mod ok {
+    use rustc_type_ir::inherent::*; // OK
+    use rustc_type_ir::inherent::{}; // OK
+    use rustc_type_ir::inherent::{*}; // OK
+
+    fn usage<T: rustc_type_ir::inherent::SliceLike>() {} // OK
+}
+
+mod direct {
+    use rustc_type_ir::inherent::Predicate; //~ ERROR non-glob import of `rustc_type_ir::inherent`
+    use rustc_type_ir::inherent::{AdtDef, Ty};
+    //~^ ERROR non-glob import of `rustc_type_ir::inherent`
+    //~| ERROR non-glob import of `rustc_type_ir::inherent`
+    use rustc_type_ir::inherent::ParamEnv as _; //~ ERROR non-glob import of `rustc_type_ir::inherent`
+}
+
+mod indirect0 {
+    use rustc_type_ir::inherent; //~ ERROR non-glob import of `rustc_type_ir::inherent`
+    use rustc_type_ir::inherent as inh; //~ ERROR non-glob import of `rustc_type_ir::inherent`
+    use rustc_type_ir::{inherent as _}; //~ ERROR non-glob import of `rustc_type_ir::inherent`
+
+    fn usage0<T: inherent::SliceLike>() {}
+    fn usage1<T: inh::SliceLike>() {}
+}
+
+mod indirect1 {
+    use rustc_type_ir::inherent::{self}; //~ ERROR non-glob import of `rustc_type_ir::inherent`
+    use rustc_type_ir::inherent::{self as innate}; //~ ERROR non-glob import of `rustc_type_ir::inherent`
+}
+
+fn main() {}
diff --git a/tests/ui-fulldeps/internal-lints/non_glob_import_of_type_ir_inherent.stderr b/tests/ui-fulldeps/internal-lints/non_glob_import_of_type_ir_inherent.stderr
new file mode 100644
index 00000000000..84e3867c95b
--- /dev/null
+++ b/tests/ui-fulldeps/internal-lints/non_glob_import_of_type_ir_inherent.stderr
@@ -0,0 +1,68 @@
+error: non-glob import of `rustc_type_ir::inherent`
+  --> $DIR/non_glob_import_of_type_ir_inherent.rs:17:9
+   |
+LL |     use rustc_type_ir::inherent::Predicate;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^---------
+   |                                  |
+   |                                  help: try using a glob import instead: `*`
+   |
+note: the lint level is defined here
+  --> $DIR/non_glob_import_of_type_ir_inherent.rs:4:9
+   |
+LL | #![deny(rustc::non_glob_import_of_type_ir_inherent)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: non-glob import of `rustc_type_ir::inherent`
+  --> $DIR/non_glob_import_of_type_ir_inherent.rs:18:35
+   |
+LL |     use rustc_type_ir::inherent::{AdtDef, Ty};
+   |                                   ^^^^^^ help: try using a glob import instead: `*`
+
+error: non-glob import of `rustc_type_ir::inherent`
+  --> $DIR/non_glob_import_of_type_ir_inherent.rs:18:43
+   |
+LL |     use rustc_type_ir::inherent::{AdtDef, Ty};
+   |                                           ^^ help: try using a glob import instead: `*`
+
+error: non-glob import of `rustc_type_ir::inherent`
+  --> $DIR/non_glob_import_of_type_ir_inherent.rs:21:9
+   |
+LL |     use rustc_type_ir::inherent::ParamEnv as _;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^-------------
+   |                                  |
+   |                                  help: try using a glob import instead: `*`
+
+error: non-glob import of `rustc_type_ir::inherent`
+  --> $DIR/non_glob_import_of_type_ir_inherent.rs:25:9
+   |
+LL |     use rustc_type_ir::inherent;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^- help: try using a glob import instead: `::*`
+
+error: non-glob import of `rustc_type_ir::inherent`
+  --> $DIR/non_glob_import_of_type_ir_inherent.rs:26:9
+   |
+LL |     use rustc_type_ir::inherent as inh;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^------- help: try using a glob import instead: `::*`
+
+error: non-glob import of `rustc_type_ir::inherent`
+  --> $DIR/non_glob_import_of_type_ir_inherent.rs:27:25
+   |
+LL |     use rustc_type_ir::{inherent as _};
+   |                         ^^^^^^^^----- help: try using a glob import instead: `::*`
+
+error: non-glob import of `rustc_type_ir::inherent`
+  --> $DIR/non_glob_import_of_type_ir_inherent.rs:34:35
+   |
+LL |     use rustc_type_ir::inherent::{self};
+   |                                   ^^^^ help: try using a glob import instead: `*`
+
+error: non-glob import of `rustc_type_ir::inherent`
+  --> $DIR/non_glob_import_of_type_ir_inherent.rs:35:35
+   |
+LL |     use rustc_type_ir::inherent::{self as innate};
+   |                                   ^^^^----------
+   |                                   |
+   |                                   help: try using a glob import instead: `*`
+
+error: aborting due to 9 previous errors
+
diff --git a/tests/ui/pub/pub-reexport-priv-extern-crate.stderr b/tests/ui/pub/pub-reexport-priv-extern-crate.stderr
index 915d07fd08a..8ab6e83641d 100644
--- a/tests/ui/pub/pub-reexport-priv-extern-crate.stderr
+++ b/tests/ui/pub/pub-reexport-priv-extern-crate.stderr
@@ -29,7 +29,7 @@ LL | pub use core as reexported_core;
    |         ^^^^^^^^^^^^^^^^^^^^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
+   = note: for more information, see issue #127909 <https://github.com/rust-lang/rust/issues/127909>
    = note: `#[deny(pub_use_of_private_extern_crate)]` on by default
 help: consider making the `extern crate` item publicly accessible
    |
@@ -40,3 +40,18 @@ error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0365, E0603.
 For more information about an error, try `rustc --explain E0365`.
+Future incompatibility report: Future breakage diagnostic:
+error[E0365]: extern crate `core` is private and cannot be re-exported
+  --> $DIR/pub-reexport-priv-extern-crate.rs:2:9
+   |
+LL | pub use core as reexported_core;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #127909 <https://github.com/rust-lang/rust/issues/127909>
+   = note: `#[deny(pub_use_of_private_extern_crate)]` on by default
+help: consider making the `extern crate` item publicly accessible
+   |
+LL | pub extern crate core;
+   | +++
+