Skip to content

Commit 2b9279f

Browse files
Diagnostic args are still args if they're documented
1 parent ad6b20b commit 2b9279f

File tree

4 files changed

+97
-8
lines changed

4 files changed

+97
-8
lines changed

compiler/rustc_macros/src/diagnostics/subdiagnostic.rs

+5-7
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,16 @@ use crate::diagnostics::error::{
44
invalid_attr, span_err, throw_invalid_attr, throw_span_err, DiagnosticDeriveError,
55
};
66
use crate::diagnostics::utils::{
7-
build_field_mapping, is_doc_comment, new_code_ident,
8-
report_error_if_not_applied_to_applicability, report_error_if_not_applied_to_span, FieldInfo,
9-
FieldInnerTy, FieldMap, HasFieldMap, SetOnce, SpannedOption, SubdiagnosticKind,
7+
build_field_mapping, build_suggestion_code, is_doc_comment, new_code_ident,
8+
report_error_if_not_applied_to_applicability, report_error_if_not_applied_to_span,
9+
should_generate_set_arg, AllowMultipleAlternatives, FieldInfo, FieldInnerTy, FieldMap,
10+
HasFieldMap, SetOnce, SpannedOption, SubdiagnosticKind,
1011
};
1112
use proc_macro2::TokenStream;
1213
use quote::{format_ident, quote};
1314
use syn::{spanned::Spanned, Attribute, Meta, MetaList, Path};
1415
use synstructure::{BindingInfo, Structure, VariantInfo};
1516

16-
use super::utils::{build_suggestion_code, AllowMultipleAlternatives};
17-
1817
/// The central struct for constructing the `add_to_diagnostic` method from an annotated struct.
1918
pub(crate) struct SubdiagnosticDeriveBuilder {
2019
diag: syn::Ident,
@@ -212,7 +211,6 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
212211
/// Generates the code for a field with no attributes.
213212
fn generate_field_set_arg(&mut self, binding: &BindingInfo<'_>) -> TokenStream {
214213
let ast = binding.ast();
215-
assert_eq!(ast.attrs.len(), 0, "field with attribute used as diagnostic arg");
216214

217215
let diag = &self.parent.diag;
218216
let ident = ast.ident.as_ref().unwrap();
@@ -580,7 +578,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
580578
.variant
581579
.bindings()
582580
.iter()
583-
.filter(|binding| binding.ast().attrs.is_empty())
581+
.filter(|binding| should_generate_set_arg(binding.ast()))
584582
.map(|binding| self.generate_field_set_arg(binding))
585583
.collect();
586584

compiler/rustc_macros/src/diagnostics/utils.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -851,7 +851,8 @@ impl quote::IdentFragment for SubdiagnosticKind {
851851
/// Returns `true` if `field` should generate a `set_arg` call rather than any other diagnostic
852852
/// call (like `span_label`).
853853
pub(super) fn should_generate_set_arg(field: &Field) -> bool {
854-
field.attrs.is_empty()
854+
// Perhaps this should be an exhaustive list...
855+
field.attrs.iter().all(|attr| is_doc_comment(attr))
855856
}
856857

857858
pub(super) fn is_doc_comment(attr: &Attribute) -> bool {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// check-fail
2+
// Tests that a doc comment will not preclude a field from being considered a diagnostic argument
3+
4+
// The proc_macro2 crate handles spans differently when on beta/stable release rather than nightly,
5+
// changing the output of this test. Since Subdiagnostic is strictly internal to the compiler
6+
// the test is just ignored on stable and beta:
7+
// ignore-stage1
8+
// ignore-beta
9+
// ignore-stable
10+
11+
#![feature(rustc_private)]
12+
#![crate_type = "lib"]
13+
14+
extern crate rustc_errors;
15+
extern crate rustc_fluent_macro;
16+
extern crate rustc_macros;
17+
extern crate rustc_session;
18+
extern crate rustc_span;
19+
20+
use rustc_errors::{Applicability, DiagnosticMessage, SubdiagnosticMessage};
21+
use rustc_fluent_macro::fluent_messages;
22+
use rustc_macros::{Diagnostic, Subdiagnostic};
23+
use rustc_span::Span;
24+
25+
fluent_messages! { "./example.ftl" }
26+
27+
struct NotIntoDiagnosticArg;
28+
29+
#[derive(Diagnostic)]
30+
//~^ ERROR the trait bound `NotIntoDiagnosticArg: IntoDiagnosticArg` is not satisfied
31+
#[diag(no_crate_example)]
32+
struct Test {
33+
#[primary_span]
34+
span: Span,
35+
/// A doc comment
36+
arg: NotIntoDiagnosticArg,
37+
}
38+
39+
#[derive(Subdiagnostic)]
40+
//~^ ERROR the trait bound `NotIntoDiagnosticArg: IntoDiagnosticArg` is not satisfied
41+
#[label(no_crate_example)]
42+
struct SubTest {
43+
#[primary_span]
44+
span: Span,
45+
/// A doc comment
46+
arg: NotIntoDiagnosticArg,
47+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
error[E0277]: the trait bound `NotIntoDiagnosticArg: IntoDiagnosticArg` is not satisfied
2+
--> $DIR/diagnostic-derive-doc-comment-field.rs:29:10
3+
|
4+
LL | #[derive(Diagnostic)]
5+
| ^^^^^^^^^^ the trait `IntoDiagnosticArg` is not implemented for `NotIntoDiagnosticArg`
6+
|
7+
= help: the following other types implement trait `IntoDiagnosticArg`:
8+
&'a T
9+
&'a std::path::Path
10+
&'a str
11+
&rustc_target::spec::TargetTriple
12+
Box<(dyn std::error::Error + 'static)>
13+
CString
14+
CguReuse
15+
Cow<'a, str>
16+
and 42 others
17+
note: required by a bound in `DiagnosticBuilder::<'a, G>::set_arg`
18+
--> $COMPILER_DIR/rustc_errors/src/diagnostic_builder.rs:747:5
19+
= 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)
20+
21+
error[E0277]: the trait bound `NotIntoDiagnosticArg: IntoDiagnosticArg` is not satisfied
22+
--> $DIR/diagnostic-derive-doc-comment-field.rs:39:10
23+
|
24+
LL | #[derive(Subdiagnostic)]
25+
| ^^^^^^^^^^^^^ the trait `IntoDiagnosticArg` is not implemented for `NotIntoDiagnosticArg`
26+
|
27+
= help: the following other types implement trait `IntoDiagnosticArg`:
28+
&'a T
29+
&'a std::path::Path
30+
&'a str
31+
&rustc_target::spec::TargetTriple
32+
Box<(dyn std::error::Error + 'static)>
33+
CString
34+
CguReuse
35+
Cow<'a, str>
36+
and 42 others
37+
note: required by a bound in `Diagnostic::set_arg`
38+
--> $COMPILER_DIR/rustc_errors/src/diagnostic.rs:964:5
39+
= note: this error originates in the derive macro `Subdiagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
40+
41+
error: aborting due to 2 previous errors
42+
43+
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)