Skip to content

Commit

Permalink
Make spans a bit better
Browse files Browse the repository at this point in the history
  • Loading branch information
compiler-errors committed May 8, 2023
1 parent 2b9279f commit a156bd7
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 46 deletions.
9 changes: 5 additions & 4 deletions compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::diagnostics::utils::{
FieldInnerTy, FieldMap, HasFieldMap, SetOnce, SpannedOption, SubdiagnosticKind,
};
use proc_macro2::{Ident, Span, TokenStream};
use quote::{format_ident, quote};
use quote::{format_ident, quote, quote_spanned};
use syn::Token;
use syn::{parse_quote, spanned::Spanned, Attribute, Meta, Path, Type};
use synstructure::{BindingInfo, Structure, VariantInfo};
Expand Down Expand Up @@ -251,7 +251,8 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
let diag = &self.parent.diag;

let field = binding_info.ast();
let field_binding = &binding_info.binding;
let mut field_binding = binding_info.binding.clone();
field_binding.set_span(field.ty.span());

let ident = field.ident.as_ref().unwrap();
let ident = format_ident!("{}", ident); // strip `r#` prefix, if present
Expand Down Expand Up @@ -284,9 +285,9 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
name == "primary_span" && matches!(inner_ty, FieldInnerTy::Vec(_));
let (binding, needs_destructure) = if needs_clone {
// `primary_span` can accept a `Vec<Span>` so don't destructure that.
(quote! { #field_binding.clone() }, false)
(quote_spanned! {inner_ty.span()=> #field_binding.clone() }, false)
} else {
(quote! { #field_binding }, true)
(quote_spanned! {inner_ty.span()=> #field_binding }, true)
};

let generated_code = self
Expand Down
21 changes: 12 additions & 9 deletions compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,18 +209,20 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
}

/// Generates the code for a field with no attributes.
fn generate_field_set_arg(&mut self, binding: &BindingInfo<'_>) -> TokenStream {
let ast = binding.ast();

fn generate_field_set_arg(&mut self, binding_info: &BindingInfo<'_>) -> TokenStream {
let diag = &self.parent.diag;
let ident = ast.ident.as_ref().unwrap();
// strip `r#` prefix, if present
let ident = format_ident!("{}", ident);

let field = binding_info.ast();
let mut field_binding = binding_info.binding.clone();
field_binding.set_span(field.ty.span());

let ident = field.ident.as_ref().unwrap();
let ident = format_ident!("{}", ident); // strip `r#` prefix, if present

quote! {
#diag.set_arg(
stringify!(#ident),
#binding
#field_binding
);
}
}
Expand Down Expand Up @@ -397,7 +399,8 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
clone_suggestion_code: bool,
) -> Result<TokenStream, DiagnosticDeriveError> {
let span = attr.span().unwrap();
let ident = &list.path.segments.last().unwrap().ident;
let mut ident = list.path.segments.last().unwrap().ident.clone();
ident.set_span(info.ty.span());
let name = ident.to_string();
let name = name.as_str();

Expand Down Expand Up @@ -496,7 +499,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
.variant
.bindings()
.iter()
.filter(|binding| !binding.ast().attrs.is_empty())
.filter(|binding| !should_generate_set_arg(binding.ast()))
.map(|binding| self.generate_field_attr_code(binding, kind_stats))
.collect();

Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_macros/src/diagnostics/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,12 @@ impl<'ty> FieldInnerTy<'ty> {
FieldInnerTy::Plain(..) => quote! { #inner },
}
}

pub fn span(&self) -> proc_macro2::Span {
match self {
FieldInnerTy::Option(ty) | FieldInnerTy::Vec(ty) | FieldInnerTy::Plain(ty) => ty.span(),
}
}
}

/// Field information passed to the builder. Deliberately omits attrs to discourage the
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// check-fail
// Tests that a doc comment will not preclude a field from being considered a diagnostic argument
// normalize-stderr-test "the following other types implement trait `IntoDiagnosticArg`:(?:.*\n){0,9}\s+and \d+ others" -> "normalized in stderr"
// normalize-stderr-test "diagnostic_builder\.rs:[0-9]+:[0-9]+" -> "diagnostic_builder.rs:LL:CC"

// The proc_macro2 crate handles spans differently when on beta/stable release rather than nightly,
// changing the output of this test. Since Subdiagnostic is strictly internal to the compiler
Expand Down Expand Up @@ -27,21 +29,21 @@ fluent_messages! { "./example.ftl" }
struct NotIntoDiagnosticArg;

#[derive(Diagnostic)]
//~^ ERROR the trait bound `NotIntoDiagnosticArg: IntoDiagnosticArg` is not satisfied
#[diag(no_crate_example)]
struct Test {
#[primary_span]
span: Span,
/// A doc comment
arg: NotIntoDiagnosticArg,
//~^ ERROR the trait bound `NotIntoDiagnosticArg: IntoDiagnosticArg` is not satisfied
}

#[derive(Subdiagnostic)]
//~^ ERROR the trait bound `NotIntoDiagnosticArg: IntoDiagnosticArg` is not satisfied
#[label(no_crate_example)]
struct SubTest {
#[primary_span]
span: Span,
/// A doc comment
arg: NotIntoDiagnosticArg,
//~^ ERROR the trait bound `NotIntoDiagnosticArg: IntoDiagnosticArg` is not satisfied
}
Original file line number Diff line number Diff line change
@@ -1,42 +1,29 @@
error[E0277]: the trait bound `NotIntoDiagnosticArg: IntoDiagnosticArg` is not satisfied
--> $DIR/diagnostic-derive-doc-comment-field.rs:29:10
--> $DIR/diagnostic-derive-doc-comment-field.rs:37:10
|
LL | #[derive(Diagnostic)]
| ^^^^^^^^^^ the trait `IntoDiagnosticArg` is not implemented for `NotIntoDiagnosticArg`
| ---------- required by a bound introduced by this call
...
LL | arg: NotIntoDiagnosticArg,
| ^^^^^^^^^^^^^^^^^^^^ the trait `IntoDiagnosticArg` is not implemented for `NotIntoDiagnosticArg`
|
= help: the following other types implement trait `IntoDiagnosticArg`:
&'a T
&'a std::path::Path
&'a str
&rustc_target::spec::TargetTriple
Box<(dyn std::error::Error + 'static)>
CString
CguReuse
Cow<'a, str>
and 42 others
= help: normalized in stderr
note: required by a bound in `DiagnosticBuilder::<'a, G>::set_arg`
--> $COMPILER_DIR/rustc_errors/src/diagnostic_builder.rs:747:5
= note: this error originates in the derive macro `Diagnostic` which comes from the expansion of the macro `forward` (in Nightly builds, run with -Z macro-backtrace for more info)
--> $COMPILER_DIR/rustc_errors/src/diagnostic_builder.rs:LL:CC
= note: this error originates in the macro `forward` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `NotIntoDiagnosticArg: IntoDiagnosticArg` is not satisfied
--> $DIR/diagnostic-derive-doc-comment-field.rs:39:10
--> $DIR/diagnostic-derive-doc-comment-field.rs:47:10
|
LL | #[derive(Subdiagnostic)]
| ^^^^^^^^^^^^^ the trait `IntoDiagnosticArg` is not implemented for `NotIntoDiagnosticArg`
| ------------- required by a bound introduced by this call
...
LL | arg: NotIntoDiagnosticArg,
| ^^^^^^^^^^^^^^^^^^^^ the trait `IntoDiagnosticArg` is not implemented for `NotIntoDiagnosticArg`
|
= help: the following other types implement trait `IntoDiagnosticArg`:
&'a T
&'a std::path::Path
&'a str
&rustc_target::spec::TargetTriple
Box<(dyn std::error::Error + 'static)>
CString
CguReuse
Cow<'a, str>
and 42 others
= help: normalized in stderr
note: required by a bound in `Diagnostic::set_arg`
--> $COMPILER_DIR/rustc_errors/src/diagnostic.rs:964:5
= note: this error originates in the derive macro `Subdiagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)

error: aborting due to 2 previous errors

Expand Down
2 changes: 1 addition & 1 deletion tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -339,12 +339,12 @@ struct ErrorWithDefaultLabelAttr<'a> {
}

#[derive(Diagnostic)]
//~^ ERROR the trait bound `Hello: IntoDiagnosticArg` is not satisfied
#[diag(no_crate_example, code = "E0123")]
struct ArgFieldWithoutSkip {
#[primary_span]
span: Span,
other: Hello,
//~^ ERROR the trait bound `Hello: IntoDiagnosticArg` is not satisfied
}

#[derive(Diagnostic)]
Expand Down
9 changes: 6 additions & 3 deletions tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -641,15 +641,18 @@ LL | #[derive(Diagnostic)]
= note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `Hello: IntoDiagnosticArg` is not satisfied
--> $DIR/diagnostic-derive.rs:341:10
--> $DIR/diagnostic-derive.rs:346:12
|
LL | #[derive(Diagnostic)]
| ^^^^^^^^^^ the trait `IntoDiagnosticArg` is not implemented for `Hello`
| ---------- required by a bound introduced by this call
...
LL | other: Hello,
| ^^^^^ the trait `IntoDiagnosticArg` is not implemented for `Hello`
|
= help: normalized in stderr
note: required by a bound in `DiagnosticBuilder::<'a, G>::set_arg`
--> $COMPILER_DIR/rustc_errors/src/diagnostic_builder.rs:LL:CC
= note: this error originates in the derive macro `Diagnostic` which comes from the expansion of the macro `forward` (in Nightly builds, run with -Z macro-backtrace for more info)
= note: this error originates in the macro `forward` (in Nightly builds, run with -Z macro-backtrace for more info)

error: aborting due to 84 previous errors

Expand Down

0 comments on commit a156bd7

Please sign in to comment.