Make spans a bit better
This commit is contained in:
parent
2b9279f313
commit
a156bd7714
@ -9,7 +9,7 @@
|
|||||||
FieldInnerTy, FieldMap, HasFieldMap, SetOnce, SpannedOption, SubdiagnosticKind,
|
FieldInnerTy, FieldMap, HasFieldMap, SetOnce, SpannedOption, SubdiagnosticKind,
|
||||||
};
|
};
|
||||||
use proc_macro2::{Ident, Span, TokenStream};
|
use proc_macro2::{Ident, Span, TokenStream};
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote, quote_spanned};
|
||||||
use syn::Token;
|
use syn::Token;
|
||||||
use syn::{parse_quote, spanned::Spanned, Attribute, Meta, Path, Type};
|
use syn::{parse_quote, spanned::Spanned, Attribute, Meta, Path, Type};
|
||||||
use synstructure::{BindingInfo, Structure, VariantInfo};
|
use synstructure::{BindingInfo, Structure, VariantInfo};
|
||||||
@ -251,7 +251,8 @@ fn generate_field_code(&mut self, binding_info: &BindingInfo<'_>) -> TokenStream
|
|||||||
let diag = &self.parent.diag;
|
let diag = &self.parent.diag;
|
||||||
|
|
||||||
let field = binding_info.ast();
|
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 = field.ident.as_ref().unwrap();
|
||||||
let ident = format_ident!("{}", ident); // strip `r#` prefix, if present
|
let ident = format_ident!("{}", ident); // strip `r#` prefix, if present
|
||||||
@ -284,9 +285,9 @@ fn generate_field_attrs_code(&mut self, binding_info: &BindingInfo<'_>) -> Token
|
|||||||
name == "primary_span" && matches!(inner_ty, FieldInnerTy::Vec(_));
|
name == "primary_span" && matches!(inner_ty, FieldInnerTy::Vec(_));
|
||||||
let (binding, needs_destructure) = if needs_clone {
|
let (binding, needs_destructure) = if needs_clone {
|
||||||
// `primary_span` can accept a `Vec<Span>` so don't destructure that.
|
// `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 {
|
} else {
|
||||||
(quote! { #field_binding }, true)
|
(quote_spanned! {inner_ty.span()=> #field_binding }, true)
|
||||||
};
|
};
|
||||||
|
|
||||||
let generated_code = self
|
let generated_code = self
|
||||||
|
@ -209,18 +209,20 @@ fn identify_kind(&mut self) -> Result<Vec<(SubdiagnosticKind, Path)>, Diagnostic
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Generates the code for a field with no attributes.
|
/// Generates the code for a field with no attributes.
|
||||||
fn generate_field_set_arg(&mut self, binding: &BindingInfo<'_>) -> TokenStream {
|
fn generate_field_set_arg(&mut self, binding_info: &BindingInfo<'_>) -> TokenStream {
|
||||||
let ast = binding.ast();
|
|
||||||
|
|
||||||
let diag = &self.parent.diag;
|
let diag = &self.parent.diag;
|
||||||
let ident = ast.ident.as_ref().unwrap();
|
|
||||||
// strip `r#` prefix, if present
|
let field = binding_info.ast();
|
||||||
let ident = format_ident!("{}", ident);
|
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! {
|
quote! {
|
||||||
#diag.set_arg(
|
#diag.set_arg(
|
||||||
stringify!(#ident),
|
stringify!(#ident),
|
||||||
#binding
|
#field_binding
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -397,7 +399,8 @@ fn generate_field_code_inner_list(
|
|||||||
clone_suggestion_code: bool,
|
clone_suggestion_code: bool,
|
||||||
) -> Result<TokenStream, DiagnosticDeriveError> {
|
) -> Result<TokenStream, DiagnosticDeriveError> {
|
||||||
let span = attr.span().unwrap();
|
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 = ident.to_string();
|
||||||
let name = name.as_str();
|
let name = name.as_str();
|
||||||
|
|
||||||
@ -496,7 +499,7 @@ pub fn into_tokens(&mut self) -> Result<TokenStream, DiagnosticDeriveError> {
|
|||||||
.variant
|
.variant
|
||||||
.bindings()
|
.bindings()
|
||||||
.iter()
|
.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))
|
.map(|binding| self.generate_field_attr_code(binding, kind_stats))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
@ -207,6 +207,12 @@ pub(crate) fn with(&self, binding: impl ToTokens, inner: impl ToTokens) -> Token
|
|||||||
FieldInnerTy::Plain(..) => quote! { #inner },
|
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
|
/// Field information passed to the builder. Deliberately omits attrs to discourage the
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
// check-fail
|
// check-fail
|
||||||
// Tests that a doc comment will not preclude a field from being considered a diagnostic argument
|
// 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,
|
// 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
|
// changing the output of this test. Since Subdiagnostic is strictly internal to the compiler
|
||||||
@ -27,21 +29,21 @@
|
|||||||
struct NotIntoDiagnosticArg;
|
struct NotIntoDiagnosticArg;
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
//~^ ERROR the trait bound `NotIntoDiagnosticArg: IntoDiagnosticArg` is not satisfied
|
|
||||||
#[diag(no_crate_example)]
|
#[diag(no_crate_example)]
|
||||||
struct Test {
|
struct Test {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
span: Span,
|
span: Span,
|
||||||
/// A doc comment
|
/// A doc comment
|
||||||
arg: NotIntoDiagnosticArg,
|
arg: NotIntoDiagnosticArg,
|
||||||
|
//~^ ERROR the trait bound `NotIntoDiagnosticArg: IntoDiagnosticArg` is not satisfied
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Subdiagnostic)]
|
#[derive(Subdiagnostic)]
|
||||||
//~^ ERROR the trait bound `NotIntoDiagnosticArg: IntoDiagnosticArg` is not satisfied
|
|
||||||
#[label(no_crate_example)]
|
#[label(no_crate_example)]
|
||||||
struct SubTest {
|
struct SubTest {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
span: Span,
|
span: Span,
|
||||||
/// A doc comment
|
/// A doc comment
|
||||||
arg: NotIntoDiagnosticArg,
|
arg: NotIntoDiagnosticArg,
|
||||||
|
//~^ ERROR the trait bound `NotIntoDiagnosticArg: IntoDiagnosticArg` is not satisfied
|
||||||
}
|
}
|
||||||
|
@ -1,42 +1,29 @@
|
|||||||
error[E0277]: the trait bound `NotIntoDiagnosticArg: IntoDiagnosticArg` is not satisfied
|
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)]
|
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`:
|
= help: normalized in stderr
|
||||||
&'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
|
|
||||||
note: required by a bound in `DiagnosticBuilder::<'a, G>::set_arg`
|
note: required by a bound in `DiagnosticBuilder::<'a, G>::set_arg`
|
||||||
--> $COMPILER_DIR/rustc_errors/src/diagnostic_builder.rs:747:5
|
--> $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[E0277]: the trait bound `NotIntoDiagnosticArg: IntoDiagnosticArg` is not satisfied
|
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)]
|
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`:
|
= help: normalized in stderr
|
||||||
&'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
|
|
||||||
note: required by a bound in `Diagnostic::set_arg`
|
note: required by a bound in `Diagnostic::set_arg`
|
||||||
--> $COMPILER_DIR/rustc_errors/src/diagnostic.rs:964:5
|
--> $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
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
@ -339,12 +339,12 @@ struct ErrorWithDefaultLabelAttr<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
//~^ ERROR the trait bound `Hello: IntoDiagnosticArg` is not satisfied
|
|
||||||
#[diag(no_crate_example, code = "E0123")]
|
#[diag(no_crate_example, code = "E0123")]
|
||||||
struct ArgFieldWithoutSkip {
|
struct ArgFieldWithoutSkip {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
span: Span,
|
span: Span,
|
||||||
other: Hello,
|
other: Hello,
|
||||||
|
//~^ ERROR the trait bound `Hello: IntoDiagnosticArg` is not satisfied
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
|
@ -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)
|
= 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
|
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)]
|
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
|
= help: normalized in stderr
|
||||||
note: required by a bound in `DiagnosticBuilder::<'a, G>::set_arg`
|
note: required by a bound in `DiagnosticBuilder::<'a, G>::set_arg`
|
||||||
--> $COMPILER_DIR/rustc_errors/src/diagnostic_builder.rs:LL:CC
|
--> $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
|
error: aborting due to 84 previous errors
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user