rust-lang/rust · #163386
Rollup of 6 pull requests
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> wherelibrary/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() {}