Skip to content

Commit 124aad3

Browse files
authored
Rollup merge of rust-lang#111032 - clubby789:migrate-asm-diagnostics, r=compiler-errors
Migrate `builtin_macros::asm` diagnostics to translatable diagnostics cc rust-lang#100717 Planning on working through the remaining diagnostics in this crate
2 parents bde3cbd + 3738a18 commit 124aad3

File tree

3 files changed

+179
-72
lines changed

3 files changed

+179
-72
lines changed

compiler/rustc_builtin_macros/messages.ftl

+35
Original file line numberDiff line numberDiff line change
@@ -169,5 +169,40 @@ builtin_macros_asm_pure_no_output = asm with the `pure` option must have at leas
169169
170170
builtin_macros_asm_modifier_invalid = asm template modifier must be a single character
171171
172+
builtin_macros_asm_requires_template = requires at least a template string argument
173+
174+
builtin_macros_asm_expected_comma = expected token: `,`
175+
.label = expected `,`
176+
177+
builtin_macros_asm_underscore_input = _ cannot be used for input operands
178+
179+
builtin_macros_asm_sym_no_path = expected a path for argument to `sym`
180+
181+
builtin_macros_asm_expected_other = expected operand, {$is_global_asm ->
182+
[true] options
183+
*[false] clobber_abi, options
184+
}, or additional template string
185+
186+
builtin_macros_asm_duplicate_arg = duplicate argument named `{$name}`
187+
.label = previously here
188+
.arg = duplicate argument
189+
190+
builtin_macros_asm_pos_after = positional arguments cannot follow named arguments or explicit register arguments
191+
.pos = positional argument
192+
.named = named argument
193+
.explicit = explicit register argument
194+
195+
builtin_macros_asm_noreturn = asm outputs are not allowed with the `noreturn` option
196+
197+
builtin_macros_global_asm_clobber_abi = `clobber_abi` cannot be used with `global_asm!`
198+
199+
builtin_macros_asm_clobber_no_reg = asm with `clobber_abi` must specify explicit registers for outputs
200+
builtin_macros_asm_clobber_abi = clobber_abi
201+
builtin_macros_asm_clobber_outputs = generic outputs
202+
203+
builtin_macros_asm_opt_already_provided = the `{$symbol}` option was already provided
204+
.label = this option was already provided
205+
.suggestion = remove this option
206+
172207
builtin_macros_test_runner_invalid = `test_runner` argument must be a path
173208
builtin_macros_test_runner_nargs = `#![test_runner(..)]` accepts exactly 1 argument

compiler/rustc_builtin_macros/src/asm.rs

+26-67
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use rustc_ast::ptr::P;
33
use rustc_ast::token::{self, Delimiter};
44
use rustc_ast::tokenstream::TokenStream;
55
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
6-
use rustc_errors::{Applicability, PResult};
6+
use rustc_errors::PResult;
77
use rustc_expand::base::{self, *};
88
use rustc_parse::parser::Parser;
99
use rustc_parse_format as parse;
@@ -49,7 +49,7 @@ pub fn parse_asm_args<'a>(
4949
let diag = &sess.span_diagnostic;
5050

5151
if p.token == token::Eof {
52-
return Err(diag.struct_span_err(sp, "requires at least a template string argument"));
52+
return Err(diag.create_err(errors::AsmRequiresTemplate { span: sp }));
5353
}
5454

