Skip to content

Commit dc5b5e5

Browse files
Rollup merge of #153401 - GuillaumeGomez:migrate-diag, r=JonathanBrouwer
Migrationg of `LintDiagnostic` - part 7 Part of #153099. This PR removes the `LintDiagnostic` trait and proc-macro. \o/ r? @JonathanBrouwer
2 parents 3092da1 + e805d8c commit dc5b5e5

16 files changed

Lines changed: 122 additions & 338 deletions

File tree

compiler/rustc_errors/src/decorate_diag.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use rustc_lint_defs::{BuiltinLintDiag, Lint, LintId};
77

88
use crate::{Diag, DiagCtxtHandle, Diagnostic, Level};
99

10-
/// We can't implement `LintDiagnostic` for `BuiltinLintDiag`, because decorating some of its
10+
/// We can't implement `Diagnostic` for `BuiltinLintDiag`, because decorating some of its
1111
/// variants requires types we don't have yet. So, handle that case separately.
1212
pub enum DecorateDiagCompat {
1313
Dynamic(Box<dyn for<'a> FnOnce(DiagCtxtHandle<'a>, Level) -> Diag<'a, ()> + DynSend + 'static>),

compiler/rustc_errors/src/diagnostic.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -138,14 +138,6 @@ where
138138
fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>);
139139
}
140140

