tracing_attributes/
lib.rs

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.65+][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.65. 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/main/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_interfaces,
74    private_bounds,
75    unconditional_recursion,
76    unused_allocation,
77    unused_comparisons,
78    unused_parens,
79    while_true
80)]
81
82use proc_macro2::TokenStream;
83use quote::TokenStreamExt;
84use quote::{quote, ToTokens};
85use syn::parse::{Parse, ParseStream};
86use syn::token::Brace;
87use syn::{Attribute, ItemFn, Signature, Visibility};
88
89mod attr;
90mod 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 [`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
207/// to the generated span through the `fields` argument on the
208/// `#[instrument]` macro. Arbitrary expressions are accepted as value
209/// for each field. The name of the field must be a single valid Rust
210/// identifier, or a constant expression that evaluates to one, enclosed in curly
211/// braces. Note that nested (dotted) field names are also supported. Any
212/// Rust expression can be used as a field value in this manner. These
213/// expressions will be evaluated at the beginning of the function's body, so
214/// arguments to the function may be used in these expressions. Field names may
215/// also be specified *without* values. Doing so will result in an [empty field]
216/// whose value may be recorded later within the function body.
217///
218/// Note that defining a field with the same name as a (non-skipped)
219/// argument will implicitly skip the argument, unless the field is provided
220/// via a constant expression (e.g. {EXPR} or {const_fn()}) as deduplicating
221/// would incur a runtime cost. In this case, the
222/// field must be explicitly skipped.
223///
224/// ## Examples
225///
226/// Adding a new field based on the value of an argument:
227///
228/// ```
229/// # use tracing_attributes::instrument;
230///
231/// // This will record a field named "i" with the value of `i` *and* a field
232/// // named "next" with the value of `i` + 1.
233/// #[instrument(fields(next = i + 1))]
234/// pub fn my_function(i: usize) {
235///     // ...
236/// }
237/// ```
238///
239/// Recording specific properties of a struct as their own fields:
240///
241/// ```
242/// # mod http {
243/// #   pub struct Error;
244/// #   pub struct Response<B> { pub(super) _b: std::marker::PhantomData<B> }
245/// #   pub struct Request<B> { _b: B }
246/// #   impl<B> std::fmt::Debug for Request<B> {
247/// #       fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
248/// #           f.pad("request")
249/// #       }
250/// #   }
251/// #   impl<B> Request<B> {
252/// #       pub fn uri(&self) -> &str { "fake" }
253/// #       pub fn method(&self) -> &str { "GET" }
254/// #   }
255/// # }
256/// # use tracing_attributes::instrument;
257///
258/// // This will record the request's URI and HTTP method as their own separate
259/// // fields.
260/// #[instrument(fields(http.uri = req.uri(), http.method = req.method()))]
261/// pub fn handle_request<B>(req: http::Request<B>) -> http::Response<B> {
262///     // ... handle the request ...
263///     # http::Response { _b: std::marker::PhantomData }
264/// }
265/// ```
266///
267/// This can be used in conjunction with `skip` or `skip_all` to record only
268/// some fields of a struct:
269/// ```
270/// # use tracing_attributes::instrument;
271/// // Remember the struct with the very large `data` field from the earlier
272/// // example? Now it also has a `name`, which we might want to include in
273/// // our span.
274/// #[derive(Debug)]
275/// struct MyType {
276///    name: &'static str,
277///    data: Vec<u8>,
278/// }
279///
280/// impl MyType {
281///     // This will skip the `data` field, but will include `self.name`,
282///     // formatted using `fmt::Display`.
283///     #[instrument(skip(self), fields(self.name = %self.name))]
284///     pub fn my_method(&mut self, an_interesting_argument: usize) {
285///          // ... do something (hopefully, using all that `data`!)
286///     }
287/// }
288/// ```
289///
290/// Adding an empty field to be recorded later:
291///
292/// ```
293/// # use tracing_attributes::instrument;
294///
295/// // This function does a very interesting and important mathematical calculation.
296/// // Suppose we want to record both the inputs to the calculation *and* its result...
297/// #[instrument(fields(result))]
298/// pub fn do_calculation(input_1: usize, input_2: usize) -> usize {
299///     // Rerform the calculation.
300///     let result = input_1 + input_2;
301///
302///     // Record the result as part of the current span.
303///     tracing::Span::current().record("result", &result);
304///
305///     // Now, the result will also be included on this event!
306///     tracing::info!("calculation complete!");
307///
308///     // ... etc ...
309///     # 0
310/// }
311/// ```
312///
313/// # Examples
314///
315/// Instrumenting a function:
316///
317/// ```
318/// # use tracing_attributes::instrument;
319/// #[instrument]
320/// pub fn my_function(my_arg: usize) {
321///     // This event will be recorded inside a span named `my_function` with the
322///     // field `my_arg`.
323///     tracing::info!("inside my_function!");
324///     // ...
325/// }
326/// ```
327/// Setting the level for the generated span:
328/// ```
329/// # use tracing_attributes::instrument;
330/// # use tracing::Level;
331/// #[instrument(level = Level::DEBUG)]
332/// pub fn my_function() {
333///     // ...
334/// }
335/// ```
336/// Levels can be specified either with [`Level`] constants, literal strings
337/// (e.g., `"debug"`, `"info"`) or numerically (1—5, corresponding to [`Level::TRACE`]—[`Level::ERROR`]).
338///
339/// Overriding the generated span's name:
340/// ```
341/// # use tracing_attributes::instrument;
342/// #[instrument(name = "my_name")]
343/// pub fn my_function() {
344///     // ...
345/// }
346/// ```
347/// Overriding the generated span's target:
348/// ```
349/// # use tracing_attributes::instrument;
350/// #[instrument(target = "my_target")]
351/// pub fn my_function() {
352///     // ...
353/// }
354/// ```
355/// Overriding the generated span's parent:
356/// ```
357/// # use tracing_attributes::instrument;
358/// #[instrument(parent = None)]
359/// pub fn my_function() {
360///     // ...
361/// }
362/// ```
363/// ```
364/// # use tracing_attributes::instrument;
365/// // A struct which owns a span handle.
366/// struct MyStruct
367/// {
368///     span: tracing::Span
369/// }
370///
371/// impl MyStruct
372/// {
373///     // Use the struct's `span` field as the parent span
374///     #[instrument(parent = &self.span, skip(self))]
375///     fn my_method(&self) {}
376/// }
377/// ```
378/// Specifying [`follows_from`] relationships:
379/// ```
380/// # use tracing_attributes::instrument;
381/// #[instrument(follows_from = causes)]
382/// pub fn my_function(causes: &[tracing::Id]) {
383///     // ...
384/// }
385/// ```
386/// Any expression of type `impl IntoIterator<Item = impl Into<Option<Id>>>`
387/// may be provided to `follows_from`; e.g.:
388/// ```
389/// # use tracing_attributes::instrument;
390/// #[instrument(follows_from = [cause])]
391/// pub fn my_function(cause: &tracing::span::EnteredSpan) {
392///     // ...
393/// }
394/// ```
395///
396///
397/// To skip recording an argument, pass the argument's name to the `skip`:
398///
399/// ```
400/// # use tracing_attributes::instrument;
401/// struct NonDebug;
402///
403/// #[instrument(skip(non_debug))]
404/// fn my_function(arg: usize, non_debug: NonDebug) {
405///     // ...
406/// }
407/// ```
408///
409/// To add additional context to the span, pass key-value pairs to `fields`:
410///
411/// ```
412/// # use tracing_attributes::instrument;
413/// #[derive(Debug)]
414/// struct Argument;
415/// impl Argument {
416///     fn bar(&self) -> &'static str {
417///         "bar"
418///     }
419/// }
420/// const FOOBAR: &'static str = "foo.bar";
421/// #[instrument(fields(foo="bar", id=1, show=true, {FOOBAR}=%arg.bar()))]
422/// fn my_function(arg: Argument) {
423///     // ...
424/// }
425/// ```
426///
427/// Adding the `ret` argument to `#[instrument]` will emit an event with the function's
428/// return value when the function returns:
429///
430/// ```
431/// # use tracing_attributes::instrument;
432/// #[instrument(ret)]
433/// fn my_function() -> i32 {
434///     42
435/// }
436/// ```
437/// The return value event will have the same level as the span generated by `#[instrument]`.
438/// By default, this will be [`INFO`], but if the level is overridden, the event will be at the same
439/// level.
440///
441/// It's also possible to override the level for the `ret` event independently:
442///
443/// ```
444/// # use tracing_attributes::instrument;
445/// # use tracing::Level;
446/// #[instrument(ret(level = Level::WARN))]
447/// fn my_function() -> i32 {
448///     42
449/// }
450/// ```
451///
452/// **Note**:  if the function returns a `Result<T, E>`, `ret` will record returned values if and
453/// only if the function returns [`Result::Ok`].
454///
455/// By default, returned values will be recorded using their [`std::fmt::Debug`] implementations.
456/// If a returned value implements [`std::fmt::Display`], it can be recorded using its `Display`
457/// implementation instead, by writing `ret(Display)`:
458///
459/// ```
460/// # use tracing_attributes::instrument;
461/// #[instrument(ret(Display))]
462/// fn my_function() -> i32 {
463///     42
464/// }
465/// ```
466///
467/// If the function returns a `Result<T, E>` and `E` implements `std::fmt::Display`, adding
468/// `err` or `err(Display)` will emit error events when the function returns `Err`:
469///
470/// ```
471/// # use tracing_attributes::instrument;
472/// #[instrument(err)]
473/// fn my_function(arg: usize) -> Result<(), std::io::Error> {
474///     Ok(())
475/// }
476/// ```
477///
478/// The level of the error value event defaults to `ERROR`.
479///
480/// Similarly, overriding the level of the `err` event :
481///
482/// ```
483/// # use tracing_attributes::instrument;
484/// # use tracing::Level;
485/// #[instrument(err(level = Level::INFO))]
486/// fn my_function(arg: usize) -> Result<(), std::io::Error> {
487///     Ok(())
488/// }
489/// ```
490///
491/// By default, error values will be recorded using their `std::fmt::Display` implementations.
492/// If an error implements `std::fmt::Debug`, it can be recorded using its `Debug` implementation
493/// instead by writing `err(Debug)`:
494///
495/// ```
496/// # use tracing_attributes::instrument;
497/// #[instrument(err(Debug))]
498/// fn my_function(arg: usize) -> Result<(), std::io::Error> {
499///     Ok(())
500/// }
501/// ```
502///
503/// If a `target` is specified, both the `ret` and `err` arguments will emit outputs to
504/// the declared target (or the default channel if `target` is not specified).
505///
506/// The `ret` and `err` arguments can be combined in order to record an event if a
507/// function returns [`Result::Ok`] or [`Result::Err`]:
508///
509/// ```
510/// # use tracing_attributes::instrument;
511/// #[instrument(err, ret)]
512/// fn my_function(arg: usize) -> Result<(), std::io::Error> {
513///     Ok(())
514/// }
515/// ```
516///
517/// `async fn`s may also be instrumented:
518///
519/// ```
520/// # use tracing_attributes::instrument;
521/// #[instrument]
522/// pub async fn my_function() -> Result<(), ()> {
523///     // ...
524///     # Ok(())
525/// }
526/// ```
527///
528/// It also works with [async-trait](https://crates.io/crates/async-trait)
529/// (a crate that allows defining async functions in traits,
530/// something not currently possible in Rust),
531/// and hopefully most libraries that exhibit similar behaviors:
532///
533/// ```
534/// # use tracing::instrument;
535/// use async_trait::async_trait;
536///
537/// #[async_trait]
538/// pub trait Foo {
539///     async fn foo(&self, arg: usize);
540/// }
541///
542/// #[derive(Debug)]
543/// struct FooImpl(usize);
544///
545/// #[async_trait]
546/// impl Foo for FooImpl {
547///     #[instrument(fields(value = self.0, tmp = std::any::type_name::<Self>()))]
548///     async fn foo(&self, arg: usize) {}
549/// }
550/// ```
551///
552/// `const fn` cannot be instrumented, and will result in a compilation failure:
553///
554/// ```compile_fail
555/// # use tracing_attributes::instrument;
556/// #[instrument]
557/// const fn my_const_function() {}
558/// ```
559///
560/// [span]: https://docs.rs/tracing/latest/tracing/span/index.html
561/// [name]: https://docs.rs/tracing/latest/tracing/struct.Metadata.html#method.name
562/// [target]: https://docs.rs/tracing/latest/tracing/struct.Metadata.html#method.target
563/// [level]: https://docs.rs/tracing/latest/tracing/struct.Level.html
564/// [module path]: https://docs.rs/tracing/latest/tracing/struct.Metadata.html#method.module_path
565/// [`INFO`]: https://docs.rs/tracing/latest/tracing/struct.Level.html#associatedconstant.INFO
566/// [empty field]: https://docs.rs/tracing/latest/tracing/field/struct.Empty.html
567/// [field syntax]: https://docs.rs/tracing/latest/tracing/#recording-fields
568/// [`follows_from`]: https://docs.rs/tracing/latest/tracing/struct.Span.html#method.follows_from
569/// [`tracing`]: https://github.com/tokio-rs/tracing
570/// [`fmt::Debug`]: std::fmt::Debug
571/// [`Level`]: https://docs.rs/tracing/latest/tracing/struct.Level.html
572/// [`Level::TRACE`]: https://docs.rs/tracing/latest/tracing/struct.Level.html#associatedconstant.TRACE
573/// [`Level::ERROR`]: https://docs.rs/tracing/latest/tracing/struct.Level.html#associatedconstant.ERROR
574#[proc_macro_attribute]
575pub fn instrument(
576    args: proc_macro::TokenStream,
577    item: proc_macro::TokenStream,
578) -> proc_macro::TokenStream {
579    let args = syn::parse_macro_input!(args as attr::InstrumentArgs);
580    // Cloning a `TokenStream` is cheap since it's reference counted internally.
581    instrument_precise(args.clone(), item.clone())
582        .unwrap_or_else(|_err| instrument_speculative(args, item))
583}
584
585/// Instrument the function, without parsing the function body (instead using the raw tokens).
586fn instrument_speculative(
587    args: attr::InstrumentArgs,
588    item: proc_macro::TokenStream,
589) -> proc_macro::TokenStream {
590    let input = syn::parse_macro_input!(item as MaybeItemFn);
591    let instrumented_function_name = input.sig.ident.to_string();
592    expand::gen_function(
593        input.as_ref(),
594        args,
595        instrumented_function_name.as_str(),
596        None,
597    )
598    .into()
599}
600
601/// Instrument the function, by fully parsing the function body,
602/// which allows us to rewrite some statements related to async-like patterns.
603fn instrument_precise(
604    args: attr::InstrumentArgs,
605    item: proc_macro::TokenStream,
606) -> Result<proc_macro::TokenStream, syn::Error> {
607    let input = syn::parse::<ItemFn>(item)?;
608    let instrumented_function_name = input.sig.ident.to_string();
609
610    if input.sig.constness.is_some() {
611        return Ok(quote! {
612            compile_error!("the `#[instrument]` attribute may not be used with `const fn`s")
613        }
614        .into());
615    }
616
617    // check for async_trait-like patterns in the block, and instrument
618    // the future instead of the wrapper
619    if let Some(async_like) = expand::AsyncInfo::from_fn(&input) {
620        return async_like.gen_async(args, instrumented_function_name.as_str());
621    }
622
623    let input = MaybeItemFn::from(input);
624
625    Ok(expand::gen_function(
626        input.as_ref(),
627        args,
628        instrumented_function_name.as_str(),
629        None,
630    )
631    .into())
632}
633
634/// This is a more flexible/imprecise `ItemFn` type,
635/// which's block is just a `TokenStream` (it may contain invalid code).
636#[derive(Debug, Clone)]
637struct MaybeItemFn {
638    outer_attrs: Vec<Attribute>,
639    inner_attrs: Vec<Attribute>,
640    vis: Visibility,
641    sig: Signature,
642    brace_token: Brace,
643    block: TokenStream,
644}
645
646impl MaybeItemFn {
647    fn as_ref(&self) -> MaybeItemFnRef<'_, TokenStream> {
648        MaybeItemFnRef {
649            outer_attrs: &self.outer_attrs,
650            inner_attrs: &self.inner_attrs,
651            vis: &self.vis,
652            sig: &self.sig,
653            brace_token: &self.brace_token,
654            block: &self.block,
655        }
656    }
657}
658
659/// This parses a `TokenStream` into a `MaybeItemFn`
660/// (just like `ItemFn`, but skips parsing the body).
661impl Parse for MaybeItemFn {
662    fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
663        let outer_attrs = input.call(Attribute::parse_outer)?;
664        let vis: Visibility = input.parse()?;
665        let sig: Signature = input.parse()?;
666        let inner_attrs = input.call(Attribute::parse_inner)?;
667        let block;
668        let brace_token = syn::braced!(block in input);
669        let block: TokenStream = block.call(|buffer| buffer.parse())?;
670        Ok(Self {
671            outer_attrs,
672            inner_attrs,
673            vis,
674            sig,
675            brace_token,
676            block,
677        })
678    }
679}
680
681impl From<ItemFn> for MaybeItemFn {
682    fn from(
683        ItemFn {
684            attrs,
685            vis,
686            sig,
687            block,
688        }: ItemFn,
689    ) -> Self {
690        let (outer_attrs, inner_attrs) = attrs
691            .into_iter()
692            .partition(|attr| attr.style == syn::AttrStyle::Outer);
693        let mut block_tokens = TokenStream::new();
694        block_tokens.append_all(block.stmts);
695        Self {
696            outer_attrs,
697            inner_attrs,
698            vis,
699            sig,
700            brace_token: block.brace_token,
701            block: block_tokens,
702        }
703    }
704}
705
706/// A generic reference type for `MaybeItemFn`,
707/// that takes a generic block type `B` that implements `ToTokens` (eg. `TokenStream`, `Block`).
708#[derive(Debug, Clone)]
709struct MaybeItemFnRef<'a, B: ToTokens> {
710    outer_attrs: &'a Vec<Attribute>,
711    inner_attrs: &'a Vec<Attribute>,
712    vis: &'a Visibility,
713    sig: &'a Signature,
714    brace_token: &'a Brace,
715    block: &'a B,
716}