Skip to content

Commit 7fbaf27

Browse files
committed
macros: support doc comments in diag derives
Documentation comments shouldn't affect the diagnostic derive in any way, but explicit support has to be added for ignoring the `doc` attribute. Signed-off-by: David Wood <david.wood@huawei.com>
1 parent 1536ab1 commit 7fbaf27

File tree

5 files changed

+90
-14
lines changed

5 files changed

+90
-14
lines changed

compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::diagnostics::error::{
55
DiagnosticDeriveError,
66
};
77
use crate::diagnostics::utils::{
8-
build_field_mapping, report_error_if_not_applied_to_span, report_type_error,
8+
build_field_mapping, is_doc_comment, report_error_if_not_applied_to_span, report_type_error,
99
should_generate_set_arg, type_is_unit, type_matches_path, FieldInfo, FieldInnerTy, FieldMap,
1010
HasFieldMap, SetOnce, SpannedOption, SubdiagnosticKind,
1111
};
@@ -152,8 +152,12 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
152152
fn parse_subdiag_attribute(
153153
&self,
154154
attr: &Attribute,
155-
) -> Result<(SubdiagnosticKind, Path), DiagnosticDeriveError> {
156-
let (subdiag, slug) = SubdiagnosticKind::from_attr(attr, self)?;
155+
) -> Result<Option<(SubdiagnosticKind, Path)>, DiagnosticDeriveError> {
156+
let Some((subdiag, slug)) = SubdiagnosticKind::from_attr(attr, self)? else {
157+
// Some attributes aren't errors - like documentation comments - but also aren't
158+
// subdiagnostics.
159+
return Ok(None);
160+
};
157161

158162
if let SubdiagnosticKind::MultipartSuggestion { .. } = subdiag {
159163
let meta = attr.parse_meta()?;
@@ -170,7 +174,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
170174
SubdiagnosticKind::MultipartSuggestion { .. } => unreachable!(),
171175
});
172176

173-
Ok((subdiag, slug))
177+
Ok(Some((subdiag, slug)))
174178
}
175179

176180
/// Establishes state in the `DiagnosticDeriveBuilder` resulting from the struct
@@ -182,6 +186,11 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
182186
) -> Result<TokenStream, DiagnosticDeriveError> {
183187
let diag = &self.parent.diag;
184188

189+
// Always allow documentation comments.
190+
if is_doc_comment(attr) {
191+
return Ok(quote! {});
192+
}
193+
185194
let name = attr.path.segments.last().unwrap().ident.to_string();
186195
let name = name.as_str();
187196
let meta = attr.parse_meta()?;
@@ -250,7 +259,11 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
250259
return Ok(tokens);
251260
}
252261

