Skip to content

Commit a703f75

Browse files
Rollup merge of #157070 - GuillaumeGomez:rm-skip_arg, r=JonathanBrouwer
Remove `skip_arg` attribute from `Diagnostic` and `Subdiagnostic` proc-macros Instead of having users to manually add `#[skip_arg]` for each field that is not used in fluent messages, I think it's better to instead let the proc-macro only call `diag.arg("name", field)` on the fields actually used. r? @JonathanBrouwer
2 parents c93a807 + 579831c commit a703f75

24 files changed

Lines changed: 286 additions & 273 deletions

File tree

compiler/rustc_const_eval/src/const_eval/machine.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -844,14 +844,13 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
844844
// current number of evaluated terminators is a power of 2. The latter gives us a cheap
845845
// way to implement exponential backoff.
846846
let span = ecx.cur_span();
847+
let mut warn =
848+
ecx.tcx.dcx().create_warn(LongRunningWarn { span, item_span: ecx.tcx.span });
847849
// We store a unique number in `force_duplicate` to evade `-Z deduplicate-diagnostics`.
848850
// `new_steps` is guaranteed to be unique because `ecx.machine.num_evaluated_steps` is
849851
// always increasing.
850-
ecx.tcx.dcx().emit_warn(LongRunningWarn {
851-
span,
852-
item_span: ecx.tcx.span,
853-
force_duplicate: new_steps,
854-
});
852+
warn.arg("force_duplicate", new_steps);
853+
warn.emit();
855854
}
856855
}
857856

compiler/rustc_const_eval/src/errors.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -298,8 +298,6 @@ pub(crate) struct LongRunningWarn {
298298
pub span: Span,
299299
#[help("the constant being evaluated")]
300300
pub item_span: Span,
301-
// Used for evading `-Z deduplicate-diagnostics`.
302-
pub force_duplicate: usize,
303301
}
304302

305303
#[derive(Subdiagnostic)]