141-
/// Trait implemented by lint types. This should not be implemented manually. Instead, use
142-
/// `#[derive(LintDiagnostic)]` -- see [rustc_macros::LintDiagnostic].
143-
#[rustc_diagnostic_item = "LintDiagnostic"]
144-
pub trait LintDiagnostic<'a, G: EmissionGuarantee> {
145-
/// Decorate a lint with the information from this type.
146-
fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, G>);
147-
}
148-
149141
#[derive(Clone, Debug, Encodable, Decodable)]
150142
pub(crate) struct DiagLocation {
151143
file: Cow<'static, str>,

compiler/rustc_errors/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ pub use codes::*;
3838
pub use decorate_diag::{BufferedEarlyLint, DecorateDiagCompat, LintBuffer};
3939
pub use diagnostic::{
4040
BugAbort, Diag, DiagInner, DiagStyledString, Diagnostic, EmissionGuarantee, FatalAbort,
41-
LintDiagnostic, StringPart, Subdiag, Subdiagnostic,
41+
StringPart, Subdiag, Subdiagnostic,
4242
};
4343
pub use diagnostic_impls::{
4444
DiagSymbolList, ElidedLifetimeInPathSubdiag, ExpectedLifetimeParameter,

compiler/rustc_macros/src/diagnostics/diagnostic.rs

Lines changed: 2 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use proc_macro2::TokenStream;
44
use quote::quote;
55
use synstructure::Structure;
66

7-
use crate::diagnostics::diagnostic_builder::DiagnosticDeriveKind;
7+
use crate::diagnostics::diagnostic_builder::each_variant;
88
use crate::diagnostics::error::DiagnosticDeriveError;
99

1010
/// The central struct for constructing the `into_diag` method from an annotated struct.
@@ -19,8 +19,7 @@ impl<'a> DiagnosticDerive<'a> {
1919

2020
pub(crate) fn into_tokens(self) -> TokenStream {
2121
let DiagnosticDerive { mut structure } = self;
22-
let kind = DiagnosticDeriveKind::Diagnostic;
23-
let implementation = kind.each_variant(&mut structure, |mut builder, variant| {
22+
let implementation = each_variant(&mut structure, |mut builder, variant| {
2423
let preamble = builder.preamble(variant);
2524
let body = builder.body(variant);
2625

@@ -64,52 +63,3 @@ impl<'a> DiagnosticDerive<'a> {
6463
})
6564
}
6665
}
67-
68-
/// The central struct for constructing the `decorate_lint` method from an annotated struct.
69-
pub(crate) struct LintDiagnosticDerive<'a> {
70-
structure: Structure<'a>,
71-
}
72-
73-
impl<'a> LintDiagnosticDerive<'a> {
74-
pub(crate) fn new(structure: Structure<'a>) -> Self {
75-
Self { structure }
76-
}
77-
78-
pub(crate) fn into_tokens(self) -> TokenStream {
79-
let LintDiagnosticDerive { mut structure } = self;
80-
let kind = DiagnosticDeriveKind::LintDiagnostic;
81-
let implementation = kind.each_variant(&mut structure, |mut builder, variant| {
82-
let preamble = builder.preamble(variant);
83-
let body = builder.body(variant);
84-
85-
let Some(message) = builder.primary_message() else {
86-
return DiagnosticDeriveError::ErrorHandled.to_compile_error();
87-
};
88-
let message = message.diag_message(Some(variant));
89-
let primary_message = quote! {
90-
diag.primary_message(#message);
91-
};
92-
93-
let formatting_init = &builder.formatting_init;
94-
quote! {
95-
#primary_message
96-
#preamble
97-
#formatting_init
98-
#body
99-
diag
100-
}
101-
});
102-
103-
structure.gen_impl(quote! {
104-
gen impl<'__a> rustc_errors::LintDiagnostic<'__a, ()> for @Self {
105-
#[track_caller]
106-
fn decorate_lint<'__b>(
107-
self,
108-
diag: &'__b mut rustc_errors::Diag<'__a, ()>
109-
) {
110-
#implementation;
111-
}
112-
}
113-
})
114-
}
115-
}

compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs

Lines changed: 48 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,54 @@ use crate::diagnostics::utils::{
1818
should_generate_arg, type_is_bool, type_is_unit, type_matches_path,
1919
};
2020

21-
/// What kind of diagnostic is being derived - a fatal/error/warning or a lint?
22-
#[derive(Clone, Copy, PartialEq, Eq)]
23-
pub(crate) enum DiagnosticDeriveKind {
24-
Diagnostic,
25-
LintDiagnostic,
21+
pub(crate) fn each_variant<'s, F>(structure: &mut Structure<'s>, f: F) -> TokenStream
22+
where
23+
F: for<'v> Fn(DiagnosticDeriveVariantBuilder, &VariantInfo<'v>) -> TokenStream,
24+
{
25+
let ast = structure.ast();
26+
let span = ast.span().unwrap();
27+
match ast.data {
28+
syn::Data::Struct(..) | syn::Data::Enum(..) => (),
29+
syn::Data::Union(..) => {
30+
span_err(span, "diagnostic derives can only be used on structs and enums").emit();
31+
}
32+
}
33+
34+
if matches!(ast.data, syn::Data::Enum(..)) {
35+
for attr in &ast.attrs {
36+
span_err(attr.span().unwrap(), "unsupported type attribute for diagnostic derive enum")
37+
.emit();
38+
}
39+
}
40+
41+
structure.bind_with(|_| synstructure::BindStyle::Move);
42+
let variants = structure.each_variant(|variant| {
43+
let span = match structure.ast().data {
44+
syn::Data::Struct(..) => span,
45+
// There isn't a good way to get the span of the variant, so the variant's
46+
// name will need to do.
47+
_ => variant.ast().ident.span().unwrap(),
48+
};
49+
let builder = DiagnosticDeriveVariantBuilder {
50+
span,
51+
field_map: build_field_mapping(variant),
52+
formatting_init: TokenStream::new(),
53+
message: None,
54+
code: None,
55+
};
56+
f(builder, variant)
57+
});
58+
59+
quote! {
60+
match self {
61+
#variants
62+
}
63+
}
2664
}
2765

2866
/// Tracks persistent information required for a specific variant when building up individual calls
29-
/// to diagnostic methods for generated diagnostic derives - both `Diagnostic` for
30-
/// fatal/errors/warnings and `LintDiagnostic` for lints.
67+
/// to diagnostic methods for generated diagnostic derives.
3168
pub(crate) struct DiagnosticDeriveVariantBuilder {
32-
/// The kind for the entire type.
33-
pub kind: DiagnosticDeriveKind,
34-
3569
/// Initialization of format strings for code suggestions.
3670
pub formatting_init: TokenStream,
3771

@@ -51,60 +85,6 @@ pub(crate) struct DiagnosticDeriveVariantBuilder {
5185
pub code: SpannedOption<()>,
5286
}
5387

54-
impl DiagnosticDeriveKind {
55-
/// Call `f` for the struct or for each variant of the enum, returning a `TokenStream` with the
56-
/// tokens from `f` wrapped in an `match` expression. Emits errors for use of derive on unions
57-
/// or attributes on the type itself when input is an enum.
58-
pub(crate) fn each_variant<'s, F>(self, structure: &mut Structure<'s>, f: F) -> TokenStream
59-
where
60-
F: for<'v> Fn(DiagnosticDeriveVariantBuilder, &VariantInfo<'v>) -> TokenStream,
61-
{
62-
let ast = structure.ast();
63-
let span = ast.span().unwrap();
64-
match ast.data {
65-
syn::Data::Struct(..) | syn::Data::Enum(..) => (),
66-
syn::Data::Union(..) => {
67-
span_err(span, "diagnostic derives can only be used on structs and enums").emit();
68-
}
69-
}
70-
71-
if matches!(ast.data, syn::Data::Enum(..)) {
72-
for attr in &ast.attrs {
73-
span_err(
74-
attr.span().unwrap(),
75-
"unsupported type attribute for diagnostic derive enum",
76-
)
77-
.emit();
78-
}
79-
}
80-
81-
structure.bind_with(|_| synstructure::BindStyle::Move);
82-
let variants = structure.each_variant(|variant| {
83-
let span = match structure.ast().data {
84-
syn::Data::Struct(..) => span,
85-
// There isn't a good way to get the span of the variant, so the variant's
86-
// name will need to do.
87-
_ => variant.ast().ident.span().unwrap(),
88-
};
89-
let builder = DiagnosticDeriveVariantBuilder {
90-
kind: self,
91-
span,
92-
field_map: build_field_mapping(variant),
93-
formatting_init: TokenStream::new(),
94-
message: None,
95-
code: None,
96-
};
97-
f(builder, variant)
98-
});
99-
100-
quote! {
101-
match self {
102-
#variants
103-
}
104-
}
105-
}
106-
}
107-
10888
impl DiagnosticDeriveVariantBuilder {
10989
pub(crate) fn primary_message(&self) -> Option<&Message> {
11090
match self.message.as_ref() {
@@ -358,20 +338,11 @@ impl DiagnosticDeriveVariantBuilder {
358338
// `arg` call will not be generated.
359339
(Meta::Path(_), "skip_arg") => return Ok(quote! {}),
360340
(Meta::Path(_), "primary_span") => {
361-
match self.kind {
362-
DiagnosticDeriveKind::Diagnostic => {
363-
report_error_if_not_applied_to_span(attr, &info)?;
341+
report_error_if_not_applied_to_span(attr, &info)?;
364342

365-
return Ok(quote! {
366-
diag.span(#binding);
367-
});
368-
}
369-
DiagnosticDeriveKind::LintDiagnostic => {
370-
throw_invalid_attr!(attr, |diag| {
371-
diag.help("the `primary_span` field attribute is not valid for lint diagnostics")
372-
})
373-
}
374-
}
343+
return Ok(quote! {
344+
diag.span(#binding);
345+
});
375346
}
376347
(Meta::Path(_), "subdiagnostic") => {
377348
return Ok(quote! { diag.subdiagnostic(#binding); });

compiler/rustc_macros/src/diagnostics/mod.rs

Lines changed: 2 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ mod msg_macro;
66
mod subdiagnostic;
77
mod utils;
88

9-
use diagnostic::{DiagnosticDerive, LintDiagnosticDerive};
9+
use diagnostic::DiagnosticDerive;
1010
pub(super) use msg_macro::msg_macro;
1111
use proc_macro2::TokenStream;
1212
use subdiagnostic::SubdiagnosticDerive;
@@ -51,38 +51,6 @@ pub(super) fn diagnostic_derive(s: Structure<'_>) -> TokenStream {
5151
DiagnosticDerive::new(s).into_tokens()
5252
}
5353

54-
/// Implements `#[derive(LintDiagnostic)]`, which allows for lints to be specified as a struct,
55-
/// independent from the actual lint emitting code.
56-
///
57-
/// ```ignore (rust)
58-
/// #[derive(LintDiagnostic)]
59-
/// #[diag("unused attribute")]
60-
/// pub(crate) struct UnusedAttribute {
61-
/// #[suggestion("remove this attribute", code = "", applicability = "machine-applicable")]
62-
/// pub this: Span,
63-
/// #[note("attribute also specified here")]
64-
/// pub other: Span,
65-
/// #[warning(
66-
/// "this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!"
67-
/// )]
68-
/// pub warning: bool,
69-
/// }
70-
/// ```
71-
///
72-
/// Then, later, to emit the error:
73-
///
74-
/// ```ignore (rust)
75-
/// cx.emit_span_lint(UNUSED_ATTRIBUTES, span, UnusedAttribute {
76-
/// ...
77-
/// });
78-
/// ```
79-
///
80-
/// See rustc dev guide for more examples on using the `#[derive(LintDiagnostic)]`:
81-
/// <https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-structs.html#reference>
82-
pub(super) fn lint_diagnostic_derive(s: Structure<'_>) -> TokenStream {
83-
LintDiagnosticDerive::new(s).into_tokens()
84-
}
85-
8654
/// Implements `#[derive(Subdiagnostic)]`, which allows for labels, notes, helps and
8755
/// suggestions to be specified as a structs or enums, independent from the actual diagnostics
8856
/// emitting code or diagnostic derives.
@@ -99,7 +67,7 @@ pub(super) fn lint_diagnostic_derive(s: Structure<'_>) -> TokenStream {
9967
/// Then, later, use the subdiagnostic in a diagnostic:
10068
///
10169
/// ```ignore (rust)
102-
/// #[derive(LintDiagnostic)]
70+
/// #[derive(Diagnostic)]
10371
/// #[diag("unused doc comment")]
10472
/// pub(crate) struct BuiltinUnusedDocComment<'a> {
10573
/// pub kind: &'a str,

compiler/rustc_macros/src/lib.rs

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -196,25 +196,6 @@ decl_derive!(
196196
suggestion_hidden,
197197
suggestion_verbose)] => diagnostics::diagnostic_derive
198198
);
199-
decl_derive!(
200-
[LintDiagnostic, attributes(
201-
// struct attributes
202-
diag,
203-
help,
204-
help_once,
205-
note,
206-
note_once,
207-
warning,
208-
// field attributes
209-
skip_arg,
210-
primary_span,
211-
label,
212-
subdiagnostic,
213-
suggestion,
214-
suggestion_short,
215-
suggestion_hidden,
216-
suggestion_verbose)] => diagnostics::lint_diagnostic_derive
217-
);
218199
decl_derive!(
219200
[Subdiagnostic, attributes(
220201
// struct/variant attributes

compiler/rustc_middle/src/lint.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -492,8 +492,8 @@ pub fn lint_level(
492492
/// - [`TyCtxt::node_lint`]
493493
/// - `LintContext::opt_span_lint`
494494
///
495-
/// This function will replace `lint_level` once all `LintDiagnostic` items have been migrated to
496-
/// `Diagnostic`.
495+
/// This function will replace `lint_level` once all its callers have been replaced
496+
/// with `diag_lint_level`.
497497
#[track_caller]
498498
pub fn diag_lint_level<'a, D: Diagnostic<'a, ()> + 'a>(
499499
sess: &'a Session,

0 commit comments

Comments
 (0)