Skip to content

Commit 45749b2

Browse files
committed
Auto merge of rust-lang#110092 - clubby789:builtin-macros-translatable, r=compiler-errors
Migrate most of `rustc_builtin_macros` to diagnostic impls cc rust-lang#100717 This is a couple of days work, but I decided to stop for now before the PR becomes too big. There's around 50 unresolved failures when `rustc::untranslatable_diagnostic` is denied, which I'll finish addressing once this PR goes thtough A couple of outputs have changed, but in all instances I think the changes are an improvement/are more consistent with other diagnostics (although I'm happy to revert any which seem worse)
2 parents dfe024e + 64f7597 commit 45749b2

31 files changed

+978
-349
lines changed

compiler/rustc_builtin_macros/messages.ftl

+146
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,149 @@ builtin_macros_requires_cfg_pattern =
33
.label = cfg-pattern required
44
55
builtin_macros_expected_one_cfg_pattern = expected 1 cfg-pattern
6+
7+
builtin_macros_alloc_error_must_be_fn = alloc_error_handler must be a function
8+
9+
builtin_macros_assert_requires_boolean = macro requires a boolean expression as an argument
10+
.label = boolean expression required
11+
12+
builtin_macros_assert_requires_expression = macro requires an expression as an argument
13+
.suggestion = try removing semicolon
14+
15+
builtin_macros_assert_missing_comma = unexpected string literal
16+
.suggestion = try adding a comma
17+
18+
builtin_macros_cfg_accessible_unspecified_path = `cfg_accessible` path is not specified
19+
builtin_macros_cfg_accessible_multiple_paths = multiple `cfg_accessible` paths are specified
20+
builtin_macros_cfg_accessible_literal_path = `cfg_accessible` path cannot be a literal
21+
builtin_macros_cfg_accessible_has_args = `cfg_accessible` path cannot accept arguments
22+
23+
builtin_macros_cfg_accessible_indeterminate = cannot determine whether the path is accessible or not
24+
25+
builtin_macros_concat_bytestr = cannot concatenate a byte string literal
26+
27+
builtin_macros_concat_missing_literal = expected a literal
28+
.note = only literals (like `"foo"`, `-42` and `3.14`) can be passed to `concat!()`
29+
30+
builtin_macros_concat_bytes_missing_literal = expected a byte literal
31+
.note = only byte literals (like `b"foo"`, `b's'` and `[3, 4, 5]`) can be passed to `concat_bytes!()`
32+
33+
builtin_macros_concat_bytes_invalid = cannot concatenate {$lit_kind} literals
34+
.byte_char = try using a byte character
35+
.byte_str = try using a byte string
36+
.number_array = try wrapping the number in an array
37+
38+
builtin_macros_concat_bytes_oob = numeric literal is out of bounds
39+
40+
builtin_macros_concat_bytes_non_u8 = numeric literal is not a `u8`
41+
42+
builtin_macros_concat_bytes_array = cannot concatenate doubly nested array
43+
.note = byte strings are treated as arrays of bytes
44+
.help = try flattening the array
45+
46+
builtin_macros_concat_bytes_bad_repeat = repeat count is not a positive number
47+
48+
builtin_macros_concat_idents_missing_args = `concat_idents!()` takes 1 or more arguments
49+
builtin_macros_concat_idents_missing_comma = `concat_idents!()` expecting comma
50+
builtin_macros_concat_idents_ident_args = `concat_idents!()` requires ident args
51+
52+
builtin_macros_bad_derive_target = `derive` may only be applied to `struct`s, `enum`s and `union`s
53+
.label = not applicable here
54+
.label2 = not a `struct`, `enum` or `union`
55+
56+
builtin_macros_unexpected_lit = expected path to a trait, found literal
57+
.label = not a trait
58+
.str_lit = try using `#[derive({$sym})]`
59+
.other = for example, write `#[derive(Debug)]` for `Debug`
60+
61+
builtin_macros_derive_path_args_list = traits in `#[derive(...)]` don't accept arguments
62+
.suggestion = remove the arguments
63+
64+
builtin_macros_derive_path_args_value = traits in `#[derive(...)]` don't accept values
65+
.suggestion = remove the value
66+
67+
builtin_macros_derive_macro_call = `derive` cannot be used on items with type macros
68+
69+
builtin_macros_cannot_derive_union = this trait cannot be derived for unions
70+
71+
builtin_macros_no_default_variant = no default declared
72+
.help = make a unit variant default by placing `#[default]` above it
73+
.suggestion = make `{$ident}` default
74+
75+
builtin_macros_multiple_defaults = multiple declared defaults
76+
.label = first default
77+
.additional = additional default
78+
.note = only one variant can be default
79+
.suggestion = make `{$ident}` default
80+
81+
builtin_macros_non_unit_default = the `#[default]` attribute may only be used on unit enum variants
82+
.help = consider a manual implementation of `Default`
83+
84+
builtin_macros_non_exhaustive_default = default variant must be exhaustive
85+
.label = declared `#[non_exhaustive]` here
86+
.help = consider a manual implementation of `Default`
87+
88+
builtin_macros_multiple_default_attrs = multiple `#[default]` attributes
89+
.note = only one `#[default]` attribute is needed
90+
.label = `#[default]` used here
91+
.label_again = `#[default]` used again here
92+
.help = try removing {$only_one ->
93+
[true] this
94+
*[false] these
95+
}
96+
97+
builtin_macros_default_arg = `#[default]` attribute does not accept a value
98+
.suggestion = try using `#[default]`
99+
100+
builtin_macros_env_takes_args = `env!()` takes 1 or 2 arguments
101+
102+
builtin_macros_env_not_defined = environment variable `{$var}` not defined at compile time
103+
.cargo = Cargo sets build script variables at run time. Use `std::env::var("{$var}")` instead
104+
.other = use `std::env::var("{$var}")` to read the variable at run time
105+
106+
builtin_macros_format_requires_string = requires at least a format string argument
107+
108+
builtin_macros_format_duplicate_arg = duplicate argument named `{$ident}`
109+
.label1 = previously here
110+
.label2 = duplicate argument
111+
112+
builtin_macros_format_positional_after_named = positional arguments cannot follow named arguments
113+
.label = positional arguments must be before named arguments
114+
.named_args = named argument
115+
116+
builtin_macros_format_string_invalid = invalid format string: {$desc}
117+
.label = {$label1} in format string
118+
.note = {$note}
119+
.second_label = {$label}
120+
121+
builtin_macros_sugg = consider using a positional formatting argument instead
122+
123+
builtin_macros_format_no_arg_named = there is no argument named `{$name}`
124+
.note = did you intend to capture a variable `{$name}` from the surrounding scope?
125+
.note2 = to avoid ambiguity, `format_args!` cannot capture variables when the format string is expanded from a macro
126+
127+
builtin_macros_format_unknown_trait = unknown format trait `{$ty}`
128+
.note = the only appropriate formatting traits are:
129+
- ``, which uses the `Display` trait
130+
- `?`, which uses the `Debug` trait
131+
- `e`, which uses the `LowerExp` trait
132+
- `E`, which uses the `UpperExp` trait
133+
- `o`, which uses the `Octal` trait
134+
- `p`, which uses the `Pointer` trait
135+
- `b`, which uses the `Binary` trait
136+
- `x`, which uses the `LowerHex` trait
137+
- `X`, which uses the `UpperHex` trait
138+
.suggestion = use the `{$trait_name}` trait
139+
140+
builtin_macros_format_unused_arg = {$named ->
141+
[true] named argument
142+
*[false] argument
143+
} never used
144+
145+
builtin_macros_format_unused_args = multiple unused formatting arguments
146+
.label = multiple missing formatting specifiers
147+
148+
builtin_macros_format_pos_mismatch = {$n} positional {$n ->
149+
[one] argument
150+
*[more] arguments
151+
} in format string, but {$desc}

