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)]
19 extern crate proc_macro;
20
21 mod entry;
22 mod select;
23
24 use 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]
main(args: TokenStream, item: TokenStream) -> TokenStream252 pub 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]
main_rt(args: TokenStream, item: TokenStream) -> TokenStream316 pub 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]
test(args: TokenStream, item: TokenStream) -> TokenStream520 pub 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]
test_rt(args: TokenStream, item: TokenStream) -> TokenStream535 pub 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]
main_fail(_args: TokenStream, _item: TokenStream) -> TokenStream544 pub 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]
test_fail(_args: TokenStream, _item: TokenStream) -> TokenStream558 pub 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)]
select_priv_declare_output_enum(input: TokenStream) -> TokenStream571 pub 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)]
select_priv_clean_pattern(input: TokenStream) -> TokenStream579 pub fn select_priv_clean_pattern(input: TokenStream) -> TokenStream {
580 select::clean_pattern_macro(input)
581 }
582