From 191cdc59a2627b192ce4350b8301026db4765f4c Mon Sep 17 00:00:00 2001 From: Andrew Pollack Date: Sat, 31 Dec 2022 11:59:44 -0800 Subject: [PATCH] attributes: add compile error on const fn instrumentation (#2418) ## Motivation The `#[instrument]` macro cannot be used on `const fn`s, because the generated code will perform runtime tracing behavior. However, when adding the attribute to a `const fn`, the compiler errors generated currently are somewhat unclear (see #2414). It would be better if we generated a less verbose error that simply states that `#[instrument]` is not supported on `const fn`s. ## Solution This branch changes the `#[instrument]` macro to detect when the annotated function is a `const fn`, and emit a simpler, more descritpive error message. The new error simply states that the `#[instrument]` attribute cannot be used on `const fn`s, and should be much less confusing to the user. Fixes #2414 --- tracing-attributes/src/lib.rs | 17 ++++++++++++++++- tracing-attributes/tests/ui.rs | 7 +++++++ tracing-attributes/tests/ui/const_instrument.rs | 8 ++++++++ .../tests/ui/const_instrument.stderr | 15 +++++++++++++++ 4 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 tracing-attributes/tests/ui/const_instrument.rs create mode 100644 tracing-attributes/tests/ui/const_instrument.stderr diff --git a/tracing-attributes/src/lib.rs b/tracing-attributes/src/lib.rs index dd692512ff..b07415ef62 100644 --- a/tracing-attributes/src/lib.rs +++ b/tracing-attributes/src/lib.rs @@ -82,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}; @@ -535,6 +535,14 @@ mod expand; /// } /// ``` /// +/// `const fn` cannot be instrumented, and will result in a compilation failure: +/// +/// ```compile_fail +/// # use tracing_attributes::instrument; +/// #[instrument] +/// const fn my_const_function() {} +/// ``` +/// /// [span]: https://docs.rs/tracing/latest/tracing/span/index.html /// [name]: https://docs.rs/tracing/latest/tracing/struct.Metadata.html#method.name /// [target]: https://docs.rs/tracing/latest/tracing/struct.Metadata.html#method.target @@ -585,6 +593,13 @@ fn instrument_precise( let input = syn::parse::(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) { diff --git a/tracing-attributes/tests/ui.rs b/tracing-attributes/tests/ui.rs index f11cc019eb..73d7fdcef8 100644 --- a/tracing-attributes/tests/ui.rs +++ b/tracing-attributes/tests/ui.rs @@ -5,3 +5,10 @@ fn async_instrument() { let t = trybuild::TestCases::new(); t.compile_fail("tests/ui/async_instrument.rs"); } + +#[rustversion::stable] +#[test] +fn const_instrument() { + let t = trybuild::TestCases::new(); + t.compile_fail("tests/ui/const_instrument.rs"); +} diff --git a/tracing-attributes/tests/ui/const_instrument.rs b/tracing-attributes/tests/ui/const_instrument.rs new file mode 100644 index 0000000000..a251e8f66b --- /dev/null +++ b/tracing-attributes/tests/ui/const_instrument.rs @@ -0,0 +1,8 @@ +#![allow(unreachable_code)] + +#[tracing::instrument] +const fn unit() { + "" +} + +fn main() {} diff --git a/tracing-attributes/tests/ui/const_instrument.stderr b/tracing-attributes/tests/ui/const_instrument.stderr new file mode 100644 index 0000000000..e76d4acad9 --- /dev/null +++ b/tracing-attributes/tests/ui/const_instrument.stderr @@ -0,0 +1,15 @@ +error: macros that expand to items must be delimited with braces or followed by a semicolon + --> tests/ui/const_instrument.rs:3:1 + | +3 | #[tracing::instrument] + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the attribute macro `tracing::instrument` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: the `#[instrument]` attribute may not be used with `const fn`s + --> tests/ui/const_instrument.rs:3:1 + | +3 | #[tracing::instrument] + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the attribute macro `tracing::instrument` (in Nightly builds, run with -Z macro-backtrace for more info)