compiler/rustc_builtin_macros/src/alloc_error_handler.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::errors;
12
use crate::util::check_builtin_macro_attribute;
23

34
use rustc_ast::ptr::P;
@@ -31,7 +32,7 @@ pub fn expand(
3132
{
3233
(item, true, ecx.with_def_site_ctxt(fn_kind.sig.span))
3334
} else {
34-
ecx.sess.parse_sess.span_diagnostic.span_err(item.span(), "alloc_error_handler must be a function");
35+
ecx.sess.parse_sess.span_diagnostic.emit_err(errors::AllocErrorMustBeFn {span: item.span() });
3536
return vec![orig_item];
3637
};
3738

compiler/rustc_builtin_macros/src/assert.rs

+6-22
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
mod context;
22

33
use crate::edition_panic::use_panic_2021;
4+
use crate::errors;
45
use rustc_ast::ptr::P;
56
use rustc_ast::token;
67
use rustc_ast::tokenstream::{DelimSpan, TokenStream};
78
use rustc_ast::{DelimArgs, Expr, ExprKind, MacCall, MacDelimiter, Path, PathSegment, UnOp};
89
use rustc_ast_pretty::pprust;
9-
use rustc_errors::{Applicability, PResult};
10+
use rustc_errors::PResult;
1011
use rustc_expand::base::{DummyResult, ExtCtxt, MacEager, MacResult};
1112
use rustc_parse::parser::Parser;
1213
use rustc_span::symbol::{sym, Ident, Symbol};
@@ -114,9 +115,7 @@ fn parse_assert<'a>(cx: &mut ExtCtxt<'a>, sp: Span, stream: TokenStream) -> PRes
114115
let mut parser = cx.new_parser_from_tts(stream);
115116

