Ensure #[suggestion] is only applied to correct tuple types

This commit is contained in:
Xiretza 2022-09-10 14:43:07 +02:00
parent 2e72387fd0
commit ec85a1b263
3 changed files with 79 additions and 48 deletions

View File

@ -571,46 +571,37 @@ impl DiagnosticDeriveBuilder {
let mut span_idx = None;
let mut applicability_idx = None;
fn type_err(span: &Span) -> Result<!, DiagnosticDeriveError> {
span_err(span.unwrap(), "wrong types for suggestion")
.help(
"`#[suggestion(...)]` on a tuple field must be applied to fields \
of type `(Span, Applicability)`",
)
.emit();
Err(DiagnosticDeriveError::ErrorHandled)
}
for (idx, elem) in tup.elems.iter().enumerate() {
if type_matches_path(elem, &["rustc_span", "Span"]) {
if span_idx.is_none() {
span_idx = Some(syn::Index::from(idx));
} else {
throw_span_err!(
info.span.unwrap(),
"type of field annotated with `#[suggestion(...)]` contains more \
than one `Span`"
);
}
span_idx.set_once((syn::Index::from(idx), elem.span().unwrap()));
} else if type_matches_path(elem, &["rustc_errors", "Applicability"]) {
if applicability_idx.is_none() {
applicability_idx = Some(syn::Index::from(idx));
applicability_idx.set_once((syn::Index::from(idx), elem.span().unwrap()));
} else {
throw_span_err!(
info.span.unwrap(),
"type of field annotated with `#[suggestion(...)]` contains more \
than one Applicability"
);
}
type_err(&elem.span())?;
}
}
if let Some(span_idx) = span_idx {
let Some((span_idx, _)) = span_idx else {
type_err(&tup.span())?;
};
let Some((applicability_idx, _applicability_span)) = applicability_idx else {
type_err(&tup.span())?;
};
let binding = &info.binding.binding;
let span = quote!(#binding.#span_idx);
let applicability = applicability_idx
.map(|applicability_idx| quote!(#binding.#applicability_idx))
.unwrap_or_else(|| quote!(rustc_errors::Applicability::Unspecified));
let applicability = quote!(#binding.#applicability_idx);
return Ok((span, Some(applicability)));
}
throw_span_err!(info.span.unwrap(), "wrong types for suggestion", |diag| {
diag.help(
"`#[suggestion(...)]` on a tuple field must be applied to fields of type \
`(Span, Applicability)`",
)
});
Ok((span, Some(applicability)))
}
// If `ty` isn't a `Span` or `(Span, Applicability)` then emit an error.
_ => throw_span_err!(info.span.unwrap(), "wrong field type for suggestion", |diag| {

View File

@ -269,16 +269,16 @@ struct SuggestWithSpanOnly {
#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
struct SuggestWithDuplicateSpanAndApplicability {
#[suggestion(typeck::suggestion, code = "This is suggested code")]
//~^ ERROR type of field annotated with `#[suggestion(...)]` contains more than one `Span`
suggestion: (Span, Span, Applicability),
//~^ ERROR specified multiple times
}
#[derive(Diagnostic)]
#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
struct SuggestWithDuplicateApplicabilityAndSpan {
#[suggestion(typeck::suggestion, code = "This is suggested code")]
//~^ ERROR type of field annotated with `#[suggestion(...)]` contains more than one
suggestion: (Applicability, Applicability, Span),
//~^ ERROR specified multiple times
}
#[derive(Diagnostic)]
@ -589,3 +589,19 @@ struct DuplicatedSuggestionCode {
//~^ ERROR specified multiple times
suggestion: Span,
}
#[derive(Diagnostic)]
#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
struct InvalidTypeInSuggestionTuple {
#[suggestion(typeck::suggestion, code = "...")]
suggestion: (Span, usize),
//~^ ERROR wrong types for suggestion
}
#[derive(Diagnostic)]
#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
struct MissingApplicabilityInSuggestionTuple {
#[suggestion(typeck::suggestion, code = "...")]
suggestion: (Span,),
//~^ ERROR wrong types for suggestion
}

View File

@ -263,21 +263,29 @@ LL | | suggestion: Applicability,
|
= help: `#[suggestion(...)]` should be applied to fields of type `Span` or `(Span, Applicability)`
error: type of field annotated with `#[suggestion(...)]` contains more than one `Span`
--> $DIR/diagnostic-derive.rs:271:5
error: specified multiple times
--> $DIR/diagnostic-derive.rs:272:24
|
LL | / #[suggestion(typeck::suggestion, code = "This is suggested code")]
LL | |
LL | | suggestion: (Span, Span, Applicability),
| |___________________________________________^
LL | suggestion: (Span, Span, Applicability),
| ^^^^
|
note: previously specified here
--> $DIR/diagnostic-derive.rs:272:18
|
LL | suggestion: (Span, Span, Applicability),
| ^^^^
error: type of field annotated with `#[suggestion(...)]` contains more than one Applicability
--> $DIR/diagnostic-derive.rs:279:5
error: specified multiple times
--> $DIR/diagnostic-derive.rs:280:33
|
LL | / #[suggestion(typeck::suggestion, code = "This is suggested code")]
LL | |
LL | | suggestion: (Applicability, Applicability, Span),
| |____________________________________________________^
LL | suggestion: (Applicability, Applicability, Span),
| ^^^^^^^^^^^^^
|
note: previously specified here
--> $DIR/diagnostic-derive.rs:280:18
|
LL | suggestion: (Applicability, Applicability, Span),
| ^^^^^^^^^^^^^
error: `#[label = ...]` is not a valid attribute
--> $DIR/diagnostic-derive.rs:287:5
@ -415,6 +423,22 @@ note: previously specified here
LL | #[suggestion(typeck::suggestion, code = "...", code = ",,,")]
| ^^^^^^^^^^^^
error: wrong types for suggestion
--> $DIR/diagnostic-derive.rs:597:24
|
LL | suggestion: (Span, usize),
| ^^^^^
|
= help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)`
error: wrong types for suggestion
--> $DIR/diagnostic-derive.rs:605:17
|
LL | suggestion: (Span,),
| ^^^^^^^
|
= help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)`
error: cannot find attribute `nonsense` in this scope
--> $DIR/diagnostic-derive.rs:53:3
|
@ -471,7 +495,7 @@ LL | arg: impl IntoDiagnosticArg,
| ^^^^^^^^^^^^^^^^^ required by this bound in `DiagnosticBuilder::<'a, G>::set_arg`
= note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 56 previous errors
error: aborting due to 58 previous errors
Some errors have detailed explanations: E0277, E0425.
For more information about an error, try `rustc --explain E0277`.