compiler/rustc_hir_typeck/src/callee.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -845,7 +845,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
845845
let mut path = None;
846846
let mut err = self.dcx().create_err(errors::InvalidCallee {
847847
span: callee_expr.span,
848-
ty: callee_ty,
849848
found: match &unit_variant {
850849
Some((_, kind, path)) => format!("{kind} `{path}`"),
851850
None => format!("`{}`", self.tcx.short_string(callee_ty, &mut path)),
@@ -949,7 +948,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
949948
}
950949

951950
if let Some(span) = self.tcx.hir_res_span(def) {
952-
let callee_ty = callee_ty.to_string();
953951
let label = match (unit_variant, inner_callee_path) {
954952
(Some((_, kind, path)), _) => {
955953
err.arg("kind", kind);
@@ -959,6 +957,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
959957
(_, Some(hir::QPath::Resolved(_, path))) => {
960958
self.tcx.sess.source_map().span_to_snippet(path.span).ok().map(|p| {
961959
err.arg("func", p);
960+
err.arg("ty", callee_ty);
962961
msg!("`{$func}` defined here returns `{$ty}`")
963962
})
964963
}
@@ -968,14 +967,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
968967
// type definitions themselves, but rather variables *of* that type.
969968
Res::Local(hir_id) => {
970969
err.arg("local_name", self.tcx.hir_name(hir_id));
970+
err.arg("ty", callee_ty);
971971
Some(msg!("`{$local_name}` has type `{$ty}`"))
972972
}
973973
Res::Def(kind, def_id) if kind.ns() == Some(Namespace::ValueNS) => {
974974
err.arg("path", self.tcx.def_path_str(def_id));
975975
Some(msg!("`{$path}` defined here"))
976976
}
977977
_ => {
978-
err.arg("path", callee_ty);
978+
err.arg("path", callee_ty.to_string());
979979
Some(msg!("`{$path}` defined here"))
980980
}
981981
}

compiler/rustc_hir_typeck/src/errors.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -476,10 +476,9 @@ pub(crate) struct SlicingSuggestion {
476476

477477
#[derive(Diagnostic)]
478478
#[diag("expected function, found {$found}", code = E0618)]
479-
pub(crate) struct InvalidCallee<'tcx> {
479+
pub(crate) struct InvalidCallee {
480480
#[primary_span]
481481
pub span: Span,
482-
pub ty: Ty<'tcx>,
483482
pub found: String,
484483
}
485484

compiler/rustc_lint/src/lints.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1562,17 +1562,16 @@ pub(crate) enum NonCamelCaseTypeSub {
15621562
pub(crate) struct NonSnakeCaseDiag<'a> {
15631563
pub sort: &'a str,
15641564
pub name: &'a str,
1565-
pub sc: String,
15661565
#[subdiagnostic]
15671566
pub sub: NonSnakeCaseDiagSub,
15681567
}
15691568

15701569
pub(crate) enum NonSnakeCaseDiagSub {
15711570
Label { span: Span },
1572-
Help,
1571+
Help { sc: String },
15731572
RenameOrConvertSuggestion { span: Span, suggestion: Ident },
15741573
ConvertSuggestion { span: Span, suggestion: String },
1575-
SuggestionAndNote { span: Span },
1574+
SuggestionAndNote { sc: String, span: Span },
15761575
}
15771576

15781577
impl Subdiagnostic for NonSnakeCaseDiagSub {
@@ -1581,7 +1580,8 @@ impl Subdiagnostic for NonSnakeCaseDiagSub {
15811580
NonSnakeCaseDiagSub::Label { span } => {
15821581
diag.span_label(span, msg!("should have a snake_case name"));
15831582
}
1584-
NonSnakeCaseDiagSub::Help => {
1583+
NonSnakeCaseDiagSub::Help { sc } => {
1584+
diag.arg("sc", sc);
15851585
diag.help(msg!("convert the identifier to snake case: `{$sc}`"));
15861586
}
15871587
NonSnakeCaseDiagSub::ConvertSuggestion { span, suggestion } => {
@@ -1600,7 +1600,8 @@ impl Subdiagnostic for NonSnakeCaseDiagSub {
16001600
Applicability::MaybeIncorrect,
16011601
);
16021602
}
1603-
NonSnakeCaseDiagSub::SuggestionAndNote { span } => {
1603+
NonSnakeCaseDiagSub::SuggestionAndNote { sc, span } => {
1604+
diag.arg("sc", sc);
16041605
diag.note(msg!("`{$sc}` cannot be used as a raw identifier"));
16051606
diag.span_suggestion(
16061607
span,

compiler/rustc_lint/src/nonstandard_style.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -311,18 +311,18 @@ impl NonSnakeCase {
311311
suggestion: sc_ident,
312312
}
313313
} else {
314-
NonSnakeCaseDiagSub::SuggestionAndNote { span }
314+
NonSnakeCaseDiagSub::SuggestionAndNote { sc, span }
315315
}
316316
} else {
317-
NonSnakeCaseDiagSub::ConvertSuggestion { span, suggestion: sc.clone() }
317+
NonSnakeCaseDiagSub::ConvertSuggestion { span, suggestion: sc }
318318
}
319319
} else {
320-
NonSnakeCaseDiagSub::Help
320+
NonSnakeCaseDiagSub::Help { sc }
321321
}
322322
} else {
323323
NonSnakeCaseDiagSub::Label { span }
324324
};
325-
cx.emit_span_lint(NON_SNAKE_CASE, span, NonSnakeCaseDiag { sort, name, sc, sub });
325+
cx.emit_span_lint(NON_SNAKE_CASE, span, NonSnakeCaseDiag { sort, name, sub });
326326
}
327327
}
328328
}

compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,5 @@ struct OpaqueHiddenInferredBoundLint<'tcx> {
232232
struct AddBound<'tcx> {
233233
#[primary_span]
234234
suggest_span: Span,
235-
#[skip_arg]
236235
trait_ref: TraitPredPrintModifiersAndPath<'tcx>,
237236
}

compiler/rustc_macros/src/diagnostics/diagnostic.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ impl<'a> DiagnosticDerive<'a> {
2626
let Some(message) = builder.primary_message() else {
2727
return DiagnosticDeriveError::ErrorHandled.to_compile_error();
2828
};
29-
let message = message.diag_message(Some(variant));
29+
let message = message.diag_message();
3030

3131
let init = quote! {
3232
let mut diag = rustc_errors::Diag::new(

compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs

Lines changed: 41 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#![deny(unused_must_use)]
22

3+
use std::collections::HashSet;
4+
35
use proc_macro2::{Ident, Span, TokenStream};
46
use quote::{format_ident, quote, quote_spanned};
57
use syn::parse::ParseStream;
@@ -52,6 +54,7 @@ where
5254
formatting_init: TokenStream::new(),
5355
message: None,
5456
code: None,
57+
used_fields: HashSet::new(),
5558
};
5659
f(builder, variant)
5760
});
@@ -83,6 +86,8 @@ pub(crate) struct DiagnosticDeriveVariantBuilder {
8386
/// Error codes are a optional part of the struct attribute - this is only set to detect
8487
/// multiple specifications.
8588
pub code: SpannedOption<()>,
89+
90+
pub used_fields: HashSet<proc_macro2::Ident>,
8691
}
8792

8893
impl DiagnosticDeriveVariantBuilder {
@@ -107,8 +112,7 @@ impl DiagnosticDeriveVariantBuilder {
107112
let ast = variant.ast();
108113
let attrs = &ast.attrs;
109114
let preamble = attrs.iter().map(|attr| {
110-
self.generate_structure_code_for_attr(attr, variant)
111-
.unwrap_or_else(|v| v.to_compile_error())
115+
self.generate_structure_code_for_attr(attr).unwrap_or_else(|v| v.to_compile_error())
112116
});
113117

114118
quote! {
@@ -120,23 +124,34 @@ impl DiagnosticDeriveVariantBuilder {
120124
/// calls to `arg` when no attributes are present.
121125
pub(crate) fn body(&mut self, variant: &VariantInfo<'_>) -> TokenStream {
122126
let mut body = quote! {};
127+
let mut second_part = quote! {};
128+
129+
// Subdiagnostic additions.
130+
for binding in variant.bindings().iter().filter(|bi| !should_generate_arg(bi.ast())) {
131+
second_part.extend(self.generate_field_attrs_code(binding));
132+
}
123133
// Generate `arg` calls first..
124134
for binding in variant.bindings().iter().filter(|bi| should_generate_arg(bi.ast())) {
125-
body.extend(self.generate_field_code(binding));
126-
}
127-
// ..and then subdiagnostic additions.
128-
for binding in variant.bindings().iter().filter(|bi| !should_generate_arg(bi.ast())) {
129-
body.extend(self.generate_field_attrs_code(binding, variant));
135+
if self.is_used_in_message(binding) {
136+
body.extend(self.generate_field_code(binding));
137+
}
130138
}
139+
body.extend(second_part);
131140
body
132141
}
133142

143+
fn is_used_in_message(&self, binding: &BindingInfo<'_>) -> bool {
144+
binding.ast().ident.as_ref().is_some_and(|ident| self.used_fields.contains(ident))
145+
}
146+
134147
/// Parse a `SubdiagnosticKind` from an `Attribute`.
135148
fn parse_subdiag_attribute(
136-
&self,
149+
&mut self,
137150
attr: &Attribute,
138151
) -> Result<Option<(SubdiagnosticKind, Message, bool)>, DiagnosticDeriveError> {
139-
let Some(subdiag) = SubdiagnosticVariant::from_attr(attr, &self.field_map)? else {
152+
let Some(subdiag) =
153+
SubdiagnosticVariant::from_attr(attr, &self.field_map, &mut self.used_fields)?
154+
else {
140155
// Some attributes aren't errors - like documentation comments - but also aren't
141156
// subdiagnostics.
142157
return Ok(None);
@@ -160,7 +175,6 @@ impl DiagnosticDeriveVariantBuilder {
160175
fn generate_structure_code_for_attr(
161176
&mut self,
162177
attr: &Attribute,
163-
variant: &VariantInfo<'_>,
164178
) -> Result<TokenStream, DiagnosticDeriveError> {
165179
// Always allow documentation comments.
166180
if is_doc_comment(attr) {
@@ -183,11 +197,14 @@ impl DiagnosticDeriveVariantBuilder {
183197
)
184198
.emit();
185199
}
186-
self.message = Some(Message {
187-
attr_span: attr.span(),
188-
message_span: message.span(),
189-
value: message.value(),
190-
});
200+
let message = Message::new(
201+
attr.span(),
202+
message.span(),
203+
message.value(),
204+
&self.field_map,
205+
&mut self.used_fields,
206+
);
207+
self.message = Some(message);
191208
}
192209

193210
// Parse arguments
@@ -240,7 +257,7 @@ impl DiagnosticDeriveVariantBuilder {
240257
| SubdiagnosticKind::NoteOnce
241258
| SubdiagnosticKind::Help
242259
| SubdiagnosticKind::HelpOnce
243-
| SubdiagnosticKind::Warn => Ok(self.add_subdiagnostic(&fn_ident, message, variant)),
260+
| SubdiagnosticKind::Warn => Ok(self.add_subdiagnostic(&fn_ident, message)),
244261
SubdiagnosticKind::Label | SubdiagnosticKind::Suggestion { .. } => {
245262
throw_invalid_attr!(attr, |diag| diag
246263
.help("`#[label]` and `#[suggestion]` can only be applied to fields"));
@@ -268,11 +285,7 @@ impl DiagnosticDeriveVariantBuilder {
268285
}
269286
}
270287

271-
fn generate_field_attrs_code(
272-
&mut self,
273-
binding_info: &BindingInfo<'_>,
274-
variant: &VariantInfo<'_>,
275-
) -> TokenStream {
288+
fn generate_field_attrs_code(&mut self, binding_info: &BindingInfo<'_>) -> TokenStream {
276289
let field = binding_info.ast();
277290
let field_binding = &binding_info.binding;
278291

@@ -311,7 +324,6 @@ impl DiagnosticDeriveVariantBuilder {
311324
attr,
312325
FieldInfo { binding: binding_info, ty: inner_ty, span: &field.span() },
313326
binding,
314-
variant
315327
)
316328
.unwrap_or_else(|v| v.to_compile_error());
317329

@@ -329,14 +341,10 @@ impl DiagnosticDeriveVariantBuilder {
329341
attr: &Attribute,
330342
info: FieldInfo<'_>,
331343
binding: TokenStream,
332-
variant: &VariantInfo<'_>,
333344
) -> Result<TokenStream, DiagnosticDeriveError> {
334345
let ident = &attr.path().segments.last().unwrap().ident;
335346
let name = ident.to_string();
336347
match (&attr.meta, name.as_str()) {
337-
// Don't need to do anything - by virtue of the attribute existing, the
338-
// `arg` call will not be generated.
339-
(Meta::Path(_), "skip_arg") => return Ok(quote! {}),
340348
(Meta::Path(_), "primary_span") => {
341349
report_error_if_not_applied_to_span(attr, &info)?;
342350

@@ -359,7 +367,7 @@ impl DiagnosticDeriveVariantBuilder {
359367
match subdiag {
360368
SubdiagnosticKind::Label => {
361369
report_error_if_not_applied_to_span(attr, &info)?;
362-
Ok(self.add_spanned_subdiagnostic(binding, &fn_ident, message, variant))
370+
Ok(self.add_spanned_subdiagnostic(binding, &fn_ident, message))
363371
}
364372
SubdiagnosticKind::Note
365373
| SubdiagnosticKind::NoteOnce
@@ -370,11 +378,11 @@ impl DiagnosticDeriveVariantBuilder {
370378
if type_matches_path(inner, &["rustc_span", "Span"])
371379
|| type_matches_path(inner, &["rustc_span", "MultiSpan"])
372380
{
373-
Ok(self.add_spanned_subdiagnostic(binding, &fn_ident, message, variant))
381+
Ok(self.add_spanned_subdiagnostic(binding, &fn_ident, message))
374382
} else if type_is_unit(inner)
375383
|| (matches!(info.ty, FieldInnerTy::Plain(_)) && type_is_bool(inner))
376384
{
377-
Ok(self.add_subdiagnostic(&fn_ident, message, variant))
385+
Ok(self.add_subdiagnostic(&fn_ident, message))
378386
} else {
379387
report_type_error(attr, "`Span`, `MultiSpan`, `bool` or `()`")?
380388
}
@@ -400,7 +408,7 @@ impl DiagnosticDeriveVariantBuilder {
400408
applicability.set_once(quote! { #static_applicability }, span);
401409
}
402410

403-
let message = message.diag_message(Some(variant));
411+
let message = message.diag_message();
404412
let applicability = applicability
405413
.value()
406414
.unwrap_or_else(|| quote! { rustc_errors::Applicability::Unspecified });
@@ -428,10 +436,9 @@ impl DiagnosticDeriveVariantBuilder {
428436
field_binding: TokenStream,
429437
kind: &Ident,
430438
message: Message,
431-
variant: &VariantInfo<'_>,
432439
) -> TokenStream {
433440
let fn_name = format_ident!("span_{}", kind);
434-
let message = message.diag_message(Some(variant));
441+
let message = message.diag_message();
435442
quote! {
436443
diag.#fn_name(
437444
#field_binding,
@@ -442,13 +449,8 @@ impl DiagnosticDeriveVariantBuilder {
442449

443450
/// Adds a subdiagnostic by generating a `diag.span_$kind` call with the current message
444451
/// and `fluent_attr_identifier`.
445-
fn add_subdiagnostic(
446-
&self,
447-
kind: &Ident,
448-
message: Message,
449-
variant: &VariantInfo<'_>,
450-
) -> TokenStream {
451-
let message = message.diag_message(Some(variant));
452+
fn add_subdiagnostic(&self, kind: &Ident, message: Message) -> TokenStream {
453+
let message = message.diag_message();
452454
quote! {
453455
diag.#kind(#message);
454456
}

0 commit comments

Comments
 (0)