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#[proc_macro_attribute]
205#[cfg(not(test))] // Work around for rust-lang/rust#62127
206pub fn main(args: TokenStream, item: TokenStream) -> TokenStream {
207 entry::main(args.into(), item.into(), true).into()
208}
209
210/// Marks async function to be executed by selected runtime. This macro helps set up a `Runtime`
211/// without requiring the user to use [Runtime](../tokio/runtime/struct.Runtime.html) or
212/// [Builder](../tokio/runtime/struct.Builder.html) directly.
213///
214/// ## Function arguments:
215///
216/// Arguments are allowed for any functions aside from `main` which is special
217///
218/// ## Usage
219///
220/// ### Using default
221///
222/// ```rust
223/// #[tokio::main(flavor = "current_thread")]
224/// async fn main() {
225/// println!("Hello world");
226/// }
227/// ```
228///
229/// Equivalent code not using `#[tokio::main]`
230///
231/// ```rust
232/// fn main() {
233/// tokio::runtime::Builder::new_current_thread()
234/// .enable_all()
235/// .build()
236/// .unwrap()
237/// .block_on(async {
238/// println!("Hello world");
239/// })
240/// }
241/// ```
242///
243/// ### Rename package
244///
245/// ```rust
246/// use tokio as tokio1;
247///
248/// #[tokio1::main(crate = "tokio1")]
249/// async fn main() {
250/// println!("Hello world");
251/// }
252/// ```
253///
254/// Equivalent code not using `#[tokio::main]`
255///
256/// ```rust
257/// use tokio as tokio1;
258///
259/// fn main() {
260/// tokio1::runtime::Builder::new_multi_thread()
261/// .enable_all()
262/// .build()
263/// .unwrap()
264/// .block_on(async {
265/// println!("Hello world");
266/// })
267/// }
268/// ```
269#[proc_macro_attribute]
270#[cfg(not(test))] // Work around for rust-lang/rust#62127
271pub fn main_rt(args: TokenStream, item: TokenStream) -> TokenStream {
272 entry::main(args.into(), item.into(), false).into()
273}
274
275/// Marks async function to be executed by runtime, suitable to test environment.
276/// This macro helps set up a `Runtime` without requiring the user to use
277/// [Runtime](../tokio/runtime/struct.Runtime.html) or
278/// [Builder](../tokio/runtime/struct.Builder.html) directly.
279///
280/// Note: This macro is designed to be simplistic and targets applications that
281/// do not require a complex setup. If the provided functionality is not
282/// sufficient, you may be interested in using
283/// [Builder](../tokio/runtime/struct.Builder.html), which provides a more
284/// powerful interface.
285///
286/// # Multi-threaded runtime
287///
288/// To use the multi-threaded runtime, the macro can be configured using
289///
290/// ```no_run
291/// #[tokio::test(flavor = "multi_thread", worker_threads = 1)]
292/// async fn my_test() {
293/// assert!(true);
294/// }
295/// ```
296///
297/// The `worker_threads` option configures the number of worker threads, and
298/// defaults to the number of cpus on the system.
299///
300/// Note: The multi-threaded runtime requires the `rt-multi-thread` feature
301/// flag.
302///
303/// # Current thread runtime
304///
305/// The default test runtime is single-threaded. Each test gets a
306/// separate current-thread runtime.
307///
308/// ```no_run
309/// #[tokio::test]
310/// async fn my_test() {
311/// assert!(true);
312/// }
313/// ```
314///
315/// ## Usage
316///
317/// ### Using the multi-thread runtime
318///
319/// ```no_run
320/// #[tokio::test(flavor = "multi_thread")]
321/// async fn my_test() {
322/// assert!(true);
323/// }
324/// ```
325///
326/// Equivalent code not using `#[tokio::test]`
327///
328/// ```no_run
329/// #[test]
330/// fn my_test() {
331/// tokio::runtime::Builder::new_multi_thread()
332/// .enable_all()
333/// .build()
334/// .unwrap()
335/// .block_on(async {
336/// assert!(true);
337/// })
338/// }
339/// ```
340///
341/// ### Using current thread runtime
342///
343/// ```no_run
344/// #[tokio::test]
345/// async fn my_test() {
346/// assert!(true);
347/// }
348/// ```
349///
350/// Equivalent code not using `#[tokio::test]`
351///
352/// ```no_run
353/// #[test]
354/// fn my_test() {
355/// tokio::runtime::Builder::new_current_thread()
356/// .enable_all()
357/// .build()
358/// .unwrap()
359/// .block_on(async {
360/// assert!(true);
361/// })
362/// }
363/// ```
364///
365/// ### Set number of worker threads
366///
367/// ```no_run
368/// #[tokio::test(flavor ="multi_thread", worker_threads = 2)]
369/// async fn my_test() {
370/// assert!(true);
371/// }
372/// ```
373///
374/// Equivalent code not using `#[tokio::test]`
375///
376/// ```no_run
377/// #[test]
378/// fn my_test() {
379/// tokio::runtime::Builder::new_multi_thread()
380/// .worker_threads(2)
381/// .enable_all()
382/// .build()
383/// .unwrap()
384/// .block_on(async {
385/// assert!(true);
386/// })
387/// }
388/// ```
389///
390/// ### Configure the runtime to start with time paused
391///
392/// ```no_run
393/// #[tokio::test(start_paused = true)]
394/// async fn my_test() {
395/// assert!(true);
396/// }
397/// ```
398///
399/// Equivalent code not using `#[tokio::test]`
400///
401/// ```no_run
402/// #[test]
403/// fn my_test() {
404/// tokio::runtime::Builder::new_current_thread()
405/// .enable_all()
406/// .start_paused(true)
407/// .build()
408/// .unwrap()
409/// .block_on(async {
410/// assert!(true);
411/// })
412/// }
413/// ```
414///
415/// Note that `start_paused` requires the `test-util` feature to be enabled.
416///
417/// ### Rename package
418///
419/// ```rust
420/// use tokio as tokio1;
421///
422/// #[tokio1::test(crate = "tokio1")]
423/// async fn my_test() {
424/// println!("Hello world");
425/// }
426/// ```
427#[proc_macro_attribute]
428pub fn test(args: TokenStream, item: TokenStream) -> TokenStream {
429 entry::test(args.into(), item.into(), true).into()
430}
431
432/// Marks async function to be executed by runtime, suitable to test environment
433///
434/// ## Usage
435///
436/// ```no_run
437/// #[tokio::test]
438/// async fn my_test() {
439/// assert!(true);
440/// }
441/// ```
442#[proc_macro_attribute]
443pub fn test_rt(args: TokenStream, item: TokenStream) -> TokenStream {
444 entry::test(args.into(), item.into(), false).into()
445}
446
447/// Always fails with the error message below.
448/// ```text
449/// The #[tokio::main] macro requires rt or rt-multi-thread.
450/// ```
451#[proc_macro_attribute]
452pub fn main_fail(_args: TokenStream, _item: TokenStream) -> TokenStream {
453 syn::Error::new(
454 proc_macro2::Span::call_site(),
455 "The #[tokio::main] macro requires rt or rt-multi-thread.",
456 )
457 .to_compile_error()
458 .into()
459}
460
461/// Always fails with the error message below.
462/// ```text
463/// The #[tokio::test] macro requires rt or rt-multi-thread.
464/// ```
465#[proc_macro_attribute]
466pub fn test_fail(_args: TokenStream, _item: TokenStream) -> TokenStream {
467 syn::Error::new(
468 proc_macro2::Span::call_site(),
469 "The #[tokio::test] macro requires rt or rt-multi-thread.",
470 )
471 .to_compile_error()
472 .into()
473}
474
475/// Implementation detail of the `select!` macro. This macro is **not** intended
476/// to be used as part of the public API and is permitted to change.
477#[proc_macro]
478#[doc(hidden)]
479pub fn select_priv_declare_output_enum(input: TokenStream) -> TokenStream {
480 select::declare_output_enum(input)
481}
482
483/// Implementation detail of the `select!` macro. This macro is **not** intended
484/// to be used as part of the public API and is permitted to change.
485#[proc_macro]
486#[doc(hidden)]
487pub fn select_priv_clean_pattern(input: TokenStream) -> TokenStream {
488 select::clean_pattern_macro(input)
489}
490