1 #![allow(unknown_lints, unexpected_cfgs)]
2 #![allow(clippy::needless_doctest_main)]
3 #![warn(
4     missing_debug_implementations,
5     missing_docs,
6     rust_2018_idioms,
7     unreachable_pub
8 )]
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 /// # Non-worker async function
44 ///
45 /// Note that the async function marked with this macro does not run as a
46 /// worker. The expectation is that other tasks are spawned by the function here.
47 /// Awaiting on other futures from the function provided here will not
48 /// perform as fast as those spawned as workers.
49 ///
50 /// # Multi-threaded runtime
51 ///
52 /// To use the multi-threaded runtime, the macro can be configured using
53 ///
54 /// ```
55 /// #[tokio::main(flavor = "multi_thread", worker_threads = 10)]
56 /// # async fn main() {}
57 /// ```
58 ///
59 /// The `worker_threads` option configures the number of worker threads, and
60 /// defaults to the number of cpus on the system. This is the default flavor.
61 ///
62 /// Note: The multi-threaded runtime requires the `rt-multi-thread` feature
63 /// flag.
64 ///
65 /// # Current thread runtime
66 ///
67 /// To use the single-threaded runtime known as the `current_thread` runtime,
68 /// the macro can be configured using
69 ///
70 /// ```
71 /// #[tokio::main(flavor = "current_thread")]
72 /// # async fn main() {}
73 /// ```
74 ///
75 /// ## Function arguments:
76 ///
77 /// Arguments are allowed for any functions aside from `main` which is special
78 ///
79 /// ## Usage
80 ///
81 /// ### Using the multi-thread runtime
82 ///
83 /// ```rust
84 /// #[tokio::main]
85 /// async fn main() {
86 ///     println!("Hello world");
87 /// }
88 /// ```
89 ///
90 /// Equivalent code not using `#[tokio::main]`
91 ///
92 /// ```rust
93 /// fn main() {
94 ///     tokio::runtime::Builder::new_multi_thread()
95 ///         .enable_all()
96 ///         .build()
97 ///         .unwrap()
98 ///         .block_on(async {
99 ///             println!("Hello world");
100 ///         })
101 /// }
102 /// ```
103 ///
104 /// ### Using current thread runtime
105 ///
106 /// The basic scheduler is single-threaded.
107 ///
108 /// ```rust
109 /// #[tokio::main(flavor = "current_thread")]
110 /// async fn main() {
111 ///     println!("Hello world");
112 /// }
113 /// ```
114 ///
115 /// Equivalent code not using `#[tokio::main]`
116 ///
117 /// ```rust
118 /// fn main() {
119 ///     tokio::runtime::Builder::new_current_thread()
120 ///         .enable_all()
121 ///         .build()
122 ///         .unwrap()
123 ///         .block_on(async {
124 ///             println!("Hello world");
125 ///         })
126 /// }
127 /// ```
128 ///
129 /// ### Set number of worker threads
130 ///
131 /// ```rust
132 /// #[tokio::main(worker_threads = 2)]
133 /// async fn main() {
134 ///     println!("Hello world");
135 /// }
136 /// ```
137 ///
138 /// Equivalent code not using `#[tokio::main]`
139 ///
140 /// ```rust
141 /// fn main() {
142 ///     tokio::runtime::Builder::new_multi_thread()
143 ///         .worker_threads(2)
144 ///         .enable_all()
145 ///         .build()
146 ///         .unwrap()
147 ///         .block_on(async {
148 ///             println!("Hello world");
149 ///         })
150 /// }
151 /// ```
152 ///
153 /// ### Configure the runtime to start with time paused
154 ///
155 /// ```rust
156 /// #[tokio::main(flavor = "current_thread", start_paused = true)]
157 /// async fn main() {
158 ///     println!("Hello world");
159 /// }
160 /// ```
161 ///
162 /// Equivalent code not using `#[tokio::main]`
163 ///
164 /// ```rust
165 /// fn main() {
166 ///     tokio::runtime::Builder::new_current_thread()
167 ///         .enable_all()
168 ///         .start_paused(true)
169 ///         .build()
170 ///         .unwrap()
171 ///         .block_on(async {
172 ///             println!("Hello world");
173 ///         })
174 /// }
175 /// ```
176 ///
177 /// Note that `start_paused` requires the `test-util` feature to be enabled.
178 ///
179 /// ### Rename package
180 ///
181 /// ```rust
182 /// use tokio as tokio1;
183 ///
184 /// #[tokio1::main(crate = "tokio1")]
185 /// async fn main() {
186 ///     println!("Hello world");
187 /// }
188 /// ```
189 ///
190 /// Equivalent code not using `#[tokio::main]`
191 ///
192 /// ```rust
193 /// use tokio as tokio1;
194 ///
195 /// fn main() {
196 ///     tokio1::runtime::Builder::new_multi_thread()
197 ///         .enable_all()
198 ///         .build()
199 ///         .unwrap()
200 ///         .block_on(async {
201 ///             println!("Hello world");
202 ///         })
203 /// }
204 /// ```
205 ///
206 /// ### Configure unhandled panic behavior
207 ///
208 /// Available options are `shutdown_runtime` and `ignore`. For more details, see
209 /// [`Builder::unhandled_panic`].
210 ///
211 /// This option is only compatible with the `current_thread` runtime.
212 ///
213 /// ```no_run
214 /// #[cfg(tokio_unstable)]
215 /// #[tokio::main(flavor = "current_thread", unhandled_panic = "shutdown_runtime")]
216 /// async fn main() {
217 ///     let _ = tokio::spawn(async {
218 ///         panic!("This panic will shutdown the runtime.");
219 ///     }).await;
220 /// }
221 /// # #[cfg(not(tokio_unstable))]
222 /// # fn main() { }
223 /// ```
224 ///
225 /// Equivalent code not using `#[tokio::main]`
226 ///
227 /// ```no_run
228 /// #[cfg(tokio_unstable)]
229 /// fn main() {
230 ///     tokio::runtime::Builder::new_current_thread()
231 ///         .enable_all()
232 ///         .unhandled_panic(UnhandledPanic::ShutdownRuntime)
233 ///         .build()
234 ///         .unwrap()
235 ///         .block_on(async {
236 ///             let _ = tokio::spawn(async {
237 ///                 panic!("This panic will shutdown the runtime.");
238 ///             }).await;
239 ///         })
240 /// }
241 /// # #[cfg(not(tokio_unstable))]
242 /// # fn main() { }
243 /// ```
244 ///
245 /// **Note**: This option depends on Tokio's [unstable API][unstable]. See [the
246 /// documentation on unstable features][unstable] for details on how to enable
247 /// Tokio's unstable features.
248 ///
249 /// [`Builder::unhandled_panic`]: ../tokio/runtime/struct.Builder.html#method.unhandled_panic
250 /// [unstable]: ../tokio/index.html#unstable-features
251 #[proc_macro_attribute]
main(args: TokenStream, item: TokenStream) -> TokenStream252 pub fn main(args: TokenStream, item: TokenStream) -> TokenStream {
253     entry::main(args.into(), item.into(), true).into()
254 }
255 
256 /// Marks async function to be executed by selected runtime. This macro helps set up a `Runtime`
257 /// without requiring the user to use [Runtime](../tokio/runtime/struct.Runtime.html) or
258 /// [Builder](../tokio/runtime/struct.Builder.html) directly.
259 ///
260 /// ## Function arguments:
261 ///
262 /// Arguments are allowed for any functions aside from `main` which is special
263 ///
264 /// ## Usage
265 ///
266 /// ### Using default
267 ///
268 /// ```rust
269 /// #[tokio::main(flavor = "current_thread")]
270 /// async fn main() {
271 ///     println!("Hello world");
272 /// }
273 /// ```
274 ///
275 /// Equivalent code not using `#[tokio::main]`
276 ///
277 /// ```rust
278 /// fn main() {
279 ///     tokio::runtime::Builder::new_current_thread()
280 ///         .enable_all()
281 ///         .build()
282 ///         .unwrap()
283 ///         .block_on(async {
284 ///             println!("Hello world");
285 ///         })
286 /// }
287 /// ```
288 ///
289 /// ### Rename package
290 ///
291 /// ```rust
292 /// use tokio as tokio1;
293 ///
294 /// #[tokio1::main(crate = "tokio1")]
295 /// async fn main() {
296 ///     println!("Hello world");
297 /// }
298 /// ```
299 ///
300 /// Equivalent code not using `#[tokio::main]`
301 ///
302 /// ```rust
303 /// use tokio as tokio1;
304 ///
305 /// fn main() {
306 ///     tokio1::runtime::Builder::new_multi_thread()
307 ///         .enable_all()
308 ///         .build()
309 ///         .unwrap()
310 ///         .block_on(async {
311 ///             println!("Hello world");
312 ///         })
313 /// }
314 /// ```
315 #[proc_macro_attribute]
main_rt(args: TokenStream, item: TokenStream) -> TokenStream316 pub fn main_rt(args: TokenStream, item: TokenStream) -> TokenStream {
317     entry::main(args.into(), item.into(), false).into()
318 }
319 
320 /// Marks async function to be executed by runtime, suitable to test environment.
321 /// This macro helps set up a `Runtime` without requiring the user to use
322 /// [Runtime](../tokio/runtime/struct.Runtime.html) or
323 /// [Builder](../tokio/runtime/struct.Builder.html) directly.
324 ///
325 /// Note: This macro is designed to be simplistic and targets applications that
326 /// do not require a complex setup. If the provided functionality is not
327 /// sufficient, you may be interested in using
328 /// [Builder](../tokio/runtime/struct.Builder.html), which provides a more
329 /// powerful interface.
330 ///
331 /// # Multi-threaded runtime
332 ///
333 /// To use the multi-threaded runtime, the macro can be configured using
334 ///
335 /// ```no_run
336 /// #[tokio::test(flavor = "multi_thread", worker_threads = 1)]
337 /// async fn my_test() {
338 ///     assert!(true);
339 /// }
340 /// ```
341 ///
342 /// The `worker_threads` option configures the number of worker threads, and
343 /// defaults to the number of cpus on the system.
344 ///
345 /// Note: The multi-threaded runtime requires the `rt-multi-thread` feature
346 /// flag.
347 ///
348 /// # Current thread runtime
349 ///
350 /// The default test runtime is single-threaded. Each test gets a
351 /// separate current-thread runtime.
352 ///
353 /// ```no_run
354 /// #[tokio::test]
355 /// async fn my_test() {
356 ///     assert!(true);
357 /// }
358 /// ```
359 ///
360 /// ## Usage
361 ///
362 /// ### Using the multi-thread runtime
363 ///
364 /// ```no_run
365 /// #[tokio::test(flavor = "multi_thread")]
366 /// async fn my_test() {
367 ///     assert!(true);
368 /// }
369 /// ```
370 ///
371 /// Equivalent code not using `#[tokio::test]`
372 ///
373 /// ```no_run
374 /// #[test]
375 /// fn my_test() {
376 ///     tokio::runtime::Builder::new_multi_thread()
377 ///         .enable_all()
378 ///         .build()
379 ///         .unwrap()
380 ///         .block_on(async {
381 ///             assert!(true);
382 ///         })
383 /// }
384 /// ```
385 ///
386 /// ### Using current thread runtime
387 ///
388 /// ```no_run
389 /// #[tokio::test]
390 /// async fn my_test() {
391 ///     assert!(true);
392 /// }
393 /// ```
394 ///
395 /// Equivalent code not using `#[tokio::test]`
396 ///
397 /// ```no_run
398 /// #[test]
399 /// fn my_test() {
400 ///     tokio::runtime::Builder::new_current_thread()
401 ///         .enable_all()
402 ///         .build()
403 ///         .unwrap()
404 ///         .block_on(async {
405 ///             assert!(true);
406 ///         })
407 /// }
408 /// ```
409 ///
410 /// ### Set number of worker threads
411 ///
412 /// ```no_run
413 /// #[tokio::test(flavor = "multi_thread", worker_threads = 2)]
414 /// async fn my_test() {
415 ///     assert!(true);
416 /// }
417 /// ```
418 ///
419 /// Equivalent code not using `#[tokio::test]`
420 ///
421 /// ```no_run
422 /// #[test]
423 /// fn my_test() {
424 ///     tokio::runtime::Builder::new_multi_thread()
425 ///         .worker_threads(2)
426 ///         .enable_all()
427 ///         .build()
428 ///         .unwrap()
429 ///         .block_on(async {
430 ///             assert!(true);
431 ///         })
432 /// }
433 /// ```
434 ///
435 /// ### Configure the runtime to start with time paused
436 ///
437 /// ```no_run
438 /// #[tokio::test(start_paused = true)]
439 /// async fn my_test() {
440 ///     assert!(true);
441 /// }
442 /// ```
443 ///
444 /// Equivalent code not using `#[tokio::test]`
445 ///
446 /// ```no_run
447 /// #[test]
448 /// fn my_test() {
449 ///     tokio::runtime::Builder::new_current_thread()
450 ///         .enable_all()
451 ///         .start_paused(true)
452 ///         .build()
453 ///         .unwrap()
454 ///         .block_on(async {
455 ///             assert!(true);
456 ///         })
457 /// }
458 /// ```
459 ///
460 /// Note that `start_paused` requires the `test-util` feature to be enabled.
461 ///
462 /// ### Rename package
463 ///
464 /// ```rust
465 /// use tokio as tokio1;
466 ///
467 /// #[tokio1::test(crate = "tokio1")]
468 /// async fn my_test() {
469 ///     println!("Hello world");
470 /// }
471 /// ```
472 ///
473 /// ### Configure unhandled panic behavior
474 ///
475 /// Available options are `shutdown_runtime` and `ignore`. For more details, see
476 /// [`Builder::unhandled_panic`].
477 ///
478 /// This option is only compatible with the `current_thread` runtime.
479 ///
480 /// ```no_run
481 /// #[cfg(tokio_unstable)]
482 /// #[tokio::test(flavor = "current_thread", unhandled_panic = "shutdown_runtime")]
483 /// async fn my_test() {
484 ///     let _ = tokio::spawn(async {
485 ///         panic!("This panic will shutdown the runtime.");
486 ///     }).await;
487 /// }
488 /// # #[cfg(not(tokio_unstable))]
489 /// # fn main() { }
490 /// ```
491 ///
492 /// Equivalent code not using `#[tokio::test]`
493 ///
494 /// ```no_run
495 /// #[cfg(tokio_unstable)]
496 /// #[test]
497 /// fn my_test() {
498 ///     tokio::runtime::Builder::new_current_thread()
499 ///         .enable_all()
500 ///         .unhandled_panic(UnhandledPanic::ShutdownRuntime)
501 ///         .build()
502 ///         .unwrap()
503 ///         .block_on(async {
504 ///             let _ = tokio::spawn(async {
505 ///                 panic!("This panic will shutdown the runtime.");
506 ///             }).await;
507 ///         })
508 /// }
509 /// # #[cfg(not(tokio_unstable))]
510 /// # fn main() { }
511 /// ```
512 ///
513 /// **Note**: This option depends on Tokio's [unstable API][unstable]. See [the
514 /// documentation on unstable features][unstable] for details on how to enable
515 /// Tokio's unstable features.
516 ///
517 /// [`Builder::unhandled_panic`]: ../tokio/runtime/struct.Builder.html#method.unhandled_panic
518 /// [unstable]: ../tokio/index.html#unstable-features
519 #[proc_macro_attribute]
test(args: TokenStream, item: TokenStream) -> TokenStream520 pub fn test(args: TokenStream, item: TokenStream) -> TokenStream {
521     entry::test(args.into(), item.into(), true).into()
522 }
523 
524 /// Marks async function to be executed by runtime, suitable to test environment
525 ///
526 /// ## Usage
527 ///
528 /// ```no_run
529 /// #[tokio::test]
530 /// async fn my_test() {
531 ///     assert!(true);
532 /// }
533 /// ```
534 #[proc_macro_attribute]
test_rt(args: TokenStream, item: TokenStream) -> TokenStream535 pub fn test_rt(args: TokenStream, item: TokenStream) -> TokenStream {
536     entry::test(args.into(), item.into(), false).into()
537 }
538 
539 /// Always fails with the error message below.
540 /// ```text
541 /// The #[tokio::main] macro requires rt or rt-multi-thread.
542 /// ```
543 #[proc_macro_attribute]
main_fail(_args: TokenStream, _item: TokenStream) -> TokenStream544 pub fn main_fail(_args: TokenStream, _item: TokenStream) -> TokenStream {
545     syn::Error::new(
546         proc_macro2::Span::call_site(),
547         "The #[tokio::main] macro requires rt or rt-multi-thread.",
548     )
549     .to_compile_error()
550     .into()
551 }
552 
553 /// Always fails with the error message below.
554 /// ```text
555 /// The #[tokio::test] macro requires rt or rt-multi-thread.
556 /// ```
557 #[proc_macro_attribute]
test_fail(_args: TokenStream, _item: TokenStream) -> TokenStream558 pub fn test_fail(_args: TokenStream, _item: TokenStream) -> TokenStream {
559     syn::Error::new(
560         proc_macro2::Span::call_site(),
561         "The #[tokio::test] macro requires rt or rt-multi-thread.",
562     )
563     .to_compile_error()
564     .into()
565 }
566 
567 /// Implementation detail of the `select!` macro. This macro is **not** intended
568 /// to be used as part of the public API and is permitted to change.
569 #[proc_macro]
570 #[doc(hidden)]
select_priv_declare_output_enum(input: TokenStream) -> TokenStream571 pub fn select_priv_declare_output_enum(input: TokenStream) -> TokenStream {
572     select::declare_output_enum(input)
573 }
574 
575 /// Implementation detail of the `select!` macro. This macro is **not** intended
576 /// to be used as part of the public API and is permitted to change.
577 #[proc_macro]
578 #[doc(hidden)]
select_priv_clean_pattern(input: TokenStream) -> TokenStream579 pub fn select_priv_clean_pattern(input: TokenStream) -> TokenStream {
580     select::clean_pattern_macro(input)
581 }
582