• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 /// # #![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]
main(args: TokenStream, item: TokenStream) -> TokenStream254 pub 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]
main_rt(args: TokenStream, item: TokenStream) -> TokenStream318 pub 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]
test(args: TokenStream, item: TokenStream) -> TokenStream524 pub 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]
test_rt(args: TokenStream, item: TokenStream) -> TokenStream539 pub 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]
main_fail(_args: TokenStream, _item: TokenStream) -> TokenStream548 pub 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]
test_fail(_args: TokenStream, _item: TokenStream) -> TokenStream562 pub 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)]
select_priv_declare_output_enum(input: TokenStream) -> TokenStream575 pub 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)]
select_priv_clean_pattern(input: TokenStream) -> TokenStream583 pub fn select_priv_clean_pattern(input: TokenStream) -> TokenStream {
584     select::clean_pattern_macro(input)
585 }
586