1 //! A procedural macro attribute for instrumenting functions with [`tracing`].
2 //!
3 //! [`tracing`] is a framework for instrumenting Rust programs to collect
4 //! structured, event-based diagnostic information. This crate provides the
5 //! [`#[instrument]`][instrument] procedural macro attribute.
6 //!
7 //! Note that this macro is also re-exported by the main `tracing` crate.
8 //!
9 //! *Compiler support: [requires `rustc` 1.56+][msrv]*
10 //!
11 //! [msrv]: #supported-rust-versions
12 //!
13 //! ## Usage
14 //!
15 //! In the `Cargo.toml`:
16 //!
17 //! ```toml
18 //! [dependencies]
19 //! tracing-attributes = "0.1.24"
20 //! ```
21 //!
22 //! The [`#[instrument]`][instrument] attribute can now be added to a function
23 //! to automatically create and enter `tracing` [span] when that function is
24 //! called. For example:
25 //!
26 //! ```
27 //! use tracing::instrument;
28 //!
29 //! #[instrument]
30 //! pub fn my_function(my_arg: usize) {
31 //!     // ...
32 //! }
33 //!
34 //! # fn main() {}
35 //! ```
36 //!
37 //! [`tracing`]: https://crates.io/crates/tracing
38 //! [span]: https://docs.rs/tracing/latest/tracing/span/index.html
39 //! [instrument]: macro@self::instrument
40 //!
41 //! ## Supported Rust Versions
42 //!
43 //! Tracing is built against the latest stable release. The minimum supported
44 //! version is 1.56. The current Tracing version is not guaranteed to build on
45 //! Rust versions earlier than the minimum supported version.
46 //!
47 //! Tracing follows the same compiler support policies as the rest of the Tokio
48 //! project. The current stable Rust compiler and the three most recent minor
49 //! versions before it will always be supported. For example, if the current
50 //! stable compiler version is 1.69, the minimum supported version will not be
51 //! increased past 1.66, three minor versions prior. Increasing the minimum
52 //! supported compiler version is not considered a semver breaking change as
53 //! long as doing so complies with this policy.
54 //!
55 #![doc(
56     html_logo_url = "https://raw.githubusercontent.com/tokio-rs/tracing/master/assets/logo-type.png",
57     issue_tracker_base_url = "https://github.com/tokio-rs/tracing/issues/"
58 )]
59 #![cfg_attr(docsrs, deny(rustdoc::broken_intra_doc_links))]
60 #![warn(
61     missing_debug_implementations,
62     missing_docs,
63     rust_2018_idioms,
64     unreachable_pub,
65     bad_style,
66     dead_code,
67     improper_ctypes,
68     non_shorthand_field_patterns,
69     no_mangle_generic_items,
70     overflowing_literals,
71     path_statements,
72     patterns_in_fns_without_body,
73     private_in_public,
74     unconditional_recursion,
75     unused_allocation,
76     unused_comparisons,
77     unused_parens,
78     while_true
79 )]
80 // TODO: once `tracing` bumps its MSRV to 1.42, remove this allow.
81 #![allow(unused)]
82 extern crate proc_macro;
83 
84 use proc_macro2::TokenStream;
85 use quote::{quote, ToTokens};
86 use syn::parse::{Parse, ParseStream};
87 use syn::{Attribute, ItemFn, Signature, Visibility};
88 
89 mod attr;
90 mod expand;
91 /// Instruments a function to create and enter a `tracing` [span] every time
92 /// the function is called.
93 ///
94 /// Unless overridden, a span with the [`INFO`] [level] will be generated.
95 /// The generated span's name will be the name of the function.
96 /// By default, all arguments to the function are included as fields on the
97 /// span. Arguments that are `tracing` [primitive types] implementing the
98 /// [`Value` trait] will be recorded as fields of that type. Types which do
99 /// not implement `Value` will be recorded using [`std::fmt::Debug`].
100 ///
101 /// [primitive types]: https://docs.rs/tracing/latest/tracing/field/trait.Value.html#foreign-impls
102 /// [`Value` trait]: https://docs.rs/tracing/latest/tracing/field/trait.Value.html.
103 ///
104 /// # Overriding Span Attributes
105 ///
106 /// To change the [name] of the generated span, add a `name` argument to the
107 /// `#[instrument]` macro, followed by an equals sign and a string literal. For
108 /// example:
109 ///
110 /// ```
111 /// # use tracing_attributes::instrument;
112 ///
113 /// // The generated span's name will be "my_span" rather than "my_function".
114 /// #[instrument(name = "my_span")]
115 /// pub fn my_function() {
116 ///     // ... do something incredibly interesting and important ...
117 /// }
118 /// ```
119 ///
120 /// To override the [target] of the generated span, add a `target` argument to
121 /// the `#[instrument]` macro, followed by an equals sign and a string literal
122 /// for the new target. The [module path] is still recorded separately. For
123 /// example:
124 ///
125 /// ```
126 /// pub mod my_module {
127 ///     # use tracing_attributes::instrument;
128 ///     // The generated span's target will be "my_crate::some_special_target",
129 ///     // rather than "my_crate::my_module".
130 ///     #[instrument(target = "my_crate::some_special_target")]
131 ///     pub fn my_function() {
132 ///         // ... all kinds of neat code in here ...
133 ///     }
134 /// }
135 /// ```
136 ///
137 /// Finally, to override the [level] of the generated span, add a `level`
138 /// argument, followed by an equals sign and a string literal with the name of
139 /// the desired level. Level names are not case sensitive. For example:
140 ///
141 /// ```
142 /// # use tracing_attributes::instrument;
143 /// // The span's level will be TRACE rather than INFO.
144 /// #[instrument(level = "trace")]
145 /// pub fn my_function() {
146 ///     // ... I have written a truly marvelous implementation of this function,
147 ///     // which this example is too narrow to contain ...
148 /// }
149 /// ```
150 ///
151 /// # Skipping Fields
152 ///
153 /// To skip recording one or more arguments to a function or method, pass
154 /// the argument's name inside the `skip()` argument on the `#[instrument]`
155 /// macro. This can be used when an argument to an instrumented function does
156 /// not implement [`fmt::Debug`], or to exclude an argument with a verbose or
157 /// costly `Debug` implementation. Note that:
158 ///
159 /// - multiple argument names can be passed to `skip`.
160 /// - arguments passed to `skip` do _not_ need to implement `fmt::Debug`.
161 ///
162 /// You can also use `skip_all` to skip all arguments.
163 ///
164 /// ## Examples
165 ///
166 /// ```
167 /// # use tracing_attributes::instrument;
168 /// # use std::collections::HashMap;
169 /// // This type doesn't implement `fmt::Debug`!
170 /// struct NonDebug;
171 ///
172 /// // `arg` will be recorded, while `non_debug` will not.
173 /// #[instrument(skip(non_debug))]
174 /// fn my_function(arg: usize, non_debug: NonDebug) {
175 ///     // ...
176 /// }
177 ///
178 /// // These arguments are huge
179 /// #[instrument(skip_all)]
180 /// fn my_big_data_function(large: Vec<u8>, also_large: HashMap<String, String>) {
181 ///     // ...
182 /// }
183 /// ```
184 ///
185 /// Skipping the `self` parameter:
186 ///
187 /// ```
188 /// # use tracing_attributes::instrument;
189 /// #[derive(Debug)]
190 /// struct MyType {
191 ///    data: Vec<u8>, // Suppose this buffer is often quite long...
192 /// }
193 ///
194 /// impl MyType {
195 ///     // Suppose we don't want to print an entire kilobyte of `data`
196 ///     // every time this is called...
197 ///     #[instrument(skip(self))]
198 ///     pub fn my_method(&mut self, an_interesting_argument: usize) {
199 ///          // ... do something (hopefully, using all that `data`!)
200 ///     }
201 /// }
202 /// ```
203 ///
204 /// # Adding Fields
205 ///
206 /// Additional fields (key-value pairs with arbitrary data) can be passed to
207 /// to the generated span through the `fields` argument on the
208 /// `#[instrument]` macro. Strings, integers or boolean literals are accepted values
209 /// for each field. The name of the field must be a single valid Rust
210 /// identifier, nested (dotted) field names are not supported. Any
211 /// Rust expression can be used as a field value in this manner. These
212 /// expressions will be evaluated at the beginning of the function's body, so
213 /// arguments to the function may be used in these expressions. Field names may
214 /// also be specified *without* values. Doing so will result in an [empty field]
215 /// whose value may be recorded later within the function body.
216 ///
217 /// Note that overlap between the names of fields and (non-skipped) arguments
218 /// will result in a compile error.
219 ///
220 /// ## Examples
221 ///
222 /// Adding a new field based on the value of an argument:
223 ///
224 /// ```
225 /// # use tracing_attributes::instrument;
226 ///
227 /// // This will record a field named "i" with the value of `i` *and* a field
228 /// // named "next" with the value of `i` + 1.
229 /// #[instrument(fields(next = i + 1))]
230 /// pub fn my_function(i: usize) {
231 ///     // ...
232 /// }
233 /// ```
234 ///
235 /// Recording specific properties of a struct as their own fields:
236 ///
237 /// ```
238 /// # mod http {
239 /// #   pub struct Error;
240 /// #   pub struct Response<B> { pub(super) _b: std::marker::PhantomData<B> }
241 /// #   pub struct Request<B> { _b: B }
242 /// #   impl<B> std::fmt::Debug for Request<B> {
243 /// #       fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
244 /// #           f.pad("request")
245 /// #       }
246 /// #   }
247 /// #   impl<B> Request<B> {
248 /// #       pub fn uri(&self) -> &str { "fake" }
249 /// #       pub fn method(&self) -> &str { "GET" }
250 /// #   }
251 /// # }
252 /// # use tracing_attributes::instrument;
253 ///
254 /// // This will record the request's URI and HTTP method as their own separate
255 /// // fields.
256 /// #[instrument(fields(http.uri = req.uri(), http.method = req.method()))]
257 /// pub fn handle_request<B>(req: http::Request<B>) -> http::Response<B> {
258 ///     // ... handle the request ...
259 ///     # http::Response { _b: std::marker::PhantomData }
260 /// }
261 /// ```
262 ///
263 /// This can be used in conjunction with `skip` or `skip_all` to record only
264 /// some fields of a struct:
265 /// ```
266 /// # use tracing_attributes::instrument;
267 /// // Remember the struct with the very large `data` field from the earlier
268 /// // example? Now it also has a `name`, which we might want to include in
269 /// // our span.
270 /// #[derive(Debug)]
271 /// struct MyType {
272 ///    name: &'static str,
273 ///    data: Vec<u8>,
274 /// }
275 ///
276 /// impl MyType {
277 ///     // This will skip the `data` field, but will include `self.name`,
278 ///     // formatted using `fmt::Display`.
279 ///     #[instrument(skip(self), fields(self.name = %self.name))]
280 ///     pub fn my_method(&mut self, an_interesting_argument: usize) {
281 ///          // ... do something (hopefully, using all that `data`!)
282 ///     }
283 /// }
284 /// ```
285 ///
286 /// Adding an empty field to be recorded later:
287 ///
288 /// ```
289 /// # use tracing_attributes::instrument;
290 ///
291 /// // This function does a very interesting and important mathematical calculation.
292 /// // Suppose we want to record both the inputs to the calculation *and* its result...
293 /// #[instrument(fields(result))]
294 /// pub fn do_calculation(input_1: usize, input_2: usize) -> usize {
295 ///     // Rerform the calculation.
296 ///     let result = input_1 + input_2;
297 ///
298 ///     // Record the result as part of the current span.
299 ///     tracing::Span::current().record("result", &result);
300 ///
301 ///     // Now, the result will also be included on this event!
302 ///     tracing::info!("calculation complete!");
303 ///
304 ///     // ... etc ...
305 ///     # 0
306 /// }
307 /// ```
308 ///
309 /// # Examples
310 ///
311 /// Instrumenting a function:
312 ///
313 /// ```
314 /// # use tracing_attributes::instrument;
315 /// #[instrument]
316 /// pub fn my_function(my_arg: usize) {
317 ///     // This event will be recorded inside a span named `my_function` with the
318 ///     // field `my_arg`.
319 ///     tracing::info!("inside my_function!");
320 ///     // ...
321 /// }
322 /// ```
323 /// Setting the level for the generated span:
324 /// ```
325 /// # use tracing_attributes::instrument;
326 /// # use tracing::Level;
327 /// #[instrument(level = Level::DEBUG)]
328 /// pub fn my_function() {
329 ///     // ...
330 /// }
331 /// ```
332 /// Levels can be specified either with [`Level`] constants, literal strings
333 /// (e.g., `"debug"`, `"info"`) or numerically (1—5, corresponding to [`Level::TRACE`]—[`Level::ERROR`]).
334 ///
335 /// Overriding the generated span's name:
336 /// ```
337 /// # use tracing_attributes::instrument;
338 /// #[instrument(name = "my_name")]
339 /// pub fn my_function() {
340 ///     // ...
341 /// }
342 /// ```
343 /// Overriding the generated span's target:
344 /// ```
345 /// # use tracing_attributes::instrument;
346 /// #[instrument(target = "my_target")]
347 /// pub fn my_function() {
348 ///     // ...
349 /// }
350 /// ```
351 /// Overriding the generated span's parent:
352 /// ```
353 /// # use tracing_attributes::instrument;
354 /// #[instrument(parent = None)]
355 /// pub fn my_function() {
356 ///     // ...
357 /// }
358 /// ```
359 /// ```
360 /// # use tracing_attributes::instrument;
361 /// // A struct which owns a span handle.
362 /// struct MyStruct
363 /// {
364 ///     span: tracing::Span
365 /// }
366 ///
367 /// impl MyStruct
368 /// {
369 ///     // Use the struct's `span` field as the parent span
370 ///     #[instrument(parent = &self.span, skip(self))]
371 ///     fn my_method(&self) {}
372 /// }
373 /// ```
374 /// Specifying [`follows_from`] relationships:
375 /// ```
376 /// # use tracing_attributes::instrument;
377 /// #[instrument(follows_from = causes)]
378 /// pub fn my_function(causes: &[tracing::Id]) {
379 ///     // ...
380 /// }
381 /// ```
382 /// Any expression of type `impl IntoIterator<Item = impl Into<Option<Id>>>`
383 /// may be provided to `follows_from`; e.g.:
384 /// ```
385 /// # use tracing_attributes::instrument;
386 /// #[instrument(follows_from = [cause])]
387 /// pub fn my_function(cause: &tracing::span::EnteredSpan) {
388 ///     // ...
389 /// }
390 /// ```
391 ///
392 ///
393 /// To skip recording an argument, pass the argument's name to the `skip`:
394 ///
395 /// ```
396 /// # use tracing_attributes::instrument;
397 /// struct NonDebug;
398 ///
399 /// #[instrument(skip(non_debug))]
400 /// fn my_function(arg: usize, non_debug: NonDebug) {
401 ///     // ...
402 /// }
403 /// ```
404 ///
405 /// To add additional context to the span, pass key-value pairs to `fields`:
406 ///
407 /// ```
408 /// # use tracing_attributes::instrument;
409 /// #[instrument(fields(foo="bar", id=1, show=true))]
410 /// fn my_function(arg: usize) {
411 ///     // ...
412 /// }
413 /// ```
414 ///
415 /// Adding the `ret` argument to `#[instrument]` will emit an event with the function's
416 /// return value when the function returns:
417 ///
418 /// ```
419 /// # use tracing_attributes::instrument;
420 /// #[instrument(ret)]
421 /// fn my_function() -> i32 {
422 ///     42
423 /// }
424 /// ```
425 /// The return value event will have the same level as the span generated by `#[instrument]`.
426 /// By default, this will be [`INFO`], but if the level is overridden, the event will be at the same
427 /// level.
428 ///
429 /// It's also possible to override the level for the `ret` event independently:
430 ///
431 /// ```
432 /// # use tracing_attributes::instrument;
433 /// # use tracing::Level;
434 /// #[instrument(ret(level = Level::WARN))]
435 /// fn my_function() -> i32 {
436 ///     42
437 /// }
438 /// ```
439 ///
440 /// **Note**:  if the function returns a `Result<T, E>`, `ret` will record returned values if and
441 /// only if the function returns [`Result::Ok`].
442 ///
443 /// By default, returned values will be recorded using their [`std::fmt::Debug`] implementations.
444 /// If a returned value implements [`std::fmt::Display`], it can be recorded using its `Display`
445 /// implementation instead, by writing `ret(Display)`:
446 ///
447 /// ```
448 /// # use tracing_attributes::instrument;
449 /// #[instrument(ret(Display))]
450 /// fn my_function() -> i32 {
451 ///     42
452 /// }
453 /// ```
454 ///
455 /// If the function returns a `Result<T, E>` and `E` implements `std::fmt::Display`, adding
456 /// `err` or `err(Display)` will emit error events when the function returns `Err`:
457 ///
458 /// ```
459 /// # use tracing_attributes::instrument;
460 /// #[instrument(err)]
461 /// fn my_function(arg: usize) -> Result<(), std::io::Error> {
462 ///     Ok(())
463 /// }
464 /// ```
465 ///
466 /// The level of the error value event defaults to `ERROR`.
467 ///
468 /// Similarly, overriding the level of the `err` event :
469 ///
470 /// ```
471 /// # use tracing_attributes::instrument;
472 /// # use tracing::Level;
473 /// #[instrument(err(level = Level::INFO))]
474 /// fn my_function(arg: usize) -> Result<(), std::io::Error> {
475 ///     Ok(())
476 /// }
477 /// ```
478 ///
479 /// By default, error values will be recorded using their `std::fmt::Display` implementations.
480 /// If an error implements `std::fmt::Debug`, it can be recorded using its `Debug` implementation
481 /// instead by writing `err(Debug)`:
482 ///
483 /// ```
484 /// # use tracing_attributes::instrument;
485 /// #[instrument(err(Debug))]
486 /// fn my_function(arg: usize) -> Result<(), std::io::Error> {
487 ///     Ok(())
488 /// }
489 /// ```
490 ///
491 /// If a `target` is specified, both the `ret` and `err` arguments will emit outputs to
492 /// the declared target (or the default channel if `target` is not specified).
493 ///
494 /// The `ret` and `err` arguments can be combined in order to record an event if a
495 /// function returns [`Result::Ok`] or [`Result::Err`]:
496 ///
497 /// ```
498 /// # use tracing_attributes::instrument;
499 /// #[instrument(err, ret)]
500 /// fn my_function(arg: usize) -> Result<(), std::io::Error> {
501 ///     Ok(())
502 /// }
503 /// ```
504 ///
505 /// `async fn`s may also be instrumented:
506 ///
507 /// ```
508 /// # use tracing_attributes::instrument;
509 /// #[instrument]
510 /// pub async fn my_function() -> Result<(), ()> {
511 ///     // ...
512 ///     # Ok(())
513 /// }
514 /// ```
515 ///
516 /// It also works with [async-trait](https://crates.io/crates/async-trait)
517 /// (a crate that allows defining async functions in traits,
518 /// something not currently possible in Rust),
519 /// and hopefully most libraries that exhibit similar behaviors:
520 ///
521 /// ```
522 /// # use tracing::instrument;
523 /// use async_trait::async_trait;
524 ///
525 /// #[async_trait]
526 /// pub trait Foo {
527 ///     async fn foo(&self, arg: usize);
528 /// }
529 ///
530 /// #[derive(Debug)]
531 /// struct FooImpl(usize);
532 ///
533 /// #[async_trait]
534 /// impl Foo for FooImpl {
535 ///     #[instrument(fields(value = self.0, tmp = std::any::type_name::<Self>()))]
536 ///     async fn foo(&self, arg: usize) {}
537 /// }
538 /// ```
539 ///
540 /// `const fn` cannot be instrumented, and will result in a compilation failure:
541 ///
542 /// ```compile_fail
543 /// # use tracing_attributes::instrument;
544 /// #[instrument]
545 /// const fn my_const_function() {}
546 /// ```
547 ///
548 /// [span]: https://docs.rs/tracing/latest/tracing/span/index.html
549 /// [name]: https://docs.rs/tracing/latest/tracing/struct.Metadata.html#method.name
550 /// [target]: https://docs.rs/tracing/latest/tracing/struct.Metadata.html#method.target
551 /// [level]: https://docs.rs/tracing/latest/tracing/struct.Level.html
552 /// [module path]: https://docs.rs/tracing/latest/tracing/struct.Metadata.html#method.module_path
553 /// [`INFO`]: https://docs.rs/tracing/latest/tracing/struct.Level.html#associatedconstant.INFO
554 /// [empty field]: https://docs.rs/tracing/latest/tracing/field/struct.Empty.html
555 /// [field syntax]: https://docs.rs/tracing/latest/tracing/#recording-fields
556 /// [`follows_from`]: https://docs.rs/tracing/latest/tracing/struct.Span.html#method.follows_from
557 /// [`tracing`]: https://github.com/tokio-rs/tracing
558 /// [`fmt::Debug`]: std::fmt::Debug
559 /// [`Level`]: https://docs.rs/tracing/latest/tracing/struct.Level.html
560 /// [`Level::TRACE`]: https://docs.rs/tracing/latest/tracing/struct.Level.html#associatedconstant.TRACE
561 /// [`Level::ERROR`]: https://docs.rs/tracing/latest/tracing/struct.Level.html#associatedconstant.ERROR
562 #[proc_macro_attribute]
instrument( args: proc_macro::TokenStream, item: proc_macro::TokenStream, ) -> proc_macro::TokenStream563 pub fn instrument(
564     args: proc_macro::TokenStream,
565     item: proc_macro::TokenStream,
566 ) -> proc_macro::TokenStream {
567     let args = syn::parse_macro_input!(args as attr::InstrumentArgs);
568     // Cloning a `TokenStream` is cheap since it's reference counted internally.
569     instrument_precise(args.clone(), item.clone())
570         .unwrap_or_else(|_err| instrument_speculative(args, item))
571 }
572 
573 /// Instrument the function, without parsing the function body (instead using the raw tokens).
instrument_speculative( args: attr::InstrumentArgs, item: proc_macro::TokenStream, ) -> proc_macro::TokenStream574 fn instrument_speculative(
575     args: attr::InstrumentArgs,
576     item: proc_macro::TokenStream,
577 ) -> proc_macro::TokenStream {
578     let input = syn::parse_macro_input!(item as MaybeItemFn);
579     let instrumented_function_name = input.sig.ident.to_string();
580     expand::gen_function(
581         input.as_ref(),
582         args,
583         instrumented_function_name.as_str(),
584         None,
585     )
586     .into()
587 }
588 
589 /// Instrument the function, by fully parsing the function body,
590 /// which allows us to rewrite some statements related to async-like patterns.
instrument_precise( args: attr::InstrumentArgs, item: proc_macro::TokenStream, ) -> Result<proc_macro::TokenStream, syn::Error>591 fn instrument_precise(
592     args: attr::InstrumentArgs,
593     item: proc_macro::TokenStream,
594 ) -> Result<proc_macro::TokenStream, syn::Error> {
595     let input = syn::parse::<ItemFn>(item)?;
596     let instrumented_function_name = input.sig.ident.to_string();
597 
598     if input.sig.constness.is_some() {
599         return Ok(quote! {
600             compile_error!("the `#[instrument]` attribute may not be used with `const fn`s")
601         }
602         .into());
603     }
604 
605     // check for async_trait-like patterns in the block, and instrument
606     // the future instead of the wrapper
607     if let Some(async_like) = expand::AsyncInfo::from_fn(&input) {
608         return async_like.gen_async(args, instrumented_function_name.as_str());
609     }
610 
611     let input = MaybeItemFn::from(input);
612 
613     Ok(expand::gen_function(
614         input.as_ref(),
615         args,
616         instrumented_function_name.as_str(),
617         None,
618     )
619     .into())
620 }
621 
622 /// This is a more flexible/imprecise `ItemFn` type,
623 /// which's block is just a `TokenStream` (it may contain invalid code).
624 #[derive(Debug, Clone)]
625 struct MaybeItemFn {
626     outer_attrs: Vec<Attribute>,
627     inner_attrs: Vec<Attribute>,
628     vis: Visibility,
629     sig: Signature,
630     block: TokenStream,
631 }
632 
633 impl MaybeItemFn {
as_ref(&self) -> MaybeItemFnRef<'_, TokenStream>634     fn as_ref(&self) -> MaybeItemFnRef<'_, TokenStream> {
635         MaybeItemFnRef {
636             outer_attrs: &self.outer_attrs,
637             inner_attrs: &self.inner_attrs,
638             vis: &self.vis,
639             sig: &self.sig,
640             block: &self.block,
641         }
642     }
643 }
644 
645 /// This parses a `TokenStream` into a `MaybeItemFn`
646 /// (just like `ItemFn`, but skips parsing the body).
647 impl Parse for MaybeItemFn {
parse(input: ParseStream<'_>) -> syn::Result<Self>648     fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
649         let outer_attrs = input.call(Attribute::parse_outer)?;
650         let vis: Visibility = input.parse()?;
651         let sig: Signature = input.parse()?;
652         let inner_attrs = input.call(Attribute::parse_inner)?;
653         let block: TokenStream = input.parse()?;
654         Ok(Self {
655             outer_attrs,
656             inner_attrs,
657             vis,
658             sig,
659             block,
660         })
661     }
662 }
663 
664 impl From<ItemFn> for MaybeItemFn {
665     fn from(
666         ItemFn {
667             attrs,
668             vis,
669             sig,
670             block,
671         }: ItemFn,
672     ) -> Self {
673         let (outer_attrs, inner_attrs) = attrs
674             .into_iter()
675             .partition(|attr| attr.style == syn::AttrStyle::Outer);
676         Self {
677             outer_attrs,
678             inner_attrs,
679             vis,
680             sig,
681             block: block.to_token_stream(),
682         }
683     }
684 }
685 
686 /// A generic reference type for `MaybeItemFn`,
687 /// that takes a generic block type `B` that implements `ToTokens` (eg. `TokenStream`, `Block`).
688 #[derive(Debug, Clone)]
689 struct MaybeItemFnRef<'a, B: ToTokens> {
690     outer_attrs: &'a Vec<Attribute>,
691     inner_attrs: &'a Vec<Attribute>,
692     vis: &'a Visibility,
693     sig: &'a Signature,
694     block: &'a B,
695 }
696