116117
if parser.token == token::Eof {
117-
let mut err = cx.struct_span_err(sp, "macro requires a boolean expression as an argument");
118-
err.span_label(sp, "boolean expression required");
119-
return Err(err);
118+
return Err(cx.create_err(errors::AssertRequiresBoolean { span: sp }));
120119
}
121120

122121
let cond_expr = parser.parse_expr()?;
@@ -129,15 +128,7 @@ fn parse_assert<'a>(cx: &mut ExtCtxt<'a>, sp: Span, stream: TokenStream) -> PRes
129128
//
130129
// Emit an error about semicolon and suggest removing it.
131130
if parser.token == token::Semi {
132-
let mut err = cx.struct_span_err(sp, "macro requires an expression as an argument");
133-
err.span_suggestion(
134-
parser.token.span,
135-
"try removing semicolon",
136-
"",
137-
Applicability::MaybeIncorrect,
138-
);
139-
err.emit();
140-
131+
cx.emit_err(errors::AssertRequiresExpression { span: sp, token: parser.token.span });
141132
parser.bump();
142133
}
143134

@@ -149,15 +140,8 @@ fn parse_assert<'a>(cx: &mut ExtCtxt<'a>, sp: Span, stream: TokenStream) -> PRes
149140
// Emit an error and suggest inserting a comma.
150141
let custom_message =
151142
if let token::Literal(token::Lit { kind: token::Str, .. }) = parser.token.kind {
152-
let mut err = cx.struct_span_err(parser.token.span, "unexpected string literal");
153-
let comma_span = parser.prev_token.span.shrink_to_hi();
154-
err.span_suggestion_short(
155-
comma_span,
156-
"try adding a comma",
157-
", ",
158-
Applicability::MaybeIncorrect,
159-
);
160-
err.emit();
143+
let comma = parser.prev_token.span.shrink_to_hi();
144+
cx.emit_err(errors::AssertMissingComma { span: parser.token.span, comma });
161145

162146
parse_custom_message(&mut parser)
163147
} else if parser.eat(&token::Comma) {

compiler/rustc_builtin_macros/src/cfg.rs

+3-18
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22
//! a literal `true` or `false` based on whether the given cfg matches the
33
//! current compilation environment.
44
5+
use crate::errors;
56
use rustc_ast as ast;
67
use rustc_ast::token;
78
use rustc_ast::tokenstream::TokenStream;
89
use rustc_attr as attr;
910
use rustc_errors::PResult;
1011
use rustc_expand::base::{self, *};
11-
use rustc_macros::Diagnostic;
1212
use rustc_span::Span;
1313

1414
pub fn expand_cfg(
@@ -35,34 +35,19 @@ pub fn expand_cfg(
3535
}
3636
}
3737

38-
#[derive(Diagnostic)]
39-
#[diag(builtin_macros_requires_cfg_pattern)]
40-
struct RequiresCfgPattern {
41-
#[primary_span]
42-
#[label]
43-
span: Span,
44-
}
45-
46-
#[derive(Diagnostic)]
47-
#[diag(builtin_macros_expected_one_cfg_pattern)]
48-
struct OneCfgPattern {
49-
#[primary_span]
50-
span: Span,
51-
}
52-
5338
fn parse_cfg<'a>(cx: &mut ExtCtxt<'a>, span: Span, tts: TokenStream) -> PResult<'a, ast::MetaItem> {
5439
let mut p = cx.new_parser_from_tts(tts);
5540

5641
if p.token == token::Eof {
57-
return Err(cx.create_err(RequiresCfgPattern { span }));
42+
return Err(cx.create_err(errors::RequiresCfgPattern { span }));
5843
}
5944

6045
let cfg = p.parse_meta_item()?;
6146

6247
let _ = p.eat(&token::Comma);
6348

6449
if !p.eat(&token::Eof) {
65-
return Err(cx.create_err(OneCfgPattern { span }));
50+
return Err(cx.create_err(errors::OneCfgPattern { span }));
6651
}
6752

6853
Ok(cfg)

compiler/rustc_builtin_macros/src/cfg_accessible.rs

