Rollup merge of #137194 - kornelski:ftls, r=tgross35
More const {} init in thread_local `const {}` in `thread_local!` gets an optimization just based on the syntax, rather than the expression being const-compatible. This is easy to miss, so I've added more examples to the docs. I've also added `const {}` in a couple of places in std where this optimization has been missed.
This commit is contained in:
commit
2ff53a293e
5 changed files with 25 additions and 7 deletions
|
@ -20,7 +20,7 @@ type LocalStream = Arc<Mutex<Vec<u8>>>;
|
|||
|
||||
thread_local! {
|
||||
/// Used by the test crate to capture the output of the print macros and panics.
|
||||
static OUTPUT_CAPTURE: Cell<Option<LocalStream>> = {
|
||||
static OUTPUT_CAPTURE: Cell<Option<LocalStream>> = const {
|
||||
Cell::new(None)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1382,3 +1382,6 @@ impl<T> fmt::Debug for Receiver<T> {
|
|||
f.pad("Receiver { .. }")
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
|
14
library/std/src/sync/mpmc/tests.rs
Normal file
14
library/std/src/sync/mpmc/tests.rs
Normal file
|
@ -0,0 +1,14 @@
|
|||
// Ensure that thread_local init with `const { 0 }` still has unique address at run-time
|
||||
#[test]
|
||||
fn waker_current_thread_id() {
|
||||
let first = super::waker::current_thread_id();
|
||||
let t = crate::thread::spawn(move || {
|
||||
let second = super::waker::current_thread_id();
|
||||
assert_ne!(first, second);
|
||||
assert_eq!(second, super::waker::current_thread_id());
|
||||
});
|
||||
|
||||
assert_eq!(first, super::waker::current_thread_id());
|
||||
t.join().unwrap();
|
||||
assert_eq!(first, super::waker::current_thread_id());
|
||||
}
|
|
@ -204,6 +204,6 @@ impl Drop for SyncWaker {
|
|||
pub fn current_thread_id() -> usize {
|
||||
// `u8` is not drop so this variable will be available during thread destruction,
|
||||
// whereas `thread::current()` would not be
|
||||
thread_local! { static DUMMY: u8 = 0 }
|
||||
thread_local! { static DUMMY: u8 = const { 0 } }
|
||||
DUMMY.with(|x| (x as *const u8).addr())
|
||||
}
|
||||
|
|
|
@ -50,7 +50,8 @@ use crate::fmt;
|
|||
/// use std::cell::Cell;
|
||||
/// use std::thread;
|
||||
///
|
||||
/// thread_local!(static FOO: Cell<u32> = Cell::new(1));
|
||||
/// // explicit `const {}` block enables more efficient initialization
|
||||
/// thread_local!(static FOO: Cell<u32> = const { Cell::new(1) });
|
||||
///
|
||||
/// assert_eq!(FOO.get(), 1);
|
||||
/// FOO.set(2);
|
||||
|
@ -138,7 +139,7 @@ impl<T: 'static> fmt::Debug for LocalKey<T> {
|
|||
/// use std::cell::{Cell, RefCell};
|
||||
///
|
||||
/// thread_local! {
|
||||
/// pub static FOO: Cell<u32> = Cell::new(1);
|
||||
/// pub static FOO: Cell<u32> = const { Cell::new(1) };
|
||||
///
|
||||
/// static BAR: RefCell<Vec<f32>> = RefCell::new(vec![1.0, 2.0]);
|
||||
/// }
|
||||
|
@ -394,7 +395,7 @@ impl<T: 'static> LocalKey<Cell<T>> {
|
|||
/// use std::cell::Cell;
|
||||
///
|
||||
/// thread_local! {
|
||||
/// static X: Cell<i32> = Cell::new(1);
|
||||
/// static X: Cell<i32> = const { Cell::new(1) };
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(X.get(), 1);
|
||||
|
@ -423,7 +424,7 @@ impl<T: 'static> LocalKey<Cell<T>> {
|
|||
/// use std::cell::Cell;
|
||||
///
|
||||
/// thread_local! {
|
||||
/// static X: Cell<Option<i32>> = Cell::new(Some(1));
|
||||
/// static X: Cell<Option<i32>> = const { Cell::new(Some(1)) };
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(X.take(), Some(1));
|
||||
|
@ -453,7 +454,7 @@ impl<T: 'static> LocalKey<Cell<T>> {
|
|||
/// use std::cell::Cell;
|
||||
///
|
||||
/// thread_local! {
|
||||
/// static X: Cell<i32> = Cell::new(1);
|
||||
/// static X: Cell<i32> = const { Cell::new(1) };
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(X.replace(2), 1);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue