Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

attributes: downgrade unrecognized input errors to warnings #786

Merged
merged 7 commits into from
Jul 8, 2020
Merged
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 43 additions & 3 deletions tracing-attributes/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,7 @@ fn gen_body(
} = sig;

let err = args.err;
let warnings = args.warnings();

// generate the span's name
let span_name = args
Expand Down Expand Up @@ -430,6 +431,7 @@ fn gen_body(
#vis #constness #unsafety #asyncness #abi fn #ident<#gen_params>(#params) #return_type
#where_clause
{
#warnings
#body
}
)
Expand All @@ -443,6 +445,8 @@ struct InstrumentArgs {
skips: HashSet<Ident>,
fields: Option<Fields>,
err: bool,
/// Errors describing any unrecognized parse inputs that we skipped.
parse_warnings: Vec<syn::Error>,
}

impl InstrumentArgs {
Expand Down Expand Up @@ -478,7 +482,8 @@ impl InstrumentArgs {
Some(Level::Path(ref pat)) => quote!(#pat),
Some(lit) => quote! {
compile_error!(
"unknown verbosity level, expected one of \"trace\", \
"unknown verbosity level, expected one of \"trace\",
return Err( \
\"debug\", \"info\", \"warn\", or \"error\", or a number 1-5"
)
},
Expand All @@ -493,6 +498,34 @@ impl InstrumentArgs {
quote!(module_path!())
}
}

/// Generate "deprecation" warnings for any unrecognized attribute inputs
/// that we skipped.
///
/// For backwards compatibility, we need to emit compiler warnings rather
/// than errors for unrecognized inputs. Generating a fake deprecation is
/// the only way to do this on stable Rust right now.
fn warnings(&self) -> impl ToTokens {
let warnings = self.parse_warnings.iter().map(|err| {
let msg = err.to_string();
let msg = LitStr::new(&msg, err.span());
// TODO(eliza): This is a bit of a hack, but it's just about the
// only way to emit warnings from a proc macro on stable Rust.
// Eventually, when the `proc_macro::Diagnostic` API stabilizes, we
// should definitely use that instead.
quote_spanned! {err.span()=>
#[warn(deprecated)]
{
#[deprecated(since = "not actually deprecated", note = #msg)]
const TRACING_INSTRUMENT_UNRECOGNIZED_INPUT: () = ();
let _ = TRACING_INSTRUMENT_UNRECOGNIZED_INPUT;
}
}
});
quote! {
{ #(#warnings)* }
}
}
}

impl Parse for InstrumentArgs {
Expand Down Expand Up @@ -542,7 +575,14 @@ impl Parse for InstrumentArgs {
} else if lookahead.peek(Token![,]) {
let _ = input.parse::<Token![,]>()?;
} else {
return Err(lookahead.error());
// We found a token that we didn't expect!
// We want to emit warnings for these, rather than errors, so
// we'll add it to the list of unrecognized inputs we've seen so
// far and keep going.
args.parse_warnings.push(lookahead.error());
// Parse the unrecognized token tree to advance the parse
// stream, and throw it away so we can keep parsing.
let _ = input.parse::<proc_macro2::TokenTree>();
}
}
Ok(args)
Expand Down Expand Up @@ -742,7 +782,7 @@ mod kw {
// Get the name of the inner function we need to hook, if the function
// was generated by async-trait.
// When we are given a function generated by async-trait, that function
// is only a "temporary" one that returns a pinned future, and it is
// is only a "temporary" one that returns a pinned future,foo and it is
hawkw marked this conversation as resolved.
Show resolved Hide resolved
// that pinned future that needs to be instrumented, otherwise we will
// only collect information on the moment the future was "built",
// and not its true span of execution.
Expand Down