+13-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! Implementation of the `#[cfg_accessible(path)]` attribute macro.
22
3+
use crate::errors;
34
use rustc_ast as ast;
45
use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, Indeterminate, MultiItemModifier};
56
use rustc_feature::AttributeTemplate;
@@ -10,15 +11,22 @@ use rustc_span::Span;
1011
pub(crate) struct Expander;
1112

1213
fn validate_input<'a>(ecx: &mut ExtCtxt<'_>, mi: &'a ast::MetaItem) -> Option<&'a ast::Path> {
14+
use errors::CfgAccessibleInvalid::*;
1315
match mi.meta_item_list() {
1416
None => {}
15-
Some([]) => ecx.span_err(mi.span, "`cfg_accessible` path is not specified"),
16-
Some([_, .., l]) => ecx.span_err(l.span(), "multiple `cfg_accessible` paths are specified"),
17+
Some([]) => {
18+
ecx.emit_err(UnspecifiedPath(mi.span));
19+
}
20+
Some([_, .., l]) => {
21+
ecx.emit_err(MultiplePaths(l.span()));
22+
}
1723
Some([nmi]) => match nmi.meta_item() {
18-
None => ecx.span_err(nmi.span(), "`cfg_accessible` path cannot be a literal"),
24+
None => {
25+
ecx.emit_err(LiteralPath(nmi.span()));
26+
}
1927
Some(mi) => {
2028
if !mi.is_word() {
21-
ecx.span_err(mi.span, "`cfg_accessible` path cannot accept arguments");
29+
ecx.emit_err(HasArguments(mi.span));
2230
}
2331
return Some(&mi.path);
2432
}
@@ -53,7 +61,7 @@ impl MultiItemModifier for Expander {
5361
Ok(true) => ExpandResult::Ready(vec![item]),
5462
Ok(false) => ExpandResult::Ready(Vec::new()),
5563
Err(Indeterminate) if ecx.force_mode => {
56-
ecx.span_err(span, "cannot determine whether the path is accessible or not");
64+
ecx.emit_err(errors::CfgAccessibleIndeterminate { span });
5765
ExpandResult::Ready(vec![item])
5866
}
5967
Err(Indeterminate) => ExpandResult::Retry(item),

compiler/rustc_builtin_macros/src/compile_error.rs

+5
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ pub fn expand_compile_error<'cx>(
1313
return DummyResult::any(sp);
1414
};
1515

16+
#[expect(
17+
rustc::diagnostic_outside_of_impl,
18+
reason = "diagnostic message is specified by user"
19+
)]
20+
#[expect(rustc::untranslatable_diagnostic, reason = "diagnostic message is specified by user")]
1621
cx.span_err(sp, var.as_str());
1722

1823
DummyResult::any(sp)

compiler/rustc_builtin_macros/src/concat.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ use rustc_expand::base::{self, DummyResult};
44
use rustc_session::errors::report_lit_error;
55
use rustc_span::symbol::Symbol;
66

7+
use crate::errors;
8+
79
pub fn expand_concat(
810
cx: &mut base::ExtCtxt<'_>,
911
sp: rustc_span::Span,
@@ -31,7 +33,7 @@ pub fn expand_concat(
3133
accumulator.push_str(&b.to_string());
3234
}
3335
Ok(ast::LitKind::Byte(..) | ast::LitKind::ByteStr(..)) => {
34-
cx.span_err(e.span, "cannot concatenate a byte string literal");
36+
cx.emit_err(errors::ConcatBytestr { span: e.span });
3537
has_errors = true;
3638
}
3739
Ok(ast::LitKind::Err) => {
@@ -55,7 +57,7 @@ pub fn expand_concat(
5557
}
5658
}
5759
ast::ExprKind::IncludedBytes(..) => {
58-
cx.span_err(e.span, "cannot concatenate a byte string literal")
60+
cx.emit_err(errors::ConcatBytestr { span: e.span });
5961
}
6062
ast::ExprKind::Err => {
6163
has_errors = true;
@@ -67,9 +69,7 @@ pub fn expand_concat(
6769
}
6870

6971
if !missing_literal.is_empty() {
70-
let mut err = cx.struct_span_err(missing_literal, "expected a literal");
71-
err.note("only literals (like `\"foo\"`, `-42` and `3.14`) can be passed to `concat!()`");
72-
err.emit();
72+
cx.emit_err(errors::ConcatMissingLiteral { spans: missing_literal });
7373
return DummyResult::any(sp);
7474
} else if has_errors {
7575
return DummyResult::any(sp);

0 commit comments

Comments
 (0)