253-
let (subdiag, slug) = self.parse_subdiag_attribute(attr)?;
262+
let Some((subdiag, slug)) = self.parse_subdiag_attribute(attr)? else {
263+
// Some attributes aren't errors - like documentation comments - but also aren't
264+
// subdiagnostics.
265+
return Ok(quote! {});
266+
};
254267
let fn_ident = format_ident!("{}", subdiag);
255268
match subdiag {
256269
SubdiagnosticKind::Note | SubdiagnosticKind::Help | SubdiagnosticKind::Warn => {
@@ -291,6 +304,11 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
291304
.attrs
292305
.iter()
293306
.map(move |attr| {
307+
// Always allow documentation comments.
308+
if is_doc_comment(attr) {
309+
return quote! {};
310+
}
311+
294312
let name = attr.path.segments.last().unwrap().ident.to_string();
295313
let needs_clone =
296314
name == "primary_span" && matches!(inner_ty, FieldInnerTy::Vec(_));
@@ -397,8 +415,11 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
397415
_ => (),
398416
}
399417

400-
let (subdiag, slug) = self.parse_subdiag_attribute(attr)?;
401-
418+
let Some((subdiag, slug)) = self.parse_subdiag_attribute(attr)? else {
419+
// Some attributes aren't errors - like documentation comments - but also aren't
420+
// subdiagnostics.
421+
return Ok(quote! {});
422+
};
402423
let fn_ident = format_ident!("{}", subdiag);
403424
match subdiag {
404425
SubdiagnosticKind::Label => {

compiler/rustc_macros/src/diagnostics/subdiagnostic.rs

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ use crate::diagnostics::error::{
55
DiagnosticDeriveError,
66
};
77
use crate::diagnostics::utils::{
8-
build_field_mapping, new_code_ident, report_error_if_not_applied_to_applicability,
9-
report_error_if_not_applied_to_span, FieldInfo, FieldInnerTy, FieldMap, HasFieldMap, SetOnce,
10-
SpannedOption, SubdiagnosticKind,
8+
build_field_mapping, is_doc_comment, new_code_ident,
9+
report_error_if_not_applied_to_applicability, report_error_if_not_applied_to_span, FieldInfo,
10+
FieldInnerTy, FieldMap, HasFieldMap, SetOnce, SpannedOption, SubdiagnosticKind,
1111
};
1212
use proc_macro2::TokenStream;
1313
use quote::{format_ident, quote};
@@ -43,6 +43,11 @@ impl SubdiagnosticDeriveBuilder {
4343

4444
if matches!(ast.data, syn::Data::Enum(..)) {
4545
for attr in &ast.attrs {
46+
// Always allow documentation comments.
47+
if is_doc_comment(attr) {
48+
continue;
49+
}
50+
4651
span_err(
4752
attr.span().unwrap(),
4853
"unsupported type attribute for subdiagnostic enum",
@@ -173,7 +178,11 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
173178
let mut kind_slugs = vec![];
174179

175180
for attr in self.variant.ast().attrs {
176-
let (kind, slug) = SubdiagnosticKind::from_attr(attr, self)?;
181+
let Some((kind, slug)) = SubdiagnosticKind::from_attr(attr, self)? else {
182+
// Some attributes aren't errors - like documentation comments - but also aren't
183+
// subdiagnostics.
184+
continue;
185+
};
177186

178187
let Some(slug) = slug else {
179188
let name = attr.path.segments.last().unwrap().ident.to_string();
@@ -227,6 +236,11 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
227236
ast.attrs
228237
.iter()
229238
.map(|attr| {
239+
// Always allow documentation comments.
240+
if is_doc_comment(attr) {
241+
return quote! {};
242+
}
243+
230244
let info = FieldInfo {
231245
binding,
232246
ty: inner_ty.inner_type().unwrap_or(&ast.ty),

compiler/rustc_macros/src/diagnostics/utils.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,12 @@ impl SubdiagnosticKind {
477477
pub(super) fn from_attr(
478478
attr: &Attribute,
479479
fields: &impl HasFieldMap,
480-
) -> Result<(SubdiagnosticKind, Option<Path>), DiagnosticDeriveError> {
480+
) -> Result<Option<(SubdiagnosticKind, Option<Path>)>, DiagnosticDeriveError> {
481+
// Always allow documentation comments.
482+
if is_doc_comment(attr) {
483+
return Ok(None);
484+
}
485+
481486
let span = attr.span().unwrap();
482487

483488
let name = attr.path.segments.last().unwrap().ident.to_string();
@@ -526,7 +531,9 @@ impl SubdiagnosticKind {
526531
| SubdiagnosticKind::Note
527532
| SubdiagnosticKind::Help
528533
| SubdiagnosticKind::Warn
529-
| SubdiagnosticKind::MultipartSuggestion { .. } => return Ok((kind, None)),
534+
| SubdiagnosticKind::MultipartSuggestion { .. } => {
535+
return Ok(Some((kind, None)));
536+
}
530537
SubdiagnosticKind::Suggestion { .. } => {
531538
throw_span_err!(span, "suggestion without `code = \"...\"`")
532539
}
@@ -626,7 +633,7 @@ impl SubdiagnosticKind {
626633
| SubdiagnosticKind::MultipartSuggestion { .. } => {}
627634
}
628635

629-
Ok((kind, slug))
636+
Ok(Some((kind, slug)))
630637
}
631638
}
632639

@@ -654,3 +661,7 @@ impl quote::IdentFragment for SubdiagnosticKind {
654661
pub(super) fn should_generate_set_arg(field: &Field) -> bool {
655662
field.attrs.is_empty()
656663
}
664+
665+
pub(super) fn is_doc_comment(attr: &Attribute) -> bool {
666+
attr.path.segments.last().unwrap().ident.to_string() == "doc"
667+
}

src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -749,3 +749,12 @@ struct SubdiagnosticEagerSuggestion {
749749
#[subdiagnostic(eager)]
750750
sub: SubdiagnosticWithSuggestion,
751751
}
752+
753+
/// with a doc comment on the type..
754+
#[derive(Diagnostic)]
755+
#[diag(compiletest::example, code = "E0123")]
756+
struct WithDocComment {
757+
/// ..and the field
758+
#[primary_span]
759+
span: Span,
760+
}

src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -641,3 +641,24 @@ struct BJ {
641641
span: Span,
642642
r#type: String,
643643
}
644+
645+
/// with a doc comment on the type..
646+
#[derive(Subdiagnostic)]
647+
#[label(parser::add_paren)]
648+
struct BK {
649+
/// ..and the field
650+
#[primary_span]
651+
span: Span,
652+
}
653+
654+
/// with a doc comment on the type..
655+
#[derive(Subdiagnostic)]
656+
enum BL {
657+
/// ..and the variant..
658+
#[label(parser::add_paren)]
659+
Foo {
660+
/// ..and the field
661+
#[primary_span]
662+
span: Span,
663+
}
664+
}

0 commit comments

Comments
 (0)