rust-lang/rust · #163386

Rollup of 6 pull requests

JonathanBrouwer · merged Sep 26, 202618 files · 233 + / 270 −
compiler/rustc_abi/src/lib.rs10 + / 0 −
@@ -2450,12 +2450,22 @@ pub enum AbiFromStrErr {     NoExplicitUnwind, } +/// The layout information for a variant.+///+/// For items with multiple variants ([`Variants::Multiple`]), the layout information of each+/// variant largely matches that of the overall item. So, instead of giving each one a new [`LayoutData`],+/// we use this struct, which stores only the information that differs between the variants.+///+/// See <https://github.com/rust-lang/rust/issues/113988> for more context. // NOTE: This struct is generic over the FieldIdx for rust-analyzer usage. #[derive(PartialEq, Eq, Hash, Clone, Debug)] #[cfg_attr(feature = "nightly", derive(StableHash))] pub struct VariantLayout<FieldIdx: Idx> {+    // FIXME: ideally we'd remove these as variants should not have their own+    // size or backend_repr.     pub size: Size,     pub backend_repr: BackendRepr,+     pub field_offsets: IndexVec<FieldIdx, Size>,     fields_in_memory_order: IndexVec<u32, FieldIdx>,     largest_niche: Option<Niche>,
compiler/rustc_hir_typeck/src/upvar.rs11 + / 49 −
@@ -30,7 +30,7 @@ //! then mean that all later passes would have to check for these figments //! and report an error, and it just seems like more mess in the end.) -use std::iter;+use std::{cmp, iter};  use rustc_abi::FIRST_VARIANT; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};@@ -2608,56 +2608,18 @@ fn determine_capture_info(     capture_info_a: ty::CaptureInfo,     capture_info_b: ty::CaptureInfo, ) -> ty::CaptureInfo {-    // If the capture kind is equivalent then, we don't need to escalate and can compare the-    // expressions.-    let eq_capture_kind = match (capture_info_a.capture_kind, capture_info_b.capture_kind) {-        (ty::UpvarCapture::ByValue, ty::UpvarCapture::ByValue) => true,-        (ty::UpvarCapture::ByUse, ty::UpvarCapture::ByUse) => true,-        (ty::UpvarCapture::ByRef(ref_a), ty::UpvarCapture::ByRef(ref_b)) => ref_a == ref_b,-        (ty::UpvarCapture::ByValue, _)-        | (ty::UpvarCapture::ByUse, _)-        | (ty::UpvarCapture::ByRef(_), _) => false,-    };--    if eq_capture_kind {-        match (capture_info_a.capture_kind_expr_id, capture_info_b.capture_kind_expr_id) {-            (Some(_), _) | (None, None) => capture_info_a,-            (None, Some(_)) => capture_info_b,-        }-    } else {-        // We select the CaptureKind which ranks higher based the following priority order:-        // (ByUse | ByValue) > MutBorrow > UniqueImmBorrow > ImmBorrow-        match (capture_info_a.capture_kind, capture_info_b.capture_kind) {-            (ty::UpvarCapture::ByUse, ty::UpvarCapture::ByValue)-            | (ty::UpvarCapture::ByValue, ty::UpvarCapture::ByUse) => {-                bug!("Same capture can't be ByUse and ByValue at the same time")-            }-            (ty::UpvarCapture::ByValue, ty::UpvarCapture::ByValue)-            | (ty::UpvarCapture::ByUse, ty::UpvarCapture::ByUse)-            | (ty::UpvarCapture::ByValue | ty::UpvarCapture::ByUse, ty::UpvarCapture::ByRef(_)) => {-                capture_info_a-            }-            (ty::UpvarCapture::ByRef(_), ty::UpvarCapture::ByValue | ty::UpvarCapture::ByUse) => {-                capture_info_b-            }-            (ty::UpvarCapture::ByRef(ref_a), ty::UpvarCapture::ByRef(ref_b)) => {-                match (ref_a, ref_b) {-                    // Take LHS:-                    (BorrowKind::UniqueImmutable | BorrowKind::Mutable, BorrowKind::Immutable)-                    | (BorrowKind::Mutable, BorrowKind::UniqueImmutable) => capture_info_a,--                    // Take RHS:-                    (BorrowKind::Immutable, BorrowKind::UniqueImmutable | BorrowKind::Mutable)-                    | (BorrowKind::UniqueImmutable, BorrowKind::Mutable) => capture_info_b,--                    (BorrowKind::Immutable, BorrowKind::Immutable)-                    | (BorrowKind::UniqueImmutable, BorrowKind::UniqueImmutable)-                    | (BorrowKind::Mutable, BorrowKind::Mutable) => {-                        bug!("Expected unequal capture kinds");-                    }-                }+    // We select the CaptureKind which ranks higher based the following priority order:+    // (ByUse | ByValue) > MutBorrow > UniqueImmBorrow > ImmBorrow+    match capture_info_a.capture_kind.partial_cmp(&capture_info_b.capture_kind) {+        Some(cmp::Ordering::Equal) => {+            match (capture_info_a.capture_kind_expr_id, capture_info_b.capture_kind_expr_id) {+                (Some(_), _) | (None, None) => capture_info_a,+                (None, Some(_)) => capture_info_b,             }         }+        Some(cmp::Ordering::Greater) => capture_info_a,+        Some(cmp::Ordering::Less) => capture_info_b,+        None => bug!("Same capture can't be ByUse and ByValue at the same time"),     } } 
compiler/rustc_middle/src/ty/closure.rs37 + / 7 −
@@ -1,3 +1,4 @@+use std::cmp; use std::fmt::Write;  use rustc_data_structures::fx::FxIndexMap;@@ -46,16 +47,32 @@ impl UpvarId { #[derive(Eq, PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, StableHash, Hash)] #[derive(TypeFoldable, TypeVisitable)] pub enum UpvarCapture {+    /// Upvar is captured by reference.+    ByRef(BorrowKind),++    /// Upvar is captured by use. This is true when the closure is labeled `use`.+    ByUse,+     /// Upvar is captured by value. This is always true when the     /// closure is labeled `move`, but can also be true in other cases     /// depending on inference.     ByValue,+} -    /// Upvar is captured by use. This is true when the closure is labeled `use`.-    ByUse,--    /// Upvar is captured by reference.-    ByRef(BorrowKind),+// Used in rustc_hir_typeck::upvar::determine_capture_info+impl PartialOrd for UpvarCapture {+    #[inline]+    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {+        match (self, other) {+            (Self::ByValue, Self::ByValue) | (Self::ByUse, Self::ByUse) => {+                Some(cmp::Ordering::Equal)+            }+            (Self::ByValue | Self::ByUse, Self::ByRef(_)) => Some(cmp::Ordering::Greater),+            (Self::ByRef(_), Self::ByValue | Self::ByUse) => Some(cmp::Ordering::Less),+            (Self::ByRef(left), Self::ByRef(right)) => Some(left.cmp(&right)),+            (Self::ByUse, Self::ByValue) | (Self::ByValue, Self::ByUse) => None,+        }+    } }  /// Given the closure DefId this map provides a map of root variables to minimum@@ -339,8 +356,21 @@ pub fn place_to_string_for_capture<'tcx>(tcx: TyCtxt<'tcx>, place: &HirPlace<'tc     curr_string } -#[derive(Eq, Clone, PartialEq, Debug, TyEncodable, TyDecodable, Copy, StableHash, Hash)]-#[derive(TypeFoldable, TypeVisitable)]+#[derive(+    Clone,+    Copy,+    Debug,+    PartialEq,+    Eq,+    Hash,+    PartialOrd, // Order of variants is load-bearing+    Ord,+    TyEncodable,+    TyDecodable,+    StableHash,+    TypeFoldable,+    TypeVisitable+)] pub enum BorrowKind {     /// Data must be immutable and is aliasable.     Immutable,
library/core/src/option.rs2 + / 2 −
@@ -1202,9 +1202,9 @@ impl<T> Option<T> {     /// Returns the provided default result (if none),     /// or applies a function to the contained value (if any).     ///-    /// Arguments passed to `map_or` are eagerly evaluated; if you are passing+    /// The `default` argument passed to `map_or` is eagerly evaluated; if you are passing     /// the result of a function call, it is recommended to use [`map_or_else`],-    /// which is lazily evaluated.+    /// which lazily evaluates `default`.     ///     /// [`map_or_else`]: Option::map_or_else     ///
library/core/src/result.rs2 + / 2 −
@@ -842,9 +842,9 @@ impl<T, E> Result<T, E> {     /// Returns the provided default (if [`Err`]), or     /// applies a function to the contained value (if [`Ok`]).     ///-    /// Arguments passed to `map_or` are eagerly evaluated; if you are passing+    /// The `default` argument passed to `map_or` is eagerly evaluated; if you are passing     /// the result of a function call, it is recommended to use [`map_or_else`],-    /// which is lazily evaluated.+    /// which lazily evaluates `default`.     ///     /// [`map_or_else`]: Result::map_or_else     ///
library/core/src/sync/mod.rs1 + / 1 −
@@ -4,5 +4,5 @@  pub mod atomic; mod sync_view;-#[unstable(feature = "exclusive_wrapper", issue = "98407")]+#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] pub use sync_view::SyncView;
library/core/src/sync/sync_view.rs35 + / 36 −
@@ -47,8 +47,6 @@ use core::task::{Context, Poll}; /// functionality: /// /// ```ignore-wasm-/// #![feature(exclusive_wrapper)]-/// /// use std::sync::SyncView; /// use std::sync::mpsc::{self, Receiver}; /// use std::thread;@@ -91,7 +89,7 @@ use core::task::{Context, Poll}; /// for any value. This is a parallel with the fact that /// `&` and `&mut` references together can be thought of as a _compile-time_ /// version of a read-write lock.-#[unstable(feature = "exclusive_wrapper", issue = "98407")]+#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] #[doc(alias = "SyncWrapper")] #[doc(alias = "SyncCell")] #[doc(alias = "Unique")]@@ -105,10 +103,10 @@ pub struct SyncView<T: ?Sized> { }  // See `SyncView`'s docs for justification.-#[unstable(feature = "exclusive_wrapper", issue = "98407")]+#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] unsafe impl<T: ?Sized> Sync for SyncView<T> {} -#[unstable(feature = "exclusive_wrapper", issue = "98407")]+#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_default", issue = "143894")] const impl<T> Default for SyncView<T> where@@ -120,7 +118,7 @@ where     } } -#[unstable(feature = "exclusive_wrapper", issue = "98407")]+#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] impl<T: ?Sized> fmt::Debug for SyncView<T> {     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {         f.debug_struct("SyncView").finish_non_exhaustive()@@ -129,17 +127,18 @@ impl<T: ?Sized> fmt::Debug for SyncView<T> {  impl<T: Sized> SyncView<T> {     /// Wrap a value in an `SyncView`-    #[unstable(feature = "exclusive_wrapper", issue = "98407")]-    #[rustc_const_unstable(feature = "exclusive_wrapper", issue = "98407")]+    #[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")]+    #[rustc_const_stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")]     #[must_use]     #[inline]     pub const fn new(t: T) -> Self {         Self { inner: t }     }      /// Unwrap the value contained in the `SyncView`-    #[unstable(feature = "exclusive_wrapper", issue = "98407")]-    #[rustc_const_unstable(feature = "exclusive_wrapper", issue = "98407")]+    #[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")]+    #[rustc_const_stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")]+    #[rustc_allow_const_fn_unstable(const_precise_live_drops)]     #[must_use]     #[inline]     pub const fn into_inner(self) -> T {@@ -154,8 +153,8 @@ impl<T: ?Sized> SyncView<T> {     /// value, which means _unpinned_ `SyncView`s can produce _unpinned_     /// access to the underlying value, but _pinned_ `SyncView`s only     /// produce _pinned_ access to the underlying value.-    #[unstable(feature = "exclusive_wrapper", issue = "98407")]-    #[rustc_const_unstable(feature = "exclusive_wrapper", issue = "98407")]+    #[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")]+    #[rustc_const_stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")]     #[must_use]     #[inline]     pub const fn as_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T> {@@ -167,8 +166,8 @@ impl<T: ?Sized> SyncView<T> {     /// Build a _mutable_ reference to an `SyncView<T>` from     /// a _mutable_ reference to a `T`. This allows you to skip     /// building an `SyncView` with [`SyncView::new`].-    #[unstable(feature = "exclusive_wrapper", issue = "98407")]-    #[rustc_const_unstable(feature = "exclusive_wrapper", issue = "98407")]+    #[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")]+    #[rustc_const_stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")]     #[must_use]     #[inline]     pub const fn from_mut(r: &'_ mut T) -> &'_ mut SyncView<T> {@@ -179,8 +178,8 @@ impl<T: ?Sized> SyncView<T> {     /// Build a _pinned mutable_ reference to an `SyncView<T>` from     /// a _pinned mutable_ reference to a `T`. This allows you to skip     /// building an `SyncView` with [`SyncView::new`].-    #[unstable(feature = "exclusive_wrapper", issue = "98407")]-    #[rustc_const_unstable(feature = "exclusive_wrapper", issue = "98407")]+    #[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")]+    #[rustc_const_stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")]     #[must_use]     #[inline]     pub const fn from_pin_mut(r: Pin<&'_ mut T>) -> Pin<&'_ mut SyncView<T>> {@@ -197,8 +196,8 @@ impl<T: ?Sized + Sync> SyncView<T> {     /// value, which means _unpinned_ `SyncView`s can produce _unpinned_     /// access to the underlying value, but _pinned_ `SyncView`s only     /// produce _pinned_ access to the underlying value.-    #[unstable(feature = "exclusive_wrapper", issue = "98407")]-    #[rustc_const_unstable(feature = "exclusive_wrapper", issue = "98407")]+    #[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")]+    #[rustc_const_stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")]     #[must_use]     #[inline]     pub const fn as_pin_ref(self: Pin<&Self>) -> Pin<&T> {@@ -208,7 +207,7 @@ impl<T: ?Sized + Sync> SyncView<T> {     } } -#[unstable(feature = "exclusive_wrapper", issue = "98407")]+#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_convert", issue = "143773")] const impl<T> From<T> for SyncView<T> {     #[inline]@@ -217,7 +216,7 @@ const impl<T> From<T> for SyncView<T> {     } } -#[unstable(feature = "exclusive_wrapper", issue = "98407")]+#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_trait_impl", issue = "143874")] const impl<F, Args> FnOnce<Args> for SyncView<F> where@@ -231,7 +230,7 @@ where     } } -#[unstable(feature = "exclusive_wrapper", issue = "98407")]+#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_trait_impl", issue = "143874")] const impl<F, Args> FnMut<Args> for SyncView<F> where@@ -243,7 +242,7 @@ where     } } -#[unstable(feature = "exclusive_wrapper", issue = "98407")]+#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_trait_impl", issue = "143874")] const impl<F, Args> Fn<Args> for SyncView<F> where@@ -255,7 +254,7 @@ where     } } -#[unstable(feature = "exclusive_wrapper", issue = "98407")]+#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] impl<F, Args> AsyncFnOnce<Args> for SyncView<F> where     F: AsyncFnOnce<Args>,@@ -270,7 +269,7 @@ where     } } -#[unstable(feature = "exclusive_wrapper", issue = "98407")]+#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] impl<F, Args> AsyncFnMut<Args> for SyncView<F> where     F: AsyncFnMut<Args>,@@ -286,7 +285,7 @@ where     } } -#[unstable(feature = "exclusive_wrapper", issue = "98407")]+#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] impl<F, Args> AsyncFn<Args> for SyncView<F> where     F: Sync + AsyncFn<Args>,@@ -297,7 +296,7 @@ where     } } -#[unstable(feature = "exclusive_wrapper", issue = "98407")]+#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] impl<T> Future for SyncView<T> where     T: Future + ?Sized,@@ -324,7 +323,7 @@ where     } } -#[unstable(feature = "exclusive_wrapper", issue = "98407")]+#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_convert", issue = "143773")] const impl<T> AsRef<T> for SyncView<T> where@@ -337,7 +336,7 @@ where     } } -#[unstable(feature = "exclusive_wrapper", issue = "98407")]+#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_convert", issue = "143773")] const impl<T> AsMut<T> for SyncView<T> where@@ -350,7 +349,7 @@ where     } } -#[unstable(feature = "exclusive_wrapper", issue = "98407")]+#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_clone", issue = "142757")] const impl<T> Clone for SyncView<T> where@@ -367,10 +366,10 @@ where #[rustc_const_unstable(feature = "const_clone", issue = "142757")] const unsafe impl<T> TrivialClone for SyncView<T> where T: Sync + [const] TrivialClone {} -#[unstable(feature = "exclusive_wrapper", issue = "98407")]+#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] impl<T> Copy for SyncView<T> where T: Sync + Copy {} -#[unstable(feature = "exclusive_wrapper", issue = "98407")]+#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] const impl<T, U> PartialEq<SyncView<U>> for SyncView<T> where@@ -383,14 +382,14 @@ where     } } -#[unstable(feature = "exclusive_wrapper", issue = "98407")]+#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] impl<T> StructuralPartialEq for SyncView<T> where T: Sync + StructuralPartialEq + ?Sized {} -#[unstable(feature = "exclusive_wrapper", issue = "98407")]+#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] const impl<T> Eq for SyncView<T> where T: Sync + [const] Eq + ?Sized {} -#[unstable(feature = "exclusive_wrapper", issue = "98407")]+#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] impl<T> Hash for SyncView<T> where     T: Sync + Hash + ?Sized,@@ -401,7 +400,7 @@ where     } } -#[unstable(feature = "exclusive_wrapper", issue = "98407")]+#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] const impl<T, U> PartialOrd<SyncView<U>> for SyncView<T> where@@ -414,7 +413,7 @@ where     } } -#[unstable(feature = "exclusive_wrapper", issue = "98407")]+#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] const impl<T> Ord for SyncView<T> where
library/std/src/env.rs7 + / 0 −
@@ -717,6 +717,11 @@ pub fn temp_dir() -> PathBuf { /// If the executable is renamed while it is running, platforms may return the /// path at the time it was loaded instead of the new path. ///+/// On Linux, if the executable is deleted while it is running, this function+/// may return the path with the string `" (deleted)"` appended.+///+/// Note that the platform-specific behavior [may change in the future][changes].+/// /// # Errors /// /// Acquiring the path of the current executable is a platform-specific operation@@ -752,6 +757,8 @@ pub fn temp_dir() -> PathBuf { ///     Err(e) => println!("failed to get current exe path: {e}"), /// }; /// ```+///+/// [changes]: crate::io#platform-specific-behavior #[stable(feature = "env", since = "1.0.0")] pub fn current_exe() -> io::Result<PathBuf> {     paths_imp::current_exe()
library/std/src/lib.rs0 + / 1 −
@@ -341,7 +341,6 @@ #![feature(error_generic_member_access)] #![feature(error_iter)] #![feature(exact_size_is_empty)]-#![feature(exclusive_wrapper)] #![feature(extend_one)] #![feature(float_gamma)] #![feature(float_minimum_maximum)]
library/std/src/sync/mod.rs1 + / 1 −
@@ -179,7 +179,7 @@ #![cfg_attr(rustfmt, rustfmt::skip)]  // These come from `core` & `alloc` and only in one flavor: no poisoning.-#[unstable(feature = "exclusive_wrapper", issue = "98407")]+#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] pub use core::sync::SyncView; #[stable(feature = "rust1", since = "1.0.0")] pub use core::sync::atomic;
library/std/src/sys/thread_local/native/mod.rs7 + / 3 −
@@ -81,8 +81,12 @@ pub macro thread_local_inner {      // used to generate the `LocalKey` value for `thread_local!`     (@key $t:ty, $(#[$align_attr:meta])*, $init:expr) => {{+        // We intentionally have an argument-position `'static` lifetime so that elided lifetimes in `$t`+        // become `'static` like they do for `const`s and `static`s, including in the other two+        // `thread_local!` implementations.+        #[allow(mismatched_lifetime_syntaxes)]         #[inline]-        fn __rust_std_internal_init_fn() -> $t {+        fn __rust_std_internal_init_fn(_lifetime_elision: $crate::marker::PhantomData<&'static ()>) -> $t {             $init         } @@ -94,15 +98,15 @@ pub macro thread_local_inner {                         $(#[$align_attr])*                         static __RUST_STD_INTERNAL_VAL: $crate::thread::local_impl::LazyStorage<$t, ()>                             = $crate::thread::local_impl::LazyStorage::new();-                        __RUST_STD_INTERNAL_VAL.get_or_init(__rust_std_internal_init, __rust_std_internal_init_fn)+                        __RUST_STD_INTERNAL_VAL.get_or_init(__rust_std_internal_init, || __rust_std_internal_init_fn($crate::marker::PhantomData))                     }                 } else {                     |__rust_std_internal_init| {                         #[thread_local]                         $(#[$align_attr])*                         static __RUST_STD_INTERNAL_VAL: $crate::thread::local_impl::LazyStorage<$t, !>                             = $crate::thread::local_impl::LazyStorage::new();-                        __RUST_STD_INTERNAL_VAL.get_or_init(__rust_std_internal_init, __rust_std_internal_init_fn)+                        __RUST_STD_INTERNAL_VAL.get_or_init(__rust_std_internal_init, || __rust_std_internal_init_fn($crate::marker::PhantomData))                     }                 }             })
library/std/src/sys/thread_local/no_threads.rs6 + / 2 −
@@ -31,14 +31,18 @@ pub macro thread_local_inner {      // used to generate the `LocalKey` value for `thread_local!`     (@key $t:ty, $(#[$align_attr:meta])*, $init:expr) => {{+        // We intentionally have an argument-position `'static` lifetime so that elided lifetimes in `$t`+        // become `'static` like they do for `const`s and `static`s, including in the other two+        // `thread_local!` implementations.+        #[allow(mismatched_lifetime_syntaxes)]         #[inline]-        fn __rust_std_internal_init_fn() -> $t { $init }+        fn __rust_std_internal_init_fn(_lifetime_elision: $crate::marker::PhantomData<&'static ()>) -> $t { $init }          unsafe {             $crate::thread::LocalKey::new(|__rust_std_internal_init| {                 $(#[$align_attr])*                 static __RUST_STD_INTERNAL_VAL: $crate::thread::local_impl::LazyStorage<$t> = $crate::thread::local_impl::LazyStorage::new();-                __RUST_STD_INTERNAL_VAL.get(__rust_std_internal_init, __rust_std_internal_init_fn)+                __RUST_STD_INTERNAL_VAL.get(__rust_std_internal_init, || __rust_std_internal_init_fn($crate::marker::PhantomData))             })         }     }},
library/std/src/sys/thread_local/os.rs6 + / 2 −
@@ -20,8 +20,12 @@ pub macro thread_local_inner {      // used to generate the `LocalKey` value for `thread_local!`.     (@key $t:ty, $($(#[$($align_attr:tt)*])+)?, $init:expr) => {{+        // We intentionally have an argument-position `'static` lifetime so that elided lifetimes in `$t`+        // become `'static` like they do for `const`s and `static`s, including in the other two+        // `thread_local!` implementations.+        #[allow(mismatched_lifetime_syntaxes)]         #[inline]-        fn __rust_std_internal_init_fn() -> $t { $init }+        fn __rust_std_internal_init_fn(_lifetime_elision: $crate::marker::PhantomData<&'static ()>) -> $t { $init }          // NOTE: this cannot import `LocalKey` or `Storage` with a `use` because that can shadow         // user provided type or type alias with a matching name. Please update the shadowing test@@ -43,7 +47,7 @@ pub macro thread_local_inner {                     final_align                 }>                     = $crate::thread::local_impl::Storage::new();-                __RUST_STD_INTERNAL_VAL.get(__rust_std_internal_init, __rust_std_internal_init_fn)+                __RUST_STD_INTERNAL_VAL.get(__rust_std_internal_init, || __rust_std_internal_init_fn($crate::marker::PhantomData))             })         }     }},
library/std/tests/sync_view.rsadded93 + / 0 −
@@ -0,0 +1,93 @@+use core::sync::SyncView;+use std::cell::Cell;+use std::future::Future;+use std::marker::PhantomPinned;+use std::pin::{Pin, pin};+use std::task::{Context, Poll, Waker};++const EMPTY: Vec<u8> = SyncView::new(Vec::new()).into_inner();+const PROJECTED: u32 = {+    let mut value = 41;+    let view = SyncView::from_mut(&mut value);+    *Pin::into_inner(Pin::new(view).as_pin_mut()) += 1;+    let view = SyncView::from_pin_mut(Pin::new(&mut value)).get_mut();+    *Pin::new(&*view).as_pin_ref().get_ref()+};++fn require_sync<T: Sync + ?Sized>(_: &T) {}++fn call_mut(mut f: impl FnMut() -> u32) -> u32 {+    f()+}++fn call_shared(f: &impl Fn() -> u32) -> u32 {+    f()+}++fn complete(future: impl Future<Output = u32>) -> u32 {+    let mut context = Context::from_waker(Waker::noop());+    match pin!(future).poll(&mut context) {+        Poll::Ready(value) => value,+        Poll::Pending => panic!("expected an immediately ready future"),+    }+}++async fn call_async_once(f: impl AsyncFnOnce() -> u32) -> u32 {+    f().await+}++struct Pinned {+    value: Cell<u32>,+    _pin: PhantomPinned,+}++#[test]+fn sync_view_const() {+    assert!(EMPTY.is_empty());+    assert_eq!(PROJECTED, 42);+}++#[test]+fn sync_view_access() {+    let mut value = std::sync::SyncView::new(Cell::new(1));+    require_sync(&value);+    value.as_mut().set(2);+    assert_eq!(value.into_inner().get(), 2);++    let mut values = [1, 2];+    let view = SyncView::from_mut(&mut values[..]);+    view.as_mut()[0] = 3;+    assert_eq!(view.as_ref(), &[3, 2]);+}++#[test]+fn sync_view_pinned_projection() {+    let mut pinned = pin!(Pinned { value: Cell::new(4), _pin: PhantomPinned });+    let address = std::ptr::from_ref(pinned.as_ref().get_ref());+    let view = SyncView::from_pin_mut(pinned.as_mut());+    require_sync(view.as_ref().get_ref());+    let inner = view.as_pin_mut();+    assert_eq!(std::ptr::from_ref(inner.as_ref().get_ref()), address);+    inner.value.set(5);+    assert_eq!(pinned.value.get(), 5);+}++#[test]+fn sync_view_forwarding() {+    let counter = Cell::new(0);+    let increment = SyncView::new(|| {+        counter.set(counter.get() + 1);+        counter.get()+    });+    require_sync(&increment);+    assert_eq!(call_mut(increment), 1);+    assert_eq!(call_shared(&SyncView::new(|| 7)), 7);++    let future = SyncView::new(async {+        std::future::ready(()).await;+        counter.get()+    });+    require_sync(&future);+    assert_eq!(complete(future), 1);+    assert_eq!(complete(call_async_once(SyncView::new(async || counter.get()))), 1);+}
tests/ui/explicit-tail-calls/callee_is_weird.rs1 + / 1 −
@@ -1,4 +1,4 @@-#![feature(explicit_tail_calls, exclusive_wrapper, fn_traits, unboxed_closures)]+#![feature(explicit_tail_calls, fn_traits, unboxed_closures)] #![expect(incomplete_features)]  fn f() {}
tests/ui/suggestions/missing-lifetime-specifier.rsremoved0 + / 54 −
@@ -1,54 +0,0 @@-// The specific errors produced depend the thread-local implementation.-// Run only on platforms with "fast" TLS.-//@ ignore-wasm globals are used instead of thread locals-//@ ignore-emscripten globals are used instead of thread locals-//@ ignore-android does not use #[thread_local]-//@ ignore-nto does not use #[thread_local]-//@ ignore-qnx does not use #[thread_local]-// Different number of duplicated diagnostics on different targets-//@ compile-flags: -Zdeduplicate-diagnostics=yes--use std::cell::RefCell;-use std::collections::HashMap;--pub union Foo<'t, 'k> {-    i: &'t i64,-    f: &'k f64,-}-trait Bar<'t, 'k> {}--pub union Qux<'t, 'k, I> {-    i: &'t I,-    f: &'k I,-}-trait Tar<'t, 'k, I> {}--thread_local! {-    static a: RefCell<HashMap<i32, Vec<Vec<Foo>>>> = RefCell::new(HashMap::new());-    //~^ ERROR missing lifetime specifiers-}-thread_local! {-    static b: RefCell<HashMap<i32, Vec<Vec<&dyn Bar>>>> = RefCell::new(HashMap::new());-    //~^ ERROR missing lifetime specifiers-}-thread_local! {-    static c: RefCell<HashMap<i32, Vec<Vec<Qux<i32>>>>> = RefCell::new(HashMap::new());-    //~^ ERROR missing lifetime specifiers-}-thread_local! {-    static d: RefCell<HashMap<i32, Vec<Vec<&dyn Tar<i32>>>>> = RefCell::new(HashMap::new());-    //~^ ERROR missing lifetime specifiers-}--thread_local! {-    static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, i32>>>>> = RefCell::new(HashMap::new());-    //~^ ERROR union takes 2 lifetime arguments but 1 lifetime argument-}-thread_local! {-    static f: RefCell<HashMap<i32, Vec<Vec<&dyn Tar<'static, i32>>>>> =-        RefCell::new(HashMap::new());-    //~^^ ERROR trait takes 2 lifetime arguments but 1 lifetime argument was supplied-    //~| ERROR missing lifetime specifier-}--fn main() {}
tests/ui/suggestions/missing-lifetime-specifier.stderrremoved0 + / 109 −
@@ -1,109 +0,0 @@-error[E0106]: missing lifetime specifiers-  --> $DIR/missing-lifetime-specifier.rs:27:44-   |-LL |     static a: RefCell<HashMap<i32, Vec<Vec<Foo>>>> = RefCell::new(HashMap::new());-   |                                            ^^^ expected 2 lifetime parameters-   |-   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from-help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`, or if you will only have owned values-   |-LL |     static a: RefCell<HashMap<i32, Vec<Vec<Foo<'static, 'static>>>>> = RefCell::new(HashMap::new());-   |                                               ++++++++++++++++++--error[E0106]: missing lifetime specifiers-  --> $DIR/missing-lifetime-specifier.rs:31:44-   |-LL |     static b: RefCell<HashMap<i32, Vec<Vec<&dyn Bar>>>> = RefCell::new(HashMap::new());-   |                                            ^    ^^^ expected 2 lifetime parameters-   |                                            |-   |                                            expected named lifetime parameter-   |-   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from-help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`-   |-LL |     static b: RefCell<HashMap<i32, Vec<Vec<&'static dyn Bar<'static, 'static>>>>> = RefCell::new(HashMap::new());-   |                                             +++++++        ++++++++++++++++++--error[E0106]: missing lifetime specifiers-  --> $DIR/missing-lifetime-specifier.rs:35:47-   |-LL |     static c: RefCell<HashMap<i32, Vec<Vec<Qux<i32>>>>> = RefCell::new(HashMap::new());-   |                                               ^ expected 2 lifetime parameters-   |-   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from-help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`, or if you will only have owned values-   |-LL |     static c: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());-   |                                                +++++++++++++++++--error[E0106]: missing lifetime specifiers-  --> $DIR/missing-lifetime-specifier.rs:39:44-   |-LL |     static d: RefCell<HashMap<i32, Vec<Vec<&dyn Tar<i32>>>>> = RefCell::new(HashMap::new());-   |                                            ^       ^ expected 2 lifetime parameters-   |                                            |-   |                                            expected named lifetime parameter-   |-   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from-help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`-   |-LL |     static d: RefCell<HashMap<i32, Vec<Vec<&'static dyn Tar<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());-   |                                             +++++++         +++++++++++++++++--error[E0106]: missing lifetime specifier-  --> $DIR/missing-lifetime-specifier.rs:48:44-   |-LL |     static f: RefCell<HashMap<i32, Vec<Vec<&dyn Tar<'static, i32>>>>> =-   |                                            ^ expected named lifetime parameter-   |-   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from-help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`-   |-LL |     static f: RefCell<HashMap<i32, Vec<Vec<&'static dyn Tar<'static, i32>>>>> =-   |                                             +++++++-help: instead, you are more likely to want to return an owned value-   |-LL -     static f: RefCell<HashMap<i32, Vec<Vec<&dyn Tar<'static, i32>>>>> =-LL +     static f: RefCell<HashMap<i32, Vec<Vec<dyn Tar<'static, i32>>>>> =-   |--error[E0107]: union takes 2 lifetime arguments but 1 lifetime argument was supplied-  --> $DIR/missing-lifetime-specifier.rs:44:44-   |-LL |     static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, i32>>>>> = RefCell::new(HashMap::new());-   |                                            ^^^ ------- supplied 1 lifetime argument-   |                                            |-   |                                            expected 2 lifetime arguments-   |-note: union defined here, with 2 lifetime parameters: `'t`, `'k`-  --> $DIR/missing-lifetime-specifier.rs:20:11-   |-LL | pub union Qux<'t, 'k, I> {-   |           ^^^ --  ---help: add missing lifetime argument-   |-LL |     static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());-   |                                                       +++++++++--error[E0107]: trait takes 2 lifetime arguments but 1 lifetime argument was supplied-  --> $DIR/missing-lifetime-specifier.rs:48:49-   |-LL |     static f: RefCell<HashMap<i32, Vec<Vec<&dyn Tar<'static, i32>>>>> =-   |                                                 ^^^ ------- supplied 1 lifetime argument-   |                                                 |-   |                                                 expected 2 lifetime arguments-   |-note: trait defined here, with 2 lifetime parameters: `'t`, `'k`-  --> $DIR/missing-lifetime-specifier.rs:24:7-   |-LL | trait Tar<'t, 'k, I> {}-   |       ^^^ --  ---help: add missing lifetime argument-   |-LL |     static f: RefCell<HashMap<i32, Vec<Vec<&dyn Tar<'static, 'static, i32>>>>> =-   |                                                            +++++++++--error: aborting due to 7 previous errors--Some errors have detailed explanations: E0106, E0107.-For more information about an error, try `rustc --explain E0106`.
tests/ui/thread-local/lifetime-elision.rsadded14 + / 0 −
@@ -0,0 +1,14 @@+// Test that  `thread_local!` defaults elided lifetimes in the type to `'static`.+// Regression test for 159358.+// Ideally this should be tested at least one target using each `thread_local!`+// implementation (no-threads, native, os), but currently there are no Tier 1 `no-threads`+// targets. `x86_64-unknown-linux-gnu` is a `native` target and `x86_64-pc-windows-gnu`+// is a `os` target, so those are covered (as of 2026-07-21).+//@ check-pass++// Const initializer+std::thread_local!(static A: &str = const { "" });+// Non-const initializer+std::thread_local!(static B: &str = "");++fn main() {}