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