tokio_macros/
lib.rs

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