Skip to content

Commit d2375c2

Browse files
Rollup merge of #151338 - factor_slug, r=Kivooeo
Factor out diagnostic slug checking from `DiagnosticDerive` Doing some cleanup work in preparation for rust-lang/compiler-team#959 r? @Kivooeo
2 parents 3f01ca0 + 7ec4a8e commit d2375c2

3 files changed

Lines changed: 67 additions & 84 deletions

File tree

compiler/rustc_macros/src/diagnostics/diagnostic.rs

Lines changed: 17 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,10 @@ use std::cell::RefCell;
44

55
use proc_macro2::TokenStream;
66
use quote::quote;
7-
use syn::spanned::Spanned;
87
use synstructure::Structure;
98

109
use crate::diagnostics::diagnostic_builder::DiagnosticDeriveKind;
11-
use crate::diagnostics::error::{DiagnosticDeriveError, span_err};
12-
use crate::diagnostics::utils::SetOnce;
10+
use crate::diagnostics::error::DiagnosticDeriveError;
1311

1412
/// The central struct for constructing the `into_diag` method from an annotated struct.
1513
pub(crate) struct DiagnosticDerive<'a> {
@@ -29,36 +27,16 @@ impl<'a> DiagnosticDerive<'a> {
2927
let preamble = builder.preamble(variant);
3028
let body = builder.body(variant);
3129

32-
let init = match builder.slug.value_ref() {
33-
None => {
34-
span_err(builder.span, "diagnostic slug not specified")
35-
.help(
36-
"specify the slug as the first argument to the `#[diag(...)]` \
37-
attribute, such as `#[diag(hir_analysis_example_error)]`",
38-
)
39-
.emit();
40-
return DiagnosticDeriveError::ErrorHandled.to_compile_error();
41-
}
42-
Some(slug)
43-
if let Some(Mismatch { slug_name, crate_name, slug_prefix }) =
44-
Mismatch::check(slug) =>
45-
{
46-
span_err(slug.span().unwrap(), "diagnostic slug and crate name do not match")
47-
.note(format!("slug is `{slug_name}` but the crate name is `{crate_name}`"))
48-
.help(format!("expected a slug starting with `{slug_prefix}_...`"))
49-
.emit();
50-
return DiagnosticDeriveError::ErrorHandled.to_compile_error();
51-
}
52-
Some(slug) => {
53-
slugs.borrow_mut().push(slug.clone());
54-
quote! {
55-
let mut diag = rustc_errors::Diag::new(
56-
dcx,
57-
level,
58-
crate::fluent_generated::#slug
59-
);
60-
}
61-
}
30+
let Some(slug) = builder.primary_message() else {
31+
return DiagnosticDeriveError::ErrorHandled.to_compile_error();
32+
};
33+
slugs.borrow_mut().push(slug.clone());
34+
let init = quote! {
35+
let mut diag = rustc_errors::Diag::new(
36+
dcx,
37+
level,
38+
crate::fluent_generated::#slug
39+
);
6240
};
6341

6442
let formatting_init = &builder.formatting_init;
@@ -113,32 +91,12 @@ impl<'a> LintDiagnosticDerive<'a> {
11391
let preamble = builder.preamble(variant);
11492
let body = builder.body(variant);
11593

116-
let primary_message = match builder.slug.value_ref() {
117-
None => {
118-
span_err(builder.span, "diagnostic slug not specified")
119-
.help(
120-
"specify the slug as the first argument to the attribute, such as \
121-
`#[diag(compiletest_example)]`",
122-
)
123-
.emit();
124-
DiagnosticDeriveError::ErrorHandled.to_compile_error()
125-
}
126-
Some(slug)
127-
if let Some(Mismatch { slug_name, crate_name, slug_prefix }) =
128-
Mismatch::check(slug) =>
129-
{
130-
span_err(slug.span().unwrap(), "diagnostic slug and crate name do not match")
131-
.note(format!("slug is `{slug_name}` but the crate name is `{crate_name}`"))
132-
.help(format!("expected a slug starting with `{slug_prefix}_...`"))
133-
.emit();
134-
DiagnosticDeriveError::ErrorHandled.to_compile_error()
135-
}
136-
Some(slug) => {
137-
slugs.borrow_mut().push(slug.clone());
138-
quote! {
139-
diag.primary_message(crate::fluent_generated::#slug);
140-
}
141-
}
94+
let Some(slug) = builder.primary_message() else {
95+
return DiagnosticDeriveError::ErrorHandled.to_compile_error();
96+
};
97+
slugs.borrow_mut().push(slug.clone());
98+
let primary_message = quote! {
99+
diag.primary_message(crate::fluent_generated::#slug);
142100
};
143101

144102
let formatting_init = &builder.formatting_init;
@@ -172,30 +130,6 @@ impl<'a> LintDiagnosticDerive<'a> {
172130
}
173131
}
174132

175-
struct Mismatch {
176-
slug_name: String,
177-
crate_name: String,
178-
slug_prefix: String,
179-
}
180-
181-
impl Mismatch {
182-
/// Checks whether the slug starts with the crate name it's in.
183-
fn check(slug: &syn::Path) -> Option<Mismatch> {
184-
// If this is missing we're probably in a test, so bail.
185-
let crate_name = std::env::var("CARGO_CRATE_NAME").ok()?;
186-
187-
// If we're not in a "rustc_" crate, bail.
188-
let Some(("rustc", slug_prefix)) = crate_name.split_once('_') else { return None };
189-
190-
let slug_name = slug.segments.first()?.ident.to_string();
191-
if !slug_name.starts_with(slug_prefix) {
192-
Some(Mismatch { slug_name, slug_prefix: slug_prefix.to_string(), crate_name })
193-
} else {
194-
None
195-
}
196-
}
197-
}
198-
199133
/// Generates a `#[test]` that verifies that all referenced variables
200134
/// exist on this structure.
201135
fn generate_test(slug: &syn::Path, structure: &Structure<'_>) -> TokenStream {

compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,31 @@ impl DiagnosticDeriveKind {
110110
}
111111

112112
impl DiagnosticDeriveVariantBuilder {
113+
pub(crate) fn primary_message(&self) -> Option<&Path> {
114+
match self.slug.value_ref() {
115+
None => {
116+
span_err(self.span, "diagnostic slug not specified")
117+
.help(
118+
"specify the slug as the first argument to the `#[diag(...)]` \
119+
attribute, such as `#[diag(hir_analysis_example_error)]`",
120+
)
121+
.emit();
122+
None
123+
}
124+
Some(slug)
125+
if let Some(Mismatch { slug_name, crate_name, slug_prefix }) =
126+
Mismatch::check(slug) =>
127+
{
128+
span_err(slug.span().unwrap(), "diagnostic slug and crate name do not match")
129+
.note(format!("slug is `{slug_name}` but the crate name is `{crate_name}`"))
130+
.help(format!("expected a slug starting with `{slug_prefix}_...`"))
131+
.emit();
132+
None
133+
}
134+
Some(slug) => Some(slug),
135+
}
136+
}
137+
113138
/// Generates calls to `code` and similar functions based on the attributes on the type or
114139
/// variant.
115140
pub(crate) fn preamble(&mut self, variant: &VariantInfo<'_>) -> TokenStream {
@@ -504,3 +529,27 @@ impl DiagnosticDeriveVariantBuilder {
504529
}
505530
}
506531
}
532+
533+
struct Mismatch {
534+
slug_name: String,
535+
crate_name: String,
536+
slug_prefix: String,
537+
}
538+
539+
impl Mismatch {
540+
/// Checks whether the slug starts with the crate name it's in.
541+
fn check(slug: &syn::Path) -> Option<Mismatch> {
542+
// If this is missing we're probably in a test, so bail.
543+
let crate_name = std::env::var("CARGO_CRATE_NAME").ok()?;
544+
545+
// If we're not in a "rustc_" crate, bail.
546+
let Some(("rustc", slug_prefix)) = crate_name.split_once('_') else { return None };
547+
548+
let slug_name = slug.segments.first()?.ident.to_string();
549+
if slug_name.starts_with(slug_prefix) {
550+
return None;
551+
}
552+
553+
Some(Mismatch { slug_name, slug_prefix: slug_prefix.to_string(), crate_name })
554+
}
555+
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ error: derive(Diagnostic): diagnostic slug not specified
384384
LL | #[lint(no_crate_example, code = E0123)]
385385
| ^
386386
|
387-
= help: specify the slug as the first argument to the attribute, such as `#[diag(compiletest_example)]`
387+
= help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
388388

389389
error: derive(Diagnostic): attribute specified multiple times
390390
--> $DIR/diagnostic-derive.rs:613:53

0 commit comments

Comments
 (0)