5555
let first_template = p.parse_expr()?;
@@ -68,8 +68,7 @@ pub fn parse_asm_args<'a>(
6868
if !p.eat(&token::Comma) {
6969
if allow_templates {
7070
// After a template string, we always expect *only* a comma...
71-
let mut err = diag.struct_span_err(p.token.span, "expected token: `,`");
72-
err.span_label(p.token.span, "expected `,`");
71+
let mut err = diag.create_err(errors::AsmExpectedComma { span: p.token.span });
7372
p.maybe_annotate_with_ascription(&mut err, false);
7473
return Err(err);
7574
} else {
@@ -112,7 +111,7 @@ pub fn parse_asm_args<'a>(
112111
let op = if !is_global_asm && p.eat_keyword(kw::In) {
113112
let reg = parse_reg(p, &mut explicit_reg)?;
114113
if p.eat_keyword(kw::Underscore) {
115-
let err = diag.struct_span_err(p.token.span, "_ cannot be used for input operands");
114+
let err = diag.create_err(errors::AsmUnderscoreInput { span: p.token.span });
116115
return Err(err);
117116
}
118117
let expr = p.parse_expr()?;
@@ -128,7 +127,7 @@ pub fn parse_asm_args<'a>(
128127
} else if !is_global_asm && p.eat_keyword(sym::inout) {
129128
let reg = parse_reg(p, &mut explicit_reg)?;
130129
if p.eat_keyword(kw::Underscore) {
131-
let err = diag.struct_span_err(p.token.span, "_ cannot be used for input operands");
130+
let err = diag.create_err(errors::AsmUnderscoreInput { span: p.token.span });
132131
return Err(err);
133132
}
134133
let expr = p.parse_expr()?;
@@ -142,7 +141,7 @@ pub fn parse_asm_args<'a>(
142141
} else if !is_global_asm && p.eat_keyword(sym::inlateout) {
143142
let reg = parse_reg(p, &mut explicit_reg)?;
144143
if p.eat_keyword(kw::Underscore) {
145-
let err = diag.struct_span_err(p.token.span, "_ cannot be used for input operands");
144+
let err = diag.create_err(errors::AsmUnderscoreInput { span: p.token.span });
146145
return Err(err);
147146
}
148147
let expr = p.parse_expr()?;
@@ -160,7 +159,7 @@ pub fn parse_asm_args<'a>(
160159
let expr = p.parse_expr()?;
161160
let ast::ExprKind::Path(qself, path) = &expr.kind else {
162161
let err = diag
163-
.struct_span_err(expr.span, "expected a path for argument to `sym`");
162+
.create_err(errors::AsmSymNoPath { span: expr.span });
164163
return Err(err);
165164
};
166165
let sym = ast::InlineAsmSym {
@@ -181,13 +180,10 @@ pub fn parse_asm_args<'a>(
181180
) => {}
182181
ast::ExprKind::MacCall(..) => {}
183182
_ => {
184-
let errstr = if is_global_asm {
185-
"expected operand, options, or additional template string"
186-
} else {
187-
"expected operand, clobber_abi, options, or additional template string"
188-
};
189-
let mut err = diag.struct_span_err(template.span, errstr);
190-
err.span_label(template.span, errstr);
183+
let err = diag.create_err(errors::AsmExpectedOther {
184+
span: template.span,
185+
is_global_asm,
186+
});
191187
return Err(err);
192188
}
193189
}
@@ -212,28 +208,16 @@ pub fn parse_asm_args<'a>(
212208
args.reg_args.insert(slot);
213209
} else if let Some(name) = name {
214210
if let Some(&prev) = args.named_args.get(&name) {
215-
diag.struct_span_err(span, &format!("duplicate argument named `{}`", name))
216-
.span_label(args.operands[prev].1, "previously here")
217-
.span_label(span, "duplicate argument")
218-
.emit();
211+
diag.emit_err(errors::AsmDuplicateArg { span, name, prev: args.operands[prev].1 });
219212
continue;
220213
}
221214
args.named_args.insert(name, slot);
222215
} else {
223216
if !args.named_args.is_empty() || !args.reg_args.is_empty() {
224-
let mut err = diag.struct_span_err(
225-
span,
226-
"positional arguments cannot follow named arguments \
227-
or explicit register arguments",
228-
);
229-
err.span_label(span, "positional argument");
230-
for pos in args.named_args.values() {
231-
err.span_label(args.operands[*pos].1, "named argument");
232-
}
233-
for pos in &args.reg_args {
234-
err.span_label(args.operands[*pos].1, "explicit register argument");
235-
}
236-
err.emit();
217+
let named = args.named_args.values().map(|p| args.operands[*p].1).collect();
218+
let explicit = args.reg_args.iter().map(|p| args.operands[*p].1).collect();
219+
220+
diag.emit_err(errors::AsmPositionalAfter { span, named, explicit });
237221
}
238222
}
239223
}
@@ -284,34 +268,25 @@ pub fn parse_asm_args<'a>(
284268
diag.emit_err(errors::AsmPureNoOutput { spans: args.options_spans.clone() });
285269
}
286270
if args.options.contains(ast::InlineAsmOptions::NORETURN) && !outputs_sp.is_empty() {
287-
let err = diag
288-
.struct_span_err(outputs_sp, "asm outputs are not allowed with the `noreturn` option");
289-
271+
let err = diag.create_err(errors::AsmNoReturn { outputs_sp });
290272
// Bail out now since this is likely to confuse MIR
291273
return Err(err);
292274
}
293275

