From 70ee0c96fc29c57f64a6ccfeb66cccf6fac951f7 Mon Sep 17 00:00:00 2001 From: David Wood Date: Thu, 31 Mar 2022 09:02:31 +0100 Subject: [PATCH] macros: add `#[no_arg]` to skip `set_arg` call A call to `set_arg` is generated for every field of a `SessionDiagnostic` struct without attributes, but not all types support being an argument, so `#[no_arg]` is introduced to skip these fields. Signed-off-by: David Wood --- compiler/rustc_macros/src/lib.rs | 1 + .../rustc_macros/src/session_diagnostic.rs | 12 ++++++++++- src/test/ui-fulldeps/session-derive-errors.rs | 20 +++++++++++++++++++ .../ui-fulldeps/session-derive-errors.stderr | 14 ++++++++++++- 4 files changed, 45 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index b571fdb4ae2..67b56d2e9db 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs @@ -67,6 +67,7 @@ decl_derive!( warning, error, // field attributes + skip_arg, primary_span, label, suggestion, diff --git a/compiler/rustc_macros/src/session_diagnostic.rs b/compiler/rustc_macros/src/session_diagnostic.rs index 73cd840f0eb..fec9a820d0f 100644 --- a/compiler/rustc_macros/src/session_diagnostic.rs +++ b/compiler/rustc_macros/src/session_diagnostic.rs @@ -216,7 +216,12 @@ impl<'a> SessionDiagnosticDerive<'a> { if field.attrs.is_empty() { let diag = &builder.diag; let ident = field_binding.ast().ident.as_ref().unwrap(); - quote! { #diag.set_arg(stringify!(#ident), #field_binding.into_diagnostic_arg()); } + quote! { + #diag.set_arg( + stringify!(#ident), + #field_binding.into_diagnostic_arg() + ); + } } else { quote! {} } @@ -566,6 +571,11 @@ impl<'a> SessionDiagnosticDeriveBuilder<'a> { let meta = attr.parse_meta()?; match meta { syn::Meta::Path(_) => match name { + "skip_arg" => { + // Don't need to do anything - by virtue of the attribute existing, the + // `set_arg` call will not be generated. + Ok(quote! {}) + } "primary_span" => { if type_matches_path(&info.ty, &["rustc_span", "Span"]) { return Ok(quote! { diff --git a/src/test/ui-fulldeps/session-derive-errors.rs b/src/test/ui-fulldeps/session-derive-errors.rs index 422f3894991..96d78c2d00e 100644 --- a/src/test/ui-fulldeps/session-derive-errors.rs +++ b/src/test/ui-fulldeps/session-derive-errors.rs @@ -311,3 +311,23 @@ struct ErrorWithLifetime<'a> { span: Span, name: &'a str, } + +#[derive(SessionDiagnostic)] +//~^ ERROR no method named `into_diagnostic_arg` found for struct `Hello` in the current scope +#[error(code = "E0123", slug = "foo")] +struct ArgFieldWithoutSkip { + #[primary_span] + span: Span, + other: Hello, +} + +#[derive(SessionDiagnostic)] +#[error(code = "E0123", slug = "foo")] +struct ArgFieldWithSkip { + #[primary_span] + span: Span, + // `Hello` does not implement `IntoDiagnosticArg` so this would result in an error if + // not for `#[skip_arg]`. + #[skip_arg] + other: Hello, +} diff --git a/src/test/ui-fulldeps/session-derive-errors.stderr b/src/test/ui-fulldeps/session-derive-errors.stderr index 78ed255523f..21bf8e060ba 100644 --- a/src/test/ui-fulldeps/session-derive-errors.stderr +++ b/src/test/ui-fulldeps/session-derive-errors.stderr @@ -274,5 +274,17 @@ error: cannot find attribute `nonsense` in this scope LL | #[nonsense] | ^^^^^^^^ -error: aborting due to 34 previous errors +error[E0599]: no method named `into_diagnostic_arg` found for struct `Hello` in the current scope + --> $DIR/session-derive-errors.rs:315:10 + | +LL | struct Hello {} + | ------------ method `into_diagnostic_arg` not found for this +... +LL | #[derive(SessionDiagnostic)] + | ^^^^^^^^^^^^^^^^^ method not found in `Hello` + | + = note: this error originates in the derive macro `SessionDiagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) +error: aborting due to 35 previous errors + +For more information about this error, try `rustc --explain E0599`.