tokio_macros/
lib.rs

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)]
19extern crate proc_macro;
20
21mod entry;
22mod select;
23
24use 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/// # #![allow(unknown_lints, unexpected_cfgs)]
215/// #[cfg(tokio_unstable)]
216/// #[tokio::main(flavor = "current_thread", unhandled_panic = "shutdown_runtime")]
217/// async fn main() {
218///     let _ = tokio::spawn(async {
219///         panic!("This panic will shutdown the runtime.");
220///     }).await;
221/// }
222/// # #[cfg(not(tokio_unstable))]
223/// # fn main() { }
224/// ```
225///
226/// Equivalent code not using `#[tokio::main]`
227///
228/// ```no_run
229/// # #![allow(unknown_lints, unexpected_cfgs)]
230/// #[cfg(tokio_unstable)]
231/// fn main() {
232///     tokio::runtime::Builder::new_current_thread()
233///         .enable_all()
234///         .unhandled_panic(UnhandledPanic::ShutdownRuntime)
235///         .build()
236///         .unwrap()
237///         .block_on(async {
238///             let _ = tokio::spawn(async {
239///                 panic!("This panic will shutdown the runtime.");
240///             }).await;
241///         })
242/// }
243/// # #[cfg(not(tokio_unstable))]
244/// # fn main() { }
245/// ```
246///
247/// **Note**: This option depends on Tokio's [unstable API][unstable]. See [the
248/// documentation on unstable features][unstable] for details on how to enable
249/// Tokio's unstable features.
250///
251/// [`Builder::unhandled_panic`]: ../tokio/runtime/struct.Builder.html#method.unhandled_panic
252/// [unstable]: ../tokio/index.html#unstable-features
253#[proc_macro_attribute]
254pub fn main(args: TokenStream, item: TokenStream) -> TokenStream {
255    entry::main(args.into(), item.into(), true).into()
256}
257
258/// Marks async function to be executed by selected runtime. This macro helps set up a `Runtime`
259/// without requiring the user to use [Runtime](../tokio/runtime/struct.Runtime.html) or
260/// [Builder](../tokio/runtime/struct.Builder.html) directly.
261///
262/// ## Function arguments:
263///
264/// Arguments are allowed for any functions aside from `main` which is special
265///
266/// ## Usage
267///
268/// ### Using default
269///
270/// ```rust
271/// #[tokio::main(flavor = "current_thread")]
272/// async fn main() {
273///     println!("Hello world");
274/// }
275/// ```
276///
277/// Equivalent code not using `#[tokio::main]`
278///
279/// ```rust
280/// fn main() {
281///     tokio::runtime::Builder::new_current_thread()
282///         .enable_all()
283///         .build()
284///         .unwrap()
285///         .block_on(async {
286///             println!("Hello world");
287///         })
288/// }
289/// ```
290///
291/// ### Rename package
292///
293/// ```rust
294/// use tokio as tokio1;
295///
296/// #[tokio1::main(crate = "tokio1")]
297/// async fn main() {
298///     println!("Hello world");
299/// }
300/// ```
301///
302/// Equivalent code not using `#[tokio::main]`
303///
304/// ```rust
305/// use tokio as tokio1;
306///
307/// fn main() {
308///     tokio1::runtime::Builder::new_multi_thread()
309///         .enable_all()
310///         .build()
311///         .unwrap()
312///         .block_on(async {
313///             println!("Hello world");
314///         })
315/// }
316/// ```
317#[proc_macro_attribute]
318pub fn main_rt(args: TokenStream, item: TokenStream) -> TokenStream {
319    entry::main(args.into(), item.into(), false).into()
320}
321
322/// Marks async function to be executed by runtime, suitable to test environment.
323/// This macro helps set up a `Runtime` without requiring the user to use
324/// [Runtime](../tokio/runtime/struct.Runtime.html) or
325/// [Builder](../tokio/runtime/struct.Builder.html) directly.
326///
327/// Note: This macro is designed to be simplistic and targets applications that
328/// do not require a complex setup. If the provided functionality is not
329/// sufficient, you may be interested in using
330/// [Builder](../tokio/runtime/struct.Builder.html), which provides a more
331/// powerful interface.
332///
333/// # Multi-threaded runtime
334///
335/// To use the multi-threaded runtime, the macro can be configured using
336///
337/// ```no_run
338/// #[tokio::test(flavor = "multi_thread", worker_threads = 1)]
339/// async fn my_test() {
340///     assert!(true);
341/// }
342/// ```
343///
344/// The `worker_threads` option configures the number of worker threads, and
345/// defaults to the number of cpus on the system.
346///
347/// Note: The multi-threaded runtime requires the `rt-multi-thread` feature
348/// flag.
349///
350/// # Current thread runtime
351///
352/// The default test runtime is single-threaded. Each test gets a
353/// separate current-thread runtime.
354///
355/// ```no_run
356/// #[tokio::test]
357/// async fn my_test() {
358///     assert!(true);
359/// }
360/// ```
361///
362/// ## Usage
363///
364/// ### Using the multi-thread runtime
365///
366/// ```no_run
367/// #[tokio::test(flavor = "multi_thread")]
368/// async fn my_test() {
369///     assert!(true);
370/// }
371/// ```
372///
373/// Equivalent code not using `#[tokio::test]`
374///
375/// ```no_run
376/// #[test]
377/// fn my_test() {
378///     tokio::runtime::Builder::new_multi_thread()
379///         .enable_all()
380///         .build()
381///         .unwrap()
382///         .block_on(async {
383///             assert!(true);
384///         })
385/// }
386/// ```
387///
388/// ### Using current thread runtime
389///
390/// ```no_run
391/// #[tokio::test]
392/// async fn my_test() {
393///     assert!(true);
394/// }
395/// ```
396///
397/// Equivalent code not using `#[tokio::test]`
398///
399/// ```no_run
400/// #[test]
401/// fn my_test() {
402///     tokio::runtime::Builder::new_current_thread()
403///         .enable_all()
404///         .build()
405///         .unwrap()
406///         .block_on(async {
407///             assert!(true);
408///         })
409/// }
410/// ```
411///
412/// ### Set number of worker threads
413///
414/// ```no_run
415/// #[tokio::test(flavor = "multi_thread", worker_threads = 2)]
416/// async fn my_test() {
417///     assert!(true);
418/// }
419/// ```
420///
421/// Equivalent code not using `#[tokio::test]`
422///
423/// ```no_run
424/// #[test]
425/// fn my_test() {
426///     tokio::runtime::Builder::new_multi_thread()
427///         .worker_threads(2)
428///         .enable_all()
429///         .build()
430///         .unwrap()
431///         .block_on(async {
432///             assert!(true);
433///         })
434/// }
435/// ```
436///
437/// ### Configure the runtime to start with time paused
438///
439/// ```no_run
440/// #[tokio::test(start_paused = true)]
441/// async fn my_test() {
442///     assert!(true);
443/// }
444/// ```
445///
446/// Equivalent code not using `#[tokio::test]`
447///
448/// ```no_run
449/// #[test]
450/// fn my_test() {
451///     tokio::runtime::Builder::new_current_thread()
452///         .enable_all()
453///         .start_paused(true)
454///         .build()
455///         .unwrap()
456///         .block_on(async {
457///             assert!(true);
458///         })
459/// }
460/// ```
461///
462/// Note that `start_paused` requires the `test-util` feature to be enabled.
463///
464/// ### Rename package
465///
466/// ```rust
467/// use tokio as tokio1;
468///
469/// #[tokio1::test(crate = "tokio1")]
470/// async fn my_test() {
471///     println!("Hello world");
472/// }
473/// ```
474///
475/// ### Configure unhandled panic behavior
476///
477/// Available options are `shutdown_runtime` and `ignore`. For more details, see
478/// [`Builder::unhandled_panic`].
479///
480/// This option is only compatible with the `current_thread` runtime.
481///
482/// ```no_run
483/// # #![allow(unknown_lints, unexpected_cfgs)]
484/// #[cfg(tokio_unstable)]
485/// #[tokio::test(flavor = "current_thread", unhandled_panic = "shutdown_runtime")]
486/// async fn my_test() {
487///     let _ = tokio::spawn(async {
488///         panic!("This panic will shutdown the runtime.");
489///     }).await;
490/// }
491/// # #[cfg(not(tokio_unstable))]
492/// # fn main() { }
493/// ```
494///
495/// Equivalent code not using `#[tokio::test]`
496///
497/// ```no_run
498/// # #![allow(unknown_lints, unexpected_cfgs)]
499/// #[cfg(tokio_unstable)]
500/// #[test]
501/// fn my_test() {
502///     tokio::runtime::Builder::new_current_thread()
503///         .enable_all()
504///         .unhandled_panic(UnhandledPanic::ShutdownRuntime)
505///         .build()
506///         .unwrap()
507///         .block_on(async {
508///             let _ = tokio::spawn(async {
509///                 panic!("This panic will shutdown the runtime.");
510///             }).await;
511///         })
512/// }
513/// # #[cfg(not(tokio_unstable))]
514/// # fn main() { }
515/// ```
516///
517/// **Note**: This option depends on Tokio's [unstable API][unstable]. See [the
518/// documentation on unstable features][unstable] for details on how to enable
519/// Tokio's unstable features.
520///
521/// [`Builder::unhandled_panic`]: ../tokio/runtime/struct.Builder.html#method.unhandled_panic
522/// [unstable]: ../tokio/index.html#unstable-features
523#[proc_macro_attribute]
524pub fn test(args: TokenStream, item: TokenStream) -> TokenStream {
525    entry::test(args.into(), item.into(), true).into()
526}
527
528/// Marks async function to be executed by runtime, suitable to test environment
529///
530/// ## Usage
531///
532/// ```no_run
533/// #[tokio::test]
534/// async fn my_test() {
535///     assert!(true);
536/// }
537/// ```
538#[proc_macro_attribute]
539pub fn test_rt(args: TokenStream, item: TokenStream) -> TokenStream {
540    entry::test(args.into(), item.into(), false).into()
541}
542
543/// Always fails with the error message below.
544/// ```text
545/// The #[tokio::main] macro requires rt or rt-multi-thread.
546/// ```
547#[proc_macro_attribute]
548pub fn main_fail(_args: TokenStream, _item: TokenStream) -> TokenStream {
549    syn::Error::new(
550        proc_macro2::Span::call_site(),
551        "The #[tokio::main] macro requires rt or rt-multi-thread.",
552    )
553    .to_compile_error()
554    .into()
555}
556
557/// Always fails with the error message below.
558/// ```text
559/// The #[tokio::test] macro requires rt or rt-multi-thread.
560/// ```
561#[proc_macro_attribute]
562pub fn test_fail(_args: TokenStream, _item: TokenStream) -> TokenStream {
563    syn::Error::new(
564        proc_macro2::Span::call_site(),
565        "The #[tokio::test] macro requires rt or rt-multi-thread.",
566    )
567    .to_compile_error()
568    .into()
569}
570
571/// Implementation detail of the `select!` macro. This macro is **not** intended
572/// to be used as part of the public API and is permitted to change.
573#[proc_macro]
574#[doc(hidden)]
575pub fn select_priv_declare_output_enum(input: TokenStream) -> TokenStream {
576    select::declare_output_enum(input)
577}
578
579/// Implementation detail of the `select!` macro. This macro is **not** intended
580/// to be used as part of the public API and is permitted to change.
581#[proc_macro]
582#[doc(hidden)]
583pub fn select_priv_clean_pattern(input: TokenStream) -> TokenStream {
584    select::clean_pattern_macro(input)
585}