294276
if args.clobber_abis.len() > 0 {
295277
if is_global_asm {
296-
let err = diag.struct_span_err(
297-
args.clobber_abis.iter().map(|(_, span)| *span).collect::<Vec<Span>>(),
298-
"`clobber_abi` cannot be used with `global_asm!`",
299-
);
278+
let err = diag.create_err(errors::GlobalAsmClobberAbi {
279+
spans: args.clobber_abis.iter().map(|(_, span)| *span).collect(),
280+
});
300281

301282
// Bail out now since this is likely to confuse later stages
302283
return Err(err);
303284
}
304285
if !regclass_outputs.is_empty() {
305-
diag.struct_span_err(
306-
regclass_outputs.clone(),
307-
"asm with `clobber_abi` must specify explicit registers for outputs",
308-
)
309-
.span_labels(
310-
args.clobber_abis.iter().map(|(_, span)| *span).collect::<Vec<Span>>(),
311-
"clobber_abi",
312-
)
313-
.span_labels(regclass_outputs, "generic outputs")
314-
.emit();
286+
diag.emit_err(errors::AsmClobberNoReg {
287+
spans: regclass_outputs,
288+
clobbers: args.clobber_abis.iter().map(|(_, span)| *span).collect(),
289+
});
315290
}
316291
}
317292

@@ -323,25 +298,9 @@ pub fn parse_asm_args<'a>(
323298
/// This function must be called immediately after the option token is parsed.
324299
/// Otherwise, the suggestion will be incorrect.
325300
fn err_duplicate_option(p: &mut Parser<'_>, symbol: Symbol, span: Span) {
326-
let mut err = p
327-
.sess
328-
.span_diagnostic
329-
.struct_span_err(span, &format!("the `{}` option was already provided", symbol));
330-
err.span_label(span, "this option was already provided");
331-
332301
// Tool-only output
333-
let mut full_span = span;
334-
if p.token.kind == token::Comma {
335-
full_span = full_span.to(p.token.span);
336-
}
337-
err.tool_only_span_suggestion(
338-
full_span,
339-
"remove this option",
340-
"",
341-
Applicability::MachineApplicable,
342-
);
343-
344-
err.emit();
302+
let full_span = if p.token.kind == token::Comma { span.to(p.token.span) } else { span };
303+
p.sess.span_diagnostic.emit_err(errors::AsmOptAlreadyprovided { span, symbol, full_span });
345304
}
346305

347306
/// Try to set the provided option in the provided `AsmArgs`.

compiler/rustc_builtin_macros/src/errors.rs

