Skip to content

Commit ef434f0

Browse files
committed
Allow using bool for optional diagnostics
1 parent 49b9cc5 commit ef434f0

File tree

4 files changed

+77
-45
lines changed

4 files changed

+77
-45
lines changed

compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ use crate::diagnostics::error::{
66
};
77
use crate::diagnostics::utils::{
88
build_field_mapping, is_doc_comment, report_error_if_not_applied_to_span, report_type_error,
9-
should_generate_set_arg, type_is_unit, type_matches_path, FieldInfo, FieldInnerTy, FieldMap,
10-
HasFieldMap, SetOnce, SpannedOption, SubdiagnosticKind,
9+
should_generate_set_arg, type_is_bool, type_is_unit, type_matches_path, FieldInfo,
10+
FieldInnerTy, FieldMap, HasFieldMap, SetOnce, SpannedOption, SubdiagnosticKind,
1111
};
1212
use proc_macro2::{Ident, Span, TokenStream};
1313
use quote::{format_ident, quote};
@@ -414,12 +414,15 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
414414
Ok(self.add_spanned_subdiagnostic(binding, &fn_ident, slug))
415415
}
416416
SubdiagnosticKind::Note | SubdiagnosticKind::Help | SubdiagnosticKind::Warn => {
417-
if type_matches_path(info.ty.inner_type(), &["rustc_span", "Span"]) {
417+
let inner = info.ty.inner_type();
418+
if type_matches_path(inner, &["rustc_span", "Span"]) {
418419
Ok(self.add_spanned_subdiagnostic(binding, &fn_ident, slug))
419-
} else if type_is_unit(info.ty.inner_type()) {
420+
} else if type_is_unit(inner)
421+
|| (matches!(info.ty, FieldInnerTy::Plain(_)) && type_is_bool(inner))
422+
{
420423
Ok(self.add_subdiagnostic(&fn_ident, slug))
421424
} else {
422-
report_type_error(attr, "`Span` or `()`")?
425+
report_type_error(attr, "`Span`, `bool` or `()`")?
423426
}
424427
}
425428
SubdiagnosticKind::Suggestion {

compiler/rustc_macros/src/diagnostics/utils.rs

+10
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@ pub(crate) fn type_is_unit(ty: &Type) -> bool {
5050
if let Type::Tuple(TypeTuple { elems, .. }) = ty { elems.is_empty() } else { false }
5151
}
5252

53+
/// Checks whether the type `ty` is `bool`.
54+
pub(crate) fn type_is_bool(ty: &Type) -> bool {
55+
type_matches_path(ty, &["bool"])
56+
}
57+
5358
/// Reports a type error for field with `attr`.
5459
pub(crate) fn report_type_error(
5560
attr: &Attribute,
@@ -192,6 +197,11 @@ impl<'ty> FieldInnerTy<'ty> {
192197
#inner
193198
}
194199
},
200+
FieldInnerTy::Plain(t) if type_is_bool(t) => quote! {
201+
if #binding {
202+
#inner
203+
}
204+
},
195205
FieldInnerTy::Plain(..) => quote! { #inner },
196206
}
197207
}

tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs

+13
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,19 @@ struct OptUnitField {
513513
bar: Option<()>,
514514
}
515515

516+
#[derive(Diagnostic)]
517+
#[diag(no_crate_example)]
518+
struct BoolField {
519+
#[primary_span]
520+
spans: Span,
521+
#[help]
522+
foo: bool,
523+
#[help(no_crate_help)]
524+
//~^ ERROR the `#[help(...)]` attribute can only be applied to fields of type `Span`, `bool` or `()`
525+
// only allow plain 'bool' fields
526+
bar: Option<bool>,
527+
}
528+
516529
#[derive(Diagnostic)]
517530
#[diag(no_crate_example, code = "E0123")]
518531
struct LabelWithTrailingPath {

0 commit comments

Comments
 (0)