From fc75a4e14607a9b6445fd0c6685fb6999fa69de8 Mon Sep 17 00:00:00 2001 From: Nikolai Vazquez Date: Tue, 3 Oct 2023 14:44:41 -0400 Subject: [PATCH 1/3] Allow any expression blocks in `thread_local!` --- library/std/src/thread/local.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs index 338567777f753..4c5e0e9139458 100644 --- a/library/std/src/thread/local.rs +++ b/library/std/src/thread/local.rs @@ -166,7 +166,10 @@ impl fmt::Debug for LocalKey { /// ``` /// use std::cell::Cell; /// thread_local! { -/// pub static FOO: Cell = const { Cell::new(1) }; +/// pub static FOO: Cell = const { +/// let value = 1; +/// Cell::new(value) +/// }; /// } /// /// assert_eq!(FOO.get(), 1); @@ -186,12 +189,12 @@ macro_rules! thread_local { // empty (base case for the recursion) () => {}; - ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = const { $init:expr }; $($rest:tt)*) => ( + ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = const $init:block; $($rest:tt)*) => ( $crate::thread::local_impl::thread_local_inner!($(#[$attr])* $vis $name, $t, const $init); $crate::thread_local!($($rest)*); ); - ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = const { $init:expr }) => ( + ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = const $init:block) => ( $crate::thread::local_impl::thread_local_inner!($(#[$attr])* $vis $name, $t, const $init); ); From f52b88e91f2d185a8be2bf4243827f7b720cd513 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 20 Jan 2024 18:39:48 -0800 Subject: [PATCH 2/3] Revert example change from PR 116392 --- library/std/src/thread/local.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs index 4c5e0e9139458..2e13f433dcffb 100644 --- a/library/std/src/thread/local.rs +++ b/library/std/src/thread/local.rs @@ -166,10 +166,7 @@ impl fmt::Debug for LocalKey { /// ``` /// use std::cell::Cell; /// thread_local! { -/// pub static FOO: Cell = const { -/// let value = 1; -/// Cell::new(value) -/// }; +/// pub static FOO: Cell = const { Cell::new(1) }; /// } /// /// assert_eq!(FOO.get(), 1); From c43344e839906624a388847906f6a9b27dcd35c4 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 20 Jan 2024 18:48:41 -0800 Subject: [PATCH 3/3] Add test of thread_local containing multiline const block Before making thread_local accept statements inside the const block, this test would fail to compile as follows: error: no rules expected the token `let` --> library/std/tests/thread.rs:26:13 | 26 | let value = 1; | ^^^ no rules expected this token in macro call | note: while trying to match meta-variable `$init:expr` --> library/std/src/thread/local.rs:189:69 | 189 | ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = const { $init:expr }; $($rest:tt)*) => ( | ^^^^^^^^^^ --- library/std/tests/thread.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/library/std/tests/thread.rs b/library/std/tests/thread.rs index 754b264c6ad93..4ce81f2846ea9 100644 --- a/library/std/tests/thread.rs +++ b/library/std/tests/thread.rs @@ -1,3 +1,4 @@ +use std::cell::{Cell, RefCell}; use std::sync::{Arc, Mutex}; use std::thread; use std::time::Duration; @@ -14,3 +15,24 @@ fn sleep() { thread::sleep(Duration::from_millis(100)); assert_eq!(*finished.lock().unwrap(), false); } + +#[test] +fn thread_local_containing_const_statements() { + // This exercises the `const $init:block` cases of the thread_local macro. + // Despite overlapping with expression syntax, the `const { ... }` is not + // parsed as `$init:expr`. + thread_local! { + static CELL: Cell = const { + let value = 1; + Cell::new(value) + }; + + static REFCELL: RefCell = const { + let value = 1; + RefCell::new(value) + }; + } + + assert_eq!(CELL.get(), 1); + assert_eq!(REFCELL.take(), 1); +}