1 #![allow(clippy::needless_doctest_main)]
2 #![warn(
3     missing_debug_implementations,
4     missing_docs,
5     rust_2018_idioms,
6     unreachable_pub
7 )]
8 #![cfg_attr(docsrs, deny(rustdoc::broken_intra_doc_links))]
9 #![doc(test(
10     no_crate_inject,
11     attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_variables))
12 ))]
13 
14 //! Macros for use with Tokio
15 
16 // This `extern` is required for older `rustc` versions but newer `rustc`
17 // versions warn about the unused `extern crate`.
18 #[allow(unused_extern_crates)]
19 extern crate proc_macro;
20 
21 mod entry;
22 mod select;
23 
24 use proc_macro::TokenStream;
25 
26 /// Marks async function to be executed by the selected runtime. This macro
27 /// helps set up a `Runtime` without requiring the user to use
28 /// [Runtime](../tokio/runtime/struct.Runtime.html) or
29 /// [Builder](../tokio/runtime/struct.Builder.html) directly.
30 ///
31 /// Note: This macro is designed to be simplistic and targets applications that
32 /// do not require a complex setup. If the provided functionality is not
33 /// sufficient, you may be interested in using
34 /// [Builder](../tokio/runtime/struct.Builder.html), which provides a more
35 /// powerful interface.
36 ///
37 /// Note: This macro can be used on any function and not just the `main`
38 /// function. Using it on a non-main function makes the function behave as if it
39 /// was synchronous by starting a new runtime each time it is called. If the
40 /// function is called often, it is preferable to create the runtime using the
41 /// runtime builder so the runtime can be reused across calls.
42 ///
43 /// # Multi-threaded runtime
44 ///
45 /// To use the multi-threaded runtime, the macro can be configured using
46 ///
47 /// ```
48 /// #[tokio::main(flavor = "multi_thread", worker_threads = 10)]
49 /// # async fn main() {}
50 /// ```
51 ///
52 /// The `worker_threads` option configures the number of worker threads, and
53 /// defaults to the number of cpus on the system. This is the default flavor.
54 ///
55 /// Note: The multi-threaded runtime requires the `rt-multi-thread` feature
56 /// flag.
57 ///
58 /// # Current thread runtime
59 ///
60 /// To use the single-threaded runtime known as the `current_thread` runtime,
61 /// the macro can be configured using
62 ///
63 /// ```
64 /// #[tokio::main(flavor = "current_thread")]
65 /// # async fn main() {}
66 /// ```
67 ///
68 /// ## Function arguments:
69 ///
70 /// Arguments are allowed for any functions aside from `main` which is special
71 ///
72 /// ## Usage
73 ///
74 /// ### Using the multi-thread runtime
75 ///
76 /// ```rust
77 /// #[tokio::main]
78 /// async fn main() {
79 ///     println!("Hello world");
80 /// }
81 /// ```
82 ///
83 /// Equivalent code not using `#[tokio::main]`
84 ///
85 /// ```rust
86 /// fn main() {
87 ///     tokio::runtime::Builder::new_multi_thread()
88 ///         .enable_all()
89 ///         .build()
90 ///         .unwrap()
91 ///         .block_on(async {
92 ///             println!("Hello world");
93 ///         })
94 /// }
95 /// ```
96 ///
97 /// ### Using current thread runtime
98 ///
99 /// The basic scheduler is single-threaded.
100 ///
101 /// ```rust
102 /// #[tokio::main(flavor = "current_thread")]
103 /// async fn main() {
104 ///     println!("Hello world");
105 /// }
106 /// ```
107 ///
108 /// Equivalent code not using `#[tokio::main]`
109 ///
110 /// ```rust
111 /// fn main() {
112 ///     tokio::runtime::Builder::new_current_thread()
113 ///         .enable_all()
114 ///         .build()
115 ///         .unwrap()
116 ///         .block_on(async {
117 ///             println!("Hello world");
118 ///         })
119 /// }
120 /// ```
121 ///
122 /// ### Set number of worker threads
123 ///
124 /// ```rust
125 /// #[tokio::main(worker_threads = 2)]
126 /// async fn main() {
127 ///     println!("Hello world");
128 /// }
129 /// ```
130 ///
131 /// Equivalent code not using `#[tokio::main]`
132 ///
133 /// ```rust
134 /// fn main() {
135 ///     tokio::runtime::Builder::new_multi_thread()
136 ///         .worker_threads(2)
137 ///         .enable_all()
138 ///         .build()
139 ///         .unwrap()
140 ///         .block_on(async {
141 ///             println!("Hello world");
142 ///         })
143 /// }
144 /// ```
145 ///
146 /// ### Configure the runtime to start with time paused
147 ///
148 /// ```rust
149 /// #[tokio::main(flavor = "current_thread", start_paused = true)]
150 /// async fn main() {
151 ///     println!("Hello world");
152 /// }
153 /// ```
154 ///
155 /// Equivalent code not using `#[tokio::main]`
156 ///
157 /// ```rust
158 /// fn main() {
159 ///     tokio::runtime::Builder::new_current_thread()
160 ///         .enable_all()
161 ///         .start_paused(true)
162 ///         .build()
163 ///         .unwrap()
164 ///         .block_on(async {
165 ///             println!("Hello world");
166 ///         })
167 /// }
168 /// ```
169 ///
170 /// Note that `start_paused` requires the `test-util` feature to be enabled.
171 ///
172 /// ### NOTE:
173 ///
174 /// If you rename the Tokio crate in your dependencies this macro will not work.
175 /// If you must rename the current version of Tokio because you're also using an
176 /// older version of Tokio, you _must_ make the current version of Tokio
177 /// available as `tokio` in the module where this macro is expanded.
178 #[proc_macro_attribute]
179 #[cfg(not(test))] // Work around for rust-lang/rust#62127
main(args: TokenStream, item: TokenStream) -> TokenStream180 pub fn main(args: TokenStream, item: TokenStream) -> TokenStream {
181     entry::main(args, item, true)
182 }
183 
184 /// Marks async function to be executed by selected runtime. This macro helps set up a `Runtime`
185 /// without requiring the user to use [Runtime](../tokio/runtime/struct.Runtime.html) or
186 /// [Builder](../tokio/runtime/struct.builder.html) directly.
187 ///
188 /// ## Function arguments:
189 ///
190 /// Arguments are allowed for any functions aside from `main` which is special
191 ///
192 /// ## Usage
193 ///
194 /// ### Using default
195 ///
196 /// ```rust
197 /// #[tokio::main(flavor = "current_thread")]
198 /// async fn main() {
199 ///     println!("Hello world");
200 /// }
201 /// ```
202 ///
203 /// Equivalent code not using `#[tokio::main]`
204 ///
205 /// ```rust
206 /// fn main() {
207 ///     tokio::runtime::Builder::new_current_thread()
208 ///         .enable_all()
209 ///         .build()
210 ///         .unwrap()
211 ///         .block_on(async {
212 ///             println!("Hello world");
213 ///         })
214 /// }
215 /// ```
216 ///
217 /// ### NOTE:
218 ///
219 /// If you rename the Tokio crate in your dependencies this macro will not work.
220 /// If you must rename the current version of Tokio because you're also using an
221 /// older version of Tokio, you _must_ make the current version of Tokio
222 /// available as `tokio` in the module where this macro is expanded.
223 #[proc_macro_attribute]
224 #[cfg(not(test))] // Work around for rust-lang/rust#62127
main_rt(args: TokenStream, item: TokenStream) -> TokenStream225 pub fn main_rt(args: TokenStream, item: TokenStream) -> TokenStream {
226     entry::main(args, item, false)
227 }
228 
229 /// Marks async function to be executed by runtime, suitable to test environment
230 ///
231 /// ## Usage
232 ///
233 /// ### Multi-thread runtime
234 ///
235 /// ```no_run
236 /// #[tokio::test(flavor = "multi_thread", worker_threads = 1)]
237 /// async fn my_test() {
238 ///     assert!(true);
239 /// }
240 /// ```
241 ///
242 /// ### Using default
243 ///
244 /// The default test runtime is single-threaded.
245 ///
246 /// ```no_run
247 /// #[tokio::test]
248 /// async fn my_test() {
249 ///     assert!(true);
250 /// }
251 /// ```
252 ///
253 /// ### Configure the runtime to start with time paused
254 ///
255 /// ```no_run
256 /// #[tokio::test(start_paused = true)]
257 /// async fn my_test() {
258 ///     assert!(true);
259 /// }
260 /// ```
261 ///
262 /// Note that `start_paused` requires the `test-util` feature to be enabled.
263 ///
264 /// ### NOTE:
265 ///
266 /// If you rename the Tokio crate in your dependencies this macro will not work.
267 /// If you must rename the current version of Tokio because you're also using an
268 /// older version of Tokio, you _must_ make the current version of Tokio
269 /// available as `tokio` in the module where this macro is expanded.
270 #[proc_macro_attribute]
test(args: TokenStream, item: TokenStream) -> TokenStream271 pub fn test(args: TokenStream, item: TokenStream) -> TokenStream {
272     entry::test(args, item, true)
273 }
274 
275 /// Marks async function to be executed by runtime, suitable to test environment
276 ///
277 /// ## Usage
278 ///
279 /// ```no_run
280 /// #[tokio::test]
281 /// async fn my_test() {
282 ///     assert!(true);
283 /// }
284 /// ```
285 ///
286 /// ### NOTE:
287 ///
288 /// If you rename the Tokio crate in your dependencies this macro will not work.
289 /// If you must rename the current version of Tokio because you're also using an
290 /// older version of Tokio, you _must_ make the current version of Tokio
291 /// available as `tokio` in the module where this macro is expanded.
292 #[proc_macro_attribute]
test_rt(args: TokenStream, item: TokenStream) -> TokenStream293 pub fn test_rt(args: TokenStream, item: TokenStream) -> TokenStream {
294     entry::test(args, item, false)
295 }
296 
297 /// Always fails with the error message below.
298 /// ```text
299 /// The #[tokio::main] macro requires rt or rt-multi-thread.
300 /// ```
301 #[proc_macro_attribute]
main_fail(_args: TokenStream, _item: TokenStream) -> TokenStream302 pub fn main_fail(_args: TokenStream, _item: TokenStream) -> TokenStream {
303     syn::Error::new(
304         proc_macro2::Span::call_site(),
305         "The #[tokio::main] macro requires rt or rt-multi-thread.",
306     )
307     .to_compile_error()
308     .into()
309 }
310 
311 /// Always fails with the error message below.
312 /// ```text
313 /// The #[tokio::test] macro requires rt or rt-multi-thread.
314 /// ```
315 #[proc_macro_attribute]
test_fail(_args: TokenStream, _item: TokenStream) -> TokenStream316 pub fn test_fail(_args: TokenStream, _item: TokenStream) -> TokenStream {
317     syn::Error::new(
318         proc_macro2::Span::call_site(),
319         "The #[tokio::test] macro requires rt or rt-multi-thread.",
320     )
321     .to_compile_error()
322     .into()
323 }
324 
325 /// Implementation detail of the `select!` macro. This macro is **not** intended
326 /// to be used as part of the public API and is permitted to change.
327 #[proc_macro]
328 #[doc(hidden)]
select_priv_declare_output_enum(input: TokenStream) -> TokenStream329 pub fn select_priv_declare_output_enum(input: TokenStream) -> TokenStream {
330     select::declare_output_enum(input)
331 }
332 
333 /// Implementation detail of the `select!` macro. This macro is **not** intended
334 /// to be used as part of the public API and is permitted to change.
335 #[proc_macro]
336 #[doc(hidden)]
select_priv_clean_pattern(input: TokenStream) -> TokenStream337 pub fn select_priv_clean_pattern(input: TokenStream) -> TokenStream {
338     select::clean_pattern_macro(input)
339 }
340