+118-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use rustc_errors::{
2-
AddToDiagnostic, EmissionGuarantee, IntoDiagnostic, MultiSpan, SingleLabelManySpans,
2+
AddToDiagnostic, DiagnosticBuilder, EmissionGuarantee, Handler, IntoDiagnostic, MultiSpan,
3+
SingleLabelManySpans,
34
};
45
use rustc_macros::{Diagnostic, Subdiagnostic};
56
use rustc_span::{symbol::Ident, Span, Symbol};
@@ -370,11 +371,12 @@ pub(crate) struct EnvNotDefined {
370371
// Hand-written implementation to support custom user messages
371372
impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for EnvNotDefined {
372373
#[track_caller]
373-
fn into_diagnostic(
374-
self,
375-
handler: &'a rustc_errors::Handler,
376-
) -> rustc_errors::DiagnosticBuilder<'a, G> {
374+
fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, G> {
377375
let mut diag = if let Some(msg) = self.msg {
376+
#[expect(
377+
rustc::untranslatable_diagnostic,
378+
reason = "cannot translate user-provided messages"
379+
)]
378380
handler.struct_diagnostic(msg.as_str())
379381
} else {
380382
handler.struct_diagnostic(crate::fluent_generated::builtin_macros_env_not_defined)
@@ -606,6 +608,117 @@ pub(crate) struct AsmModifierInvalid {
606608
pub(crate) span: Span,
607609
}
608610

611+
#[derive(Diagnostic)]
612+
#[diag(builtin_macros_asm_requires_template)]
613+
pub(crate) struct AsmRequiresTemplate {
614+
#[primary_span]
615+
pub(crate) span: Span,
616+
}
617+
618+
#[derive(Diagnostic)]
619+
#[diag(builtin_macros_asm_expected_comma)]
620+
pub(crate) struct AsmExpectedComma {
621+
#[primary_span]
622+
#[label]
623+
pub(crate) span: Span,
624+
}
625+
626+
#[derive(Diagnostic)]
627+
#[diag(builtin_macros_asm_underscore_input)]
628+
pub(crate) struct AsmUnderscoreInput {
629+
#[primary_span]
630+
pub(crate) span: Span,
631+
}
632+
633+
#[derive(Diagnostic)]
634+
#[diag(builtin_macros_asm_sym_no_path)]
635+
pub(crate) struct AsmSymNoPath {
636+
#[primary_span]
637+
pub(crate) span: Span,
638+
}
639+
640+
#[derive(Diagnostic)]
641+
#[diag(builtin_macros_asm_expected_other)]
642+
pub(crate) struct AsmExpectedOther {
643+
#[primary_span]
644+
#[label(builtin_macros_asm_expected_other)]
645+
pub(crate) span: Span,
646+
pub(crate) is_global_asm: bool,
647+
}
648+
649+
#[derive(Diagnostic)]
650+
#[diag(builtin_macros_asm_duplicate_arg)]
651+
pub(crate) struct AsmDuplicateArg {
652+
#[primary_span]
653+
#[label(builtin_macros_arg)]
654+
pub(crate) span: Span,
655+
#[label]
656+
pub(crate) prev: Span,
657+
pub(crate) name: Symbol,
658+
}
659+
660+
#[derive(Diagnostic)]
661+
#[diag(builtin_macros_asm_pos_after)]
662+
pub(crate) struct AsmPositionalAfter {
663+
#[primary_span]
664+
#[label(builtin_macros_pos)]
665+
pub(crate) span: Span,
666+
#[label(builtin_macros_named)]
667+
pub(crate) named: Vec<Span>,
668+
#[label(builtin_macros_explicit)]
669+
pub(crate) explicit: Vec<Span>,
670+
}
671+
672+
#[derive(Diagnostic)]
673+
#[diag(builtin_macros_asm_noreturn)]
674+
pub(crate) struct AsmNoReturn {
675+
#[primary_span]
676+
pub(crate) outputs_sp: Vec<Span>,
677+
}
678+
679+
#[derive(Diagnostic)]
680+
#[diag(builtin_macros_global_asm_clobber_abi)]
681+
pub(crate) struct GlobalAsmClobberAbi {
682+
#[primary_span]
683+
pub(crate) spans: Vec<Span>,
684+
}
685+
686+
pub(crate) struct AsmClobberNoReg {
687+
pub(crate) spans: Vec<Span>,
688+
pub(crate) clobbers: Vec<Span>,
689+
}
690+
691+
impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for AsmClobberNoReg {
692+
fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, G> {
693+
let mut diag =
694+
handler.struct_diagnostic(crate::fluent_generated::builtin_macros_asm_clobber_no_reg);
695+
diag.set_span(self.spans.clone());
696+
// eager translation as `span_labels` takes `AsRef<str>`
697+
let lbl1 = handler.eagerly_translate_to_string(
698+
crate::fluent_generated::builtin_macros_asm_clobber_abi,
699+
[].into_iter(),
700+
);
701+
diag.span_labels(self.clobbers, &lbl1);
702+
let lbl2 = handler.eagerly_translate_to_string(
703+
crate::fluent_generated::builtin_macros_asm_clobber_outputs,
704+
[].into_iter(),
705+
);
706+
diag.span_labels(self.spans, &lbl2);
707+
diag
708+
}
709+
}
710+
711+
#[derive(Diagnostic)]
712+
#[diag(builtin_macros_asm_opt_already_provided)]
713+
pub(crate) struct AsmOptAlreadyprovided {
714+
#[primary_span]
715+
#[label]
716+
pub(crate) span: Span,
717+
pub(crate) symbol: Symbol,
718+
#[suggestion(code = "", applicability = "machine-applicable", style = "tool-only")]
719+
pub(crate) full_span: Span,
720+
}
721+
609722
#[derive(Diagnostic)]
610723
#[diag(builtin_macros_test_runner_invalid)]
611724
pub(crate) struct TestRunnerInvalid {

0 commit comments

Comments
 (0)