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/// #[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]
252pub 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]
316pub 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]
520pub 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]
535pub 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]
544pub 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]
558pub 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)]
571pub 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)]
579pub fn select_priv_clean_pattern(input: TokenStream) -> TokenStream {
580 select::clean_pattern_macro(input)
581}