summaryrefslogtreecommitdiffstats
path: root/vendor/tracing-attributes/src
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:31 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:31 +0000
commitdc0db358abe19481e475e10c32149b53370f1a1c (patch)
treeab8ce99c4b255ce46f99ef402c27916055b899ee /vendor/tracing-attributes/src
parentReleasing progress-linux version 1.71.1+dfsg1-2~progress7.99u1. (diff)
downloadrustc-dc0db358abe19481e475e10c32149b53370f1a1c.tar.xz
rustc-dc0db358abe19481e475e10c32149b53370f1a1c.zip
Merging upstream version 1.72.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/tracing-attributes/src')
-rw-r--r--vendor/tracing-attributes/src/attr.rs190
-rw-r--r--vendor/tracing-attributes/src/expand.rs53
-rw-r--r--vendor/tracing-attributes/src/lib.rs104
3 files changed, 211 insertions, 136 deletions
diff --git a/vendor/tracing-attributes/src/attr.rs b/vendor/tracing-attributes/src/attr.rs
index ff875e179..f5ad40939 100644
--- a/vendor/tracing-attributes/src/attr.rs
+++ b/vendor/tracing-attributes/src/attr.rs
@@ -6,6 +6,14 @@ use quote::{quote, quote_spanned, ToTokens};
use syn::ext::IdentExt as _;
use syn::parse::{Parse, ParseStream};
+/// Arguments to `#[instrument(err(...))]` and `#[instrument(ret(...))]` which describe how the
+/// return value event should be emitted.
+#[derive(Clone, Default, Debug)]
+pub(crate) struct EventArgs {
+ level: Option<Level>,
+ pub(crate) mode: FormatMode,
+}
+
#[derive(Clone, Default, Debug)]
pub(crate) struct InstrumentArgs {
level: Option<Level>,
@@ -16,51 +24,15 @@ pub(crate) struct InstrumentArgs {
pub(crate) skips: HashSet<Ident>,
pub(crate) skip_all: bool,
pub(crate) fields: Option<Fields>,
- pub(crate) err_mode: Option<FormatMode>,
- pub(crate) ret_mode: Option<FormatMode>,
+ pub(crate) err_args: Option<EventArgs>,
+ pub(crate) ret_args: Option<EventArgs>,
/// Errors describing any unrecognized parse inputs that we skipped.
parse_warnings: Vec<syn::Error>,
}
impl InstrumentArgs {
- pub(crate) fn level(&self) -> impl ToTokens {
- fn is_level(lit: &LitInt, expected: u64) -> bool {
- match lit.base10_parse::<u64>() {
- Ok(value) => value == expected,
- Err(_) => false,
- }
- }
-
- match &self.level {
- Some(Level::Str(ref lit)) if lit.value().eq_ignore_ascii_case("trace") => {
- quote!(tracing::Level::TRACE)
- }
- Some(Level::Str(ref lit)) if lit.value().eq_ignore_ascii_case("debug") => {
- quote!(tracing::Level::DEBUG)
- }
- Some(Level::Str(ref lit)) if lit.value().eq_ignore_ascii_case("info") => {
- quote!(tracing::Level::INFO)
- }
- Some(Level::Str(ref lit)) if lit.value().eq_ignore_ascii_case("warn") => {
- quote!(tracing::Level::WARN)
- }
- Some(Level::Str(ref lit)) if lit.value().eq_ignore_ascii_case("error") => {
- quote!(tracing::Level::ERROR)
- }
- Some(Level::Int(ref lit)) if is_level(lit, 1) => quote!(tracing::Level::TRACE),
- Some(Level::Int(ref lit)) if is_level(lit, 2) => quote!(tracing::Level::DEBUG),
- Some(Level::Int(ref lit)) if is_level(lit, 3) => quote!(tracing::Level::INFO),
- Some(Level::Int(ref lit)) if is_level(lit, 4) => quote!(tracing::Level::WARN),
- Some(Level::Int(ref lit)) if is_level(lit, 5) => quote!(tracing::Level::ERROR),
- Some(Level::Path(ref pat)) => quote!(#pat),
- Some(_) => quote! {
- compile_error!(
- "unknown verbosity level, expected one of \"trace\", \
- \"debug\", \"info\", \"warn\", or \"error\", or a number 1-5"
- )
- },
- None => quote!(tracing::Level::INFO),
- }
+ pub(crate) fn level(&self) -> Level {
+ self.level.clone().unwrap_or(Level::Info)
}
pub(crate) fn target(&self) -> impl ToTokens {
@@ -167,12 +139,12 @@ impl Parse for InstrumentArgs {
args.fields = Some(input.parse()?);
} else if lookahead.peek(kw::err) {
let _ = input.parse::<kw::err>();
- let mode = FormatMode::parse(input)?;
- args.err_mode = Some(mode);
+ let err_args = EventArgs::parse(input)?;
+ args.err_args = Some(err_args);
} else if lookahead.peek(kw::ret) {
let _ = input.parse::<kw::ret>()?;
- let mode = FormatMode::parse(input)?;
- args.ret_mode = Some(mode);
+ let ret_args = EventArgs::parse(input)?;
+ args.ret_args = Some(ret_args);
} else if lookahead.peek(Token![,]) {
let _ = input.parse::<Token![,]>()?;
} else {
@@ -190,6 +162,55 @@ impl Parse for InstrumentArgs {
}
}
+impl EventArgs {
+ pub(crate) fn level(&self, default: Level) -> Level {
+ self.level.clone().unwrap_or(default)
+ }
+}
+
+impl Parse for EventArgs {
+ fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
+ if !input.peek(syn::token::Paren) {
+ return Ok(Self::default());
+ }
+ let content;
+ let _ = syn::parenthesized!(content in input);
+ let mut result = Self::default();
+ let mut parse_one_arg =
+ || {
+ let lookahead = content.lookahead1();
+ if lookahead.peek(kw::level) {
+ if result.level.is_some() {
+ return Err(content.error("expected only a single `level` argument"));
+ }
+ result.level = Some(content.parse()?);
+ } else if result.mode != FormatMode::default() {
+ return Err(content.error("expected only a single format argument"));
+ } else if let Some(ident) = content.parse::<Option<Ident>>()? {
+ match ident.to_string().as_str() {
+ "Debug" => result.mode = FormatMode::Debug,
+ "Display" => result.mode = FormatMode::Display,
+ _ => return Err(syn::Error::new(
+ ident.span(),
+ "unknown event formatting mode, expected either `Debug` or `Display`",
+ )),
+ }
+ }
+ Ok(())
+ };
+ parse_one_arg()?;
+ if !content.is_empty() {
+ if content.lookahead1().peek(Token![,]) {
+ let _ = content.parse::<Token![,]>()?;
+ parse_one_arg()?;
+ } else {
+ return Err(content.error("expected `,` or `)`"));
+ }
+ }
+ Ok(result)
+ }
+}
+
struct StrArg<T> {
value: LitStr,
_p: std::marker::PhantomData<T>,
@@ -231,7 +252,7 @@ impl Parse for Skips {
let _ = input.parse::<kw::skip>();
let content;
let _ = syn::parenthesized!(content in input);
- let names: Punctuated<Ident, Token![,]> = content.parse_terminated(Ident::parse_any)?;
+ let names = content.parse_terminated(Ident::parse_any, Token![,])?;
let mut skips = HashSet::new();
for name in names {
if skips.contains(&name) {
@@ -260,27 +281,6 @@ impl Default for FormatMode {
}
}
-impl Parse for FormatMode {
- fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
- if !input.peek(syn::token::Paren) {
- return Ok(FormatMode::default());
- }
- let content;
- let _ = syn::parenthesized!(content in input);
- let maybe_mode: Option<Ident> = content.parse()?;
- maybe_mode.map_or(Ok(FormatMode::default()), |ident| {
- match ident.to_string().as_str() {
- "Debug" => Ok(FormatMode::Debug),
- "Display" => Ok(FormatMode::Display),
- _ => Err(syn::Error::new(
- ident.span(),
- "unknown error mode, must be Debug or Display",
- )),
- }
- })
- }
-}
-
#[derive(Clone, Debug)]
pub(crate) struct Fields(pub(crate) Punctuated<Field, Token![,]>);
@@ -303,7 +303,7 @@ impl Parse for Fields {
let _ = input.parse::<kw::fields>();
let content;
let _ = syn::parenthesized!(content in input);
- let fields: Punctuated<_, Token![,]> = content.parse_terminated(Field::parse)?;
+ let fields = content.parse_terminated(Field::parse, Token![,])?;
Ok(Self(fields))
}
}
@@ -348,7 +348,7 @@ impl ToTokens for Field {
let name = &self.name;
let kind = &self.kind;
tokens.extend(quote! {
- #name = #kind#value
+ #name = #kind #value
})
} else if self.kind == FieldKind::Value {
// XXX(eliza): I don't like that fields without values produce
@@ -376,9 +376,12 @@ impl ToTokens for FieldKind {
}
#[derive(Clone, Debug)]
-enum Level {
- Str(LitStr),
- Int(LitInt),
+pub(crate) enum Level {
+ Trace,
+ Debug,
+ Info,
+ Warn,
+ Error,
Path(Path),
}
@@ -388,9 +391,37 @@ impl Parse for Level {
let _ = input.parse::<Token![=]>()?;
let lookahead = input.lookahead1();
if lookahead.peek(LitStr) {
- Ok(Self::Str(input.parse()?))
+ let str: LitStr = input.parse()?;
+ match str.value() {
+ s if s.eq_ignore_ascii_case("trace") => Ok(Level::Trace),
+ s if s.eq_ignore_ascii_case("debug") => Ok(Level::Debug),
+ s if s.eq_ignore_ascii_case("info") => Ok(Level::Info),
+ s if s.eq_ignore_ascii_case("warn") => Ok(Level::Warn),
+ s if s.eq_ignore_ascii_case("error") => Ok(Level::Error),
+ _ => Err(input.error(
+ "unknown verbosity level, expected one of \"trace\", \
+ \"debug\", \"info\", \"warn\", or \"error\", or a number 1-5",
+ )),
+ }
} else if lookahead.peek(LitInt) {
- Ok(Self::Int(input.parse()?))
+ fn is_level(lit: &LitInt, expected: u64) -> bool {
+ match lit.base10_parse::<u64>() {
+ Ok(value) => value == expected,
+ Err(_) => false,
+ }
+ }
+ let int: LitInt = input.parse()?;
+ match &int {
+ i if is_level(i, 1) => Ok(Level::Trace),
+ i if is_level(i, 2) => Ok(Level::Debug),
+ i if is_level(i, 3) => Ok(Level::Info),
+ i if is_level(i, 4) => Ok(Level::Warn),
+ i if is_level(i, 5) => Ok(Level::Error),
+ _ => Err(input.error(
+ "unknown verbosity level, expected one of \"trace\", \
+ \"debug\", \"info\", \"warn\", or \"error\", or a number 1-5",
+ )),
+ }
} else if lookahead.peek(Ident) {
Ok(Self::Path(input.parse()?))
} else {
@@ -399,6 +430,19 @@ impl Parse for Level {
}
}
+impl ToTokens for Level {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ match self {
+ Level::Trace => tokens.extend(quote!(tracing::Level::TRACE)),
+ Level::Debug => tokens.extend(quote!(tracing::Level::DEBUG)),
+ Level::Info => tokens.extend(quote!(tracing::Level::INFO)),
+ Level::Warn => tokens.extend(quote!(tracing::Level::WARN)),
+ Level::Error => tokens.extend(quote!(tracing::Level::ERROR)),
+ Level::Path(ref pat) => tokens.extend(quote!(#pat)),
+ }
+ }
+}
+
mod kw {
syn::custom_keyword!(fields);
syn::custom_keyword!(skip);
diff --git a/vendor/tracing-attributes/src/expand.rs b/vendor/tracing-attributes/src/expand.rs
index 7005b4423..eb7be8f47 100644
--- a/vendor/tracing-attributes/src/expand.rs
+++ b/vendor/tracing-attributes/src/expand.rs
@@ -10,7 +10,7 @@ use syn::{
};
use crate::{
- attr::{Field, Fields, FormatMode, InstrumentArgs},
+ attr::{Field, Fields, FormatMode, InstrumentArgs, Level},
MaybeItemFn, MaybeItemFnRef,
};
@@ -64,7 +64,10 @@ pub(crate) fn gen_function<'a, B: ToTokens + 'a>(
// unreachable, but does affect inference, so it needs to be written
// exactly that way for it to do its magic.
let fake_return_edge = quote_spanned! {return_span=>
- #[allow(unreachable_code, clippy::diverging_sub_expression, clippy::let_unit_value)]
+ #[allow(
+ unknown_lints, unreachable_code, clippy::diverging_sub_expression,
+ clippy::let_unit_value, clippy::unreachable, clippy::let_with_type_underscore
+ )]
if false {
let __tracing_attr_fake_return: #return_type =
unreachable!("this is just for type inference, and is unreachable code");
@@ -116,7 +119,8 @@ fn gen_block<B: ToTokens>(
.map(|name| quote!(#name))
.unwrap_or_else(|| quote!(#instrumented_function_name));
- let level = args.level();
+ let args_level = args.level();
+ let level = args_level.clone();
let follows_from = args.follows_from.iter();
let follows_from = quote! {
@@ -134,7 +138,7 @@ fn gen_block<B: ToTokens>(
.into_iter()
.flat_map(|param| match param {
FnArg::Typed(PatType { pat, ty, .. }) => {
- param_names(*pat, RecordType::parse_from_ty(&*ty))
+ param_names(*pat, RecordType::parse_from_ty(&ty))
}
FnArg::Receiver(_) => Box::new(iter::once((
Ident::new("self", param.span()),
@@ -232,21 +236,33 @@ fn gen_block<B: ToTokens>(
let target = args.target();
- let err_event = match args.err_mode {
- Some(FormatMode::Default) | Some(FormatMode::Display) => {
- Some(quote!(tracing::error!(target: #target, error = %e)))
+ let err_event = match args.err_args {
+ Some(event_args) => {
+ let level_tokens = event_args.level(Level::Error);
+ match event_args.mode {
+ FormatMode::Default | FormatMode::Display => Some(quote!(
+ tracing::event!(target: #target, #level_tokens, error = %e)
+ )),
+ FormatMode::Debug => Some(quote!(
+ tracing::event!(target: #target, #level_tokens, error = ?e)
+ )),
+ }
}
- Some(FormatMode::Debug) => Some(quote!(tracing::error!(target: #target, error = ?e))),
_ => None,
};
- let ret_event = match args.ret_mode {
- Some(FormatMode::Display) => Some(quote!(
- tracing::event!(target: #target, #level, return = %x)
- )),
- Some(FormatMode::Default) | Some(FormatMode::Debug) => Some(quote!(
- tracing::event!(target: #target, #level, return = ?x)
- )),
+ let ret_event = match args.ret_args {
+ Some(event_args) => {
+ let level_tokens = event_args.level(args_level);
+ match event_args.mode {
+ FormatMode::Display => Some(quote!(
+ tracing::event!(target: #target, #level_tokens, return = %x)
+ )),
+ FormatMode::Default | FormatMode::Debug => Some(quote!(
+ tracing::event!(target: #target, #level_tokens, return = ?x)
+ )),
+ }
+ }
_ => None,
};
@@ -464,10 +480,7 @@ fn param_names(pat: Pat, record_type: RecordType) -> Box<dyn Iterator<Item = (Id
.into_iter()
.flat_map(|p| param_names(p, RecordType::Debug)),
),
- Pat::TupleStruct(PatTupleStruct {
- pat: PatTuple { elems, .. },
- ..
- }) => Box::new(
+ Pat::TupleStruct(PatTupleStruct { elems, .. }) => Box::new(
elems
.into_iter()
.flat_map(|p| param_names(p, RecordType::Debug)),
@@ -551,7 +564,7 @@ impl<'block> AsyncInfo<'block> {
// last expression of the block: it determines the return value of the
// block, this is quite likely a `Box::pin` statement or an async block
let (last_expr_stmt, last_expr) = block.stmts.iter().rev().find_map(|stmt| {
- if let Stmt::Expr(expr) = stmt {
+ if let Stmt::Expr(expr, _semi) = stmt {
Some((stmt, expr))
} else {
None
diff --git a/vendor/tracing-attributes/src/lib.rs b/vendor/tracing-attributes/src/lib.rs
index f5974e4e5..c7477946d 100644
--- a/vendor/tracing-attributes/src/lib.rs
+++ b/vendor/tracing-attributes/src/lib.rs
@@ -6,17 +6,17 @@
//!
//! Note that this macro is also re-exported by the main `tracing` crate.
//!
-//! *Compiler support: [requires `rustc` 1.49+][msrv]*
+//! *Compiler support: [requires `rustc` 1.56+][msrv]*
//!
//! [msrv]: #supported-rust-versions
//!
//! ## Usage
//!
-//! First, add this to your `Cargo.toml`:
+//! In the `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
-//! tracing-attributes = "0.1.23"
+//! tracing-attributes = "0.1.24"
//! ```
//!
//! The [`#[instrument]`][instrument] attribute can now be added to a function
@@ -24,7 +24,7 @@
//! called. For example:
//!
//! ```
-//! use tracing_attributes::instrument;
+//! use tracing::instrument;
//!
//! #[instrument]
//! pub fn my_function(my_arg: usize) {
@@ -41,18 +41,17 @@
//! ## Supported Rust Versions
//!
//! Tracing is built against the latest stable release. The minimum supported
-//! version is 1.49. The current Tracing version is not guaranteed to build on
+//! version is 1.56. The current Tracing version is not guaranteed to build on
//! Rust versions earlier than the minimum supported version.
//!
//! Tracing follows the same compiler support policies as the rest of the Tokio
//! project. The current stable Rust compiler and the three most recent minor
//! versions before it will always be supported. For example, if the current
-//! stable compiler version is 1.45, the minimum supported version will not be
-//! increased past 1.42, three minor versions prior. Increasing the minimum
+//! stable compiler version is 1.69, the minimum supported version will not be
+//! increased past 1.66, three minor versions prior. Increasing the minimum
//! supported compiler version is not considered a semver breaking change as
//! long as doing so complies with this policy.
//!
-#![doc(html_root_url = "https://docs.rs/tracing-attributes/0.1.23")]
#![doc(
html_logo_url = "https://raw.githubusercontent.com/tokio-rs/tracing/master/assets/logo-type.png",
issue_tracker_base_url = "https://github.com/tokio-rs/tracing/issues/"
@@ -64,7 +63,6 @@
rust_2018_idioms,
unreachable_pub,
bad_style,
- const_err,
dead_code,
improper_ctypes,
non_shorthand_field_patterns,
@@ -84,7 +82,7 @@
extern crate proc_macro;
use proc_macro2::TokenStream;
-use quote::ToTokens;
+use quote::{quote, ToTokens};
use syn::parse::{Parse, ParseStream};
use syn::{Attribute, ItemFn, Signature, Visibility};
@@ -205,16 +203,17 @@ mod expand;
///
/// # Adding Fields
///
-/// Additional fields (key-value pairs with arbitrary data) may be added to the
-/// generated span using the `fields` argument on the `#[instrument]` macro. Any
+/// Additional fields (key-value pairs with arbitrary data) can be passed to
+/// to the generated span through the `fields` argument on the
+/// `#[instrument]` macro. Strings, integers or boolean literals are accepted values
+/// for each field. The name of the field must be a single valid Rust
+/// identifier, nested (dotted) field names are not supported. Any
/// Rust expression can be used as a field value in this manner. These
/// expressions will be evaluated at the beginning of the function's body, so
/// arguments to the function may be used in these expressions. Field names may
/// also be specified *without* values. Doing so will result in an [empty field]
/// whose value may be recorded later within the function body.
///
-/// This supports the same [field syntax] as the `span!` and `event!` macros.
-///
/// Note that overlap between the names of fields and (non-skipped) arguments
/// will result in a compile error.
///
@@ -324,11 +323,15 @@ mod expand;
/// Setting the level for the generated span:
/// ```
/// # use tracing_attributes::instrument;
-/// #[instrument(level = "debug")]
+/// # use tracing::Level;
+/// #[instrument(level = Level::DEBUG)]
/// pub fn my_function() {
/// // ...
/// }
/// ```
+/// Levels can be specified either with [`Level`] constants, literal strings
+/// (e.g., `"debug"`, `"info"`) or numerically (1—5, corresponding to [`Level::TRACE`]—[`Level::ERROR`]).
+///
/// Overriding the generated span's name:
/// ```
/// # use tracing_attributes::instrument;
@@ -399,7 +402,7 @@ mod expand;
/// }
/// ```
///
-/// To add an additional context to the span, pass key-value pairs to `fields`:
+/// To add additional context to the span, pass key-value pairs to `fields`:
///
/// ```
/// # use tracing_attributes::instrument;
@@ -423,6 +426,17 @@ mod expand;
/// By default, this will be [`INFO`], but if the level is overridden, the event will be at the same
/// level.
///
+/// It's also possible to override the level for the `ret` event independently:
+///
+/// ```
+/// # use tracing_attributes::instrument;
+/// # use tracing::Level;
+/// #[instrument(ret(level = Level::WARN))]
+/// fn my_function() -> i32 {
+/// 42
+/// }
+/// ```
+///
/// **Note**: if the function returns a `Result<T, E>`, `ret` will record returned values if and
/// only if the function returns [`Result::Ok`].
///
@@ -438,8 +452,8 @@ mod expand;
/// }
/// ```
///
-/// If the function returns a `Result<T, E>` and `E` implements `std::fmt::Display`, you can add
-/// `err` or `err(Display)` to emit error events when the function returns `Err`:
+/// If the function returns a `Result<T, E>` and `E` implements `std::fmt::Display`, adding
+/// `err` or `err(Display)` will emit error events when the function returns `Err`:
///
/// ```
/// # use tracing_attributes::instrument;
@@ -449,9 +463,22 @@ mod expand;
/// }
/// ```
///
+/// The level of the error value event defaults to `ERROR`.
+///
+/// Similarly, overriding the level of the `err` event :
+///
+/// ```
+/// # use tracing_attributes::instrument;
+/// # use tracing::Level;
+/// #[instrument(err(level = Level::INFO))]
+/// fn my_function(arg: usize) -> Result<(), std::io::Error> {
+/// Ok(())
+/// }
+/// ```
+///
/// By default, error values will be recorded using their `std::fmt::Display` implementations.
/// If an error implements `std::fmt::Debug`, it can be recorded using its `Debug` implementation
-/// instead, by writing `err(Debug)`:
+/// instead by writing `err(Debug)`:
///
/// ```
/// # use tracing_attributes::instrument;
@@ -510,32 +537,13 @@ mod expand;
/// }
/// ```
///
-/// Note than on `async-trait` <= 0.1.43, references to the `Self`
-/// type inside the `fields` argument were only allowed when the instrumented
-/// function is a method (i.e., the function receives `self` as an argument).
-/// For example, this *used to not work* because the instrument function
-/// didn't receive `self`:
-/// ```
-/// # use tracing::instrument;
-/// use async_trait::async_trait;
+/// `const fn` cannot be instrumented, and will result in a compilation failure:
///
-/// #[async_trait]
-/// pub trait Bar {
-/// async fn bar();
-/// }
-///
-/// #[derive(Debug)]
-/// struct BarImpl(usize);
-///
-/// #[async_trait]
-/// impl Bar for BarImpl {
-/// #[instrument(fields(tmp = std::any::type_name::<Self>()))]
-/// async fn bar() {}
-/// }
+/// ```compile_fail
+/// # use tracing_attributes::instrument;
+/// #[instrument]
+/// const fn my_const_function() {}
/// ```
-/// Instead, you should manually rewrite any `Self` types as the type for
-/// which you implement the trait: `#[instrument(fields(tmp = std::any::type_name::<Bar>()))]`
-/// (or maybe you can just bump `async-trait`).
///
/// [span]: https://docs.rs/tracing/latest/tracing/span/index.html
/// [name]: https://docs.rs/tracing/latest/tracing/struct.Metadata.html#method.name
@@ -548,6 +556,9 @@ mod expand;
/// [`follows_from`]: https://docs.rs/tracing/latest/tracing/struct.Span.html#method.follows_from
/// [`tracing`]: https://github.com/tokio-rs/tracing
/// [`fmt::Debug`]: std::fmt::Debug
+/// [`Level`]: https://docs.rs/tracing/latest/tracing/struct.Level.html
+/// [`Level::TRACE`]: https://docs.rs/tracing/latest/tracing/struct.Level.html#associatedconstant.TRACE
+/// [`Level::ERROR`]: https://docs.rs/tracing/latest/tracing/struct.Level.html#associatedconstant.ERROR
#[proc_macro_attribute]
pub fn instrument(
args: proc_macro::TokenStream,
@@ -584,6 +595,13 @@ fn instrument_precise(
let input = syn::parse::<ItemFn>(item)?;
let instrumented_function_name = input.sig.ident.to_string();
+ if input.sig.constness.is_some() {
+ return Ok(quote! {
+ compile_error!("the `#[instrument]` attribute may not be used with `const fn`s")
+ }
+ .into());
+ }
+
// check for async_trait-like patterns in the block, and instrument
// the future instead of the wrapper
if let Some(async_like) = expand::AsyncInfo::from_fn(&input) {