diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs index 6b54ec8afca9c..152b9771086b8 100644 --- a/src/libstd/thread/local.rs +++ b/src/libstd/thread/local.rs @@ -100,18 +100,52 @@ pub struct LocalKey { /// Declare a new thread local storage key of type `std::thread::LocalKey`. /// +/// # Syntax +/// +/// The macro wraps any number of static declarations and makes them thread local. +/// Each static may be public or private, and attributes are allowed. Example: +/// +/// ``` +/// use std::cell::RefCell; +/// thread_local! { +/// pub static FOO: RefCell = RefCell::new(1); +/// +/// #[allow(unused)] +/// static BAR: RefCell = RefCell::new(1.0); +/// } +/// # fn main() {} +/// ``` +/// /// See [LocalKey documentation](thread/struct.LocalKey.html) for more /// information. #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] #[allow_internal_unstable] macro_rules! thread_local { - (static $name:ident: $t:ty = $init:expr) => ( - static $name: $crate::thread::LocalKey<$t> = + // rule 0: empty (base case for the recursion) + () => {}; + + // rule 1: process multiple declarations where the first one is private + ($(#[$attr:meta])* static $name:ident: $t:ty = $init:expr; $($rest:tt)*) => ( + thread_local!($(#[$attr])* static $name: $t = $init); // go to rule 2 + thread_local!($($rest)*); + ); + + // rule 2: handle a single private declaration + ($(#[$attr:meta])* static $name:ident: $t:ty = $init:expr) => ( + $(#[$attr])* static $name: $crate::thread::LocalKey<$t> = __thread_local_inner!($t, $init); ); - (pub static $name:ident: $t:ty = $init:expr) => ( - pub static $name: $crate::thread::LocalKey<$t> = + + // rule 3: handle multiple declarations where the first one is public + ($(#[$attr:meta])* pub static $name:ident: $t:ty = $init:expr; $($rest:tt)*) => ( + thread_local!($(#[$attr])* pub static $name: $t = $init); // go to rule 4 + thread_local!($($rest)*); + ); + + // rule 4: handle a single public declaration + ($(#[$attr:meta])* pub static $name:ident: $t:ty = $init:expr) => ( + $(#[$attr])* pub static $name: $crate::thread::LocalKey<$t> = __thread_local_inner!($t, $init); ); } diff --git a/src/test/run-pass/thread-local-syntax.rs b/src/test/run-pass/thread-local-syntax.rs new file mode 100644 index 0000000000000..a5967249b5454 --- /dev/null +++ b/src/test/run-pass/thread-local-syntax.rs @@ -0,0 +1,23 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![deny(missing_docs)] +//! this tests the syntax of `thread_local!` + +thread_local! { + // no docs + #[allow(unused)] + static FOO: i32 = 42; + /// docs + pub static BAR: String = String::from("bar"); +} +thread_local!(static BAZ: u32 = 0); + +fn main() {}