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)]
18 extern crate proc_macro;
19 
20 mod entry;
21 mod select;
22 
23 use 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 /// # Multi-threaded runtime
43 ///
44 /// To use the multi-threaded runtime, the macro can be configured using
45 ///
46 /// ```
47 /// #[tokio::main(flavor = "multi_thread", worker_threads = 10)]
48 /// # async fn main() {}
49 /// ```
50 ///
51 /// The `worker_threads` option configures the number of worker threads, and
52 /// defaults to the number of cpus on the system. This is the default flavor.
53 ///
54 /// Note: The multi-threaded runtime requires the `rt-multi-thread` feature
55 /// flag.
56 ///
57 /// # Current thread runtime
58 ///
59 /// To use the single-threaded runtime known as the `current_thread` runtime,
60 /// the macro can be configured using
61 ///
62 /// ```
63 /// #[tokio::main(flavor = "current_thread")]
64 /// # async fn main() {}
65 /// ```
66 ///
67 /// ## Function arguments:
68 ///
69 /// Arguments are allowed for any functions aside from `main` which is special
70 ///
71 /// ## Usage
72 ///
73 /// ### Using the multi-thread runtime
74 ///
75 /// ```rust
76 /// #[tokio::main]
77 /// async fn main() {
78 ///     println!("Hello world");
79 /// }
80 /// ```
81 ///
82 /// Equivalent code not using `#[tokio::main]`
83 ///
84 /// ```rust
85 /// fn main() {
86 ///     tokio::runtime::Builder::new_multi_thread()
87 ///         .enable_all()
88 ///         .build()
89 ///         .unwrap()
90 ///         .block_on(async {
91 ///             println!("Hello world");
92 ///         })
93 /// }
94 /// ```
95 ///
96 /// ### Using current thread runtime
97 ///
98 /// The basic scheduler is single-threaded.
99 ///
100 /// ```rust
101 /// #[tokio::main(flavor = "current_thread")]
102 /// async fn main() {
103 ///     println!("Hello world");
104 /// }
105 /// ```
106 ///
107 /// Equivalent code not using `#[tokio::main]`
108 ///
109 /// ```rust
110 /// fn main() {
111 ///     tokio::runtime::Builder::new_current_thread()
112 ///         .enable_all()
113 ///         .build()
114 ///         .unwrap()
115 ///         .block_on(async {
116 ///             println!("Hello world");
117 ///         })
118 /// }
119 /// ```
120 ///
121 /// ### Set number of worker threads
122 ///
123 /// ```rust
124 /// #[tokio::main(worker_threads = 2)]
125 /// async fn main() {
126 ///     println!("Hello world");
127 /// }
128 /// ```
129 ///
130 /// Equivalent code not using `#[tokio::main]`
131 ///
132 /// ```rust
133 /// fn main() {
134 ///     tokio::runtime::Builder::new_multi_thread()
135 ///         .worker_threads(2)
136 ///         .enable_all()
137 ///         .build()
138 ///         .unwrap()
139 ///         .block_on(async {
140 ///             println!("Hello world");
141 ///         })
142 /// }
143 /// ```
144 ///
145 /// ### Configure the runtime to start with time paused
146 ///
147 /// ```rust
148 /// #[tokio::main(flavor = "current_thread", start_paused = true)]
149 /// async fn main() {
150 ///     println!("Hello world");
151 /// }
152 /// ```
153 ///
154 /// Equivalent code not using `#[tokio::main]`
155 ///
156 /// ```rust
157 /// fn main() {
158 ///     tokio::runtime::Builder::new_current_thread()
159 ///         .enable_all()
160 ///         .start_paused(true)
161 ///         .build()
162 ///         .unwrap()
163 ///         .block_on(async {
164 ///             println!("Hello world");
165 ///         })
166 /// }
167 /// ```
168 ///
169 /// Note that `start_paused` requires the `test-util` feature to be enabled.
170 ///
171 /// ### NOTE:
172 ///
173 /// If you rename the Tokio crate in your dependencies this macro will not work.
174 /// If you must rename the current version of Tokio because you're also using an
175 /// older version of Tokio, you _must_ make the current version of Tokio
176 /// available as `tokio` in the module where this macro is expanded.
177 #[proc_macro_attribute]
178 #[cfg(not(test))] // Work around for rust-lang/rust#62127
main(args: TokenStream, item: TokenStream) -> TokenStream179 pub fn main(args: TokenStream, item: TokenStream) -> TokenStream {
180     entry::main(args, item, true)
181 }
182 
183 /// Marks async function to be executed by selected runtime. This macro helps set up a `Runtime`
184 /// without requiring the user to use [Runtime](../tokio/runtime/struct.Runtime.html) or
185 /// [Builder](../tokio/runtime/struct.builder.html) directly.
186 ///
187 /// ## Function arguments:
188 ///
189 /// Arguments are allowed for any functions aside from `main` which is special
190 ///
191 /// ## Usage
192 ///
193 /// ### Using default
194 ///
195 /// ```rust
196 /// #[tokio::main(flavor = "current_thread")]
197 /// async fn main() {
198 ///     println!("Hello world");
199 /// }
200 /// ```
201 ///
202 /// Equivalent code not using `#[tokio::main]`
203 ///
204 /// ```rust
205 /// fn main() {
206 ///     tokio::runtime::Builder::new_current_thread()
207 ///         .enable_all()
208 ///         .build()
209 ///         .unwrap()
210 ///         .block_on(async {
211 ///             println!("Hello world");
212 ///         })
213 /// }
214 /// ```
215 ///
216 /// ### NOTE:
217 ///
218 /// If you rename the Tokio crate in your dependencies this macro will not work.
219 /// If you must rename the current version of Tokio because you're also using an
220 /// older version of Tokio, you _must_ make the current version of Tokio
221 /// available as `tokio` in the module where this macro is expanded.
222 #[proc_macro_attribute]
223 #[cfg(not(test))] // Work around for rust-lang/rust#62127
main_rt(args: TokenStream, item: TokenStream) -> TokenStream224 pub fn main_rt(args: TokenStream, item: TokenStream) -> TokenStream {
225     entry::main(args, item, false)
226 }
227 
228 /// Marks async function to be executed by runtime, suitable to test environment
229 ///
230 /// ## Usage
231 ///
232 /// ### Multi-thread runtime
233 ///
234 /// ```no_run
235 /// #[tokio::test(flavor = "multi_thread", worker_threads = 1)]
236 /// async fn my_test() {
237 ///     assert!(true);
238 /// }
239 /// ```
240 ///
241 /// ### Using default
242 ///
243 /// The default test runtime is single-threaded.
244 ///
245 /// ```no_run
246 /// #[tokio::test]
247 /// async fn my_test() {
248 ///     assert!(true);
249 /// }
250 /// ```
251 ///
252 /// ### Configure the runtime to start with time paused
253 ///
254 /// ```no_run
255 /// #[tokio::test(start_paused = true)]
256 /// async fn my_test() {
257 ///     assert!(true);
258 /// }
259 /// ```
260 ///
261 /// Note that `start_paused` requires the `test-util` feature to be enabled.
262 ///
263 /// ### NOTE:
264 ///
265 /// If you rename the Tokio crate in your dependencies this macro will not work.
266 /// If you must rename the current version of Tokio because you're also using an
267 /// older version of Tokio, you _must_ make the current version of Tokio
268 /// available as `tokio` in the module where this macro is expanded.
269 #[proc_macro_attribute]
test(args: TokenStream, item: TokenStream) -> TokenStream270 pub fn test(args: TokenStream, item: TokenStream) -> TokenStream {
271     entry::test(args, item, true)
272 }
273 
274 /// Marks async function to be executed by runtime, suitable to test environment
275 ///
276 /// ## Usage
277 ///
278 /// ```no_run
279 /// #[tokio::test]
280 /// async fn my_test() {
281 ///     assert!(true);
282 /// }
283 /// ```
284 ///
285 /// ### NOTE:
286 ///
287 /// If you rename the Tokio crate in your dependencies this macro will not work.
288 /// If you must rename the current version of Tokio because you're also using an
289 /// older version of Tokio, you _must_ make the current version of Tokio
290 /// available as `tokio` in the module where this macro is expanded.
291 #[proc_macro_attribute]
test_rt(args: TokenStream, item: TokenStream) -> TokenStream292 pub fn test_rt(args: TokenStream, item: TokenStream) -> TokenStream {
293     entry::test(args, item, false)
294 }
295 
296 /// Always fails with the error message below.
297 /// ```text
298 /// The #[tokio::main] macro requires rt or rt-multi-thread.
299 /// ```
300 #[proc_macro_attribute]
main_fail(_args: TokenStream, _item: TokenStream) -> TokenStream301 pub fn main_fail(_args: TokenStream, _item: TokenStream) -> TokenStream {
302     syn::Error::new(
303         proc_macro2::Span::call_site(),
304         "The #[tokio::main] macro requires rt or rt-multi-thread.",
305     )
306     .to_compile_error()
307     .into()
308 }
309 
310 /// Always fails with the error message below.
311 /// ```text
312 /// The #[tokio::test] macro requires rt or rt-multi-thread.
313 /// ```
314 #[proc_macro_attribute]
test_fail(_args: TokenStream, _item: TokenStream) -> TokenStream315 pub fn test_fail(_args: TokenStream, _item: TokenStream) -> TokenStream {
316     syn::Error::new(
317         proc_macro2::Span::call_site(),
318         "The #[tokio::test] macro requires rt or rt-multi-thread.",
319     )
320     .to_compile_error()
321     .into()
322 }
323 
324 /// Implementation detail of the `select!` macro. This macro is **not** intended
325 /// to be used as part of the public API and is permitted to change.
326 #[proc_macro]
327 #[doc(hidden)]
select_priv_declare_output_enum(input: TokenStream) -> TokenStream328 pub fn select_priv_declare_output_enum(input: TokenStream) -> TokenStream {
329     select::declare_output_enum(input)
330 }
331 
332 /// Implementation detail of the `select!` macro. This macro is **not** intended
333 /// to be used as part of the public API and is permitted to change.
334 #[proc_macro]
335 #[doc(hidden)]
select_priv_clean_pattern(input: TokenStream) -> TokenStream336 pub fn select_priv_clean_pattern(input: TokenStream) -> TokenStream {
337     select::clean_pattern_macro(input)
338 }
339