diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs
index a1051d990b14b..d6e344c311bd8 100644
--- a/compiler/rustc_builtin_macros/src/asm.rs
+++ b/compiler/rustc_builtin_macros/src/asm.rs
@@ -3,7 +3,7 @@ use rustc_ast::ptr::P;
use rustc_ast::token::{self, Delimiter};
use rustc_ast::tokenstream::TokenStream;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_errors::{Applicability, PResult};
+use rustc_errors::PResult;
use rustc_expand::base::{self, *};
use rustc_parse::parser::Parser;
use rustc_parse_format as parse;
@@ -15,6 +15,8 @@ use rustc_span::{InnerSpan, Span};
use rustc_target::asm::InlineAsmArch;
use smallvec::smallvec;
+use crate::errors::*;
+
pub struct AsmArgs {
pub templates: Vec
>,
pub operands: Vec<(ast::InlineAsmOperand, Span)>,
@@ -41,13 +43,11 @@ fn parse_args<'a>(
pub fn parse_asm_args<'a>(
p: &mut Parser<'a>,
sess: &'a ParseSess,
- sp: Span,
+ span: Span,
is_global_asm: bool,
) -> PResult<'a, AsmArgs> {
- let diag = &sess.span_diagnostic;
-
if p.token == token::Eof {
- return Err(diag.struct_span_err(sp, "requires at least a template string argument"));
+ return Err(sess.create_err(AsmRequiresTemplateStringArg { span }));
}
let first_template = p.parse_expr()?;
@@ -66,8 +66,7 @@ pub fn parse_asm_args<'a>(
if !p.eat(&token::Comma) {
if allow_templates {
// After a template string, we always expect *only* a comma...
- let mut err = diag.struct_span_err(p.token.span, "expected token: `,`");
- err.span_label(p.token.span, "expected `,`");
+ let mut err = sess.create_err(AsmExpectedTokenComma { span: p.token.span });
p.maybe_annotate_with_ascription(&mut err, false);
return Err(err);
} else {
@@ -110,8 +109,7 @@ pub fn parse_asm_args<'a>(
let op = if !is_global_asm && p.eat_keyword(kw::In) {
let reg = parse_reg(p, &mut explicit_reg)?;
if p.eat_keyword(kw::Underscore) {
- let err = diag.struct_span_err(p.token.span, "_ cannot be used for input operands");
- return Err(err);
+ return Err(sess.create_err(AsmUnderscoreForInputOperands { span: p.token.span }));
}
let expr = p.parse_expr()?;
ast::InlineAsmOperand::In { reg, expr }
@@ -126,8 +124,7 @@ pub fn parse_asm_args<'a>(
} else if !is_global_asm && p.eat_keyword(sym::inout) {
let reg = parse_reg(p, &mut explicit_reg)?;
if p.eat_keyword(kw::Underscore) {
- let err = diag.struct_span_err(p.token.span, "_ cannot be used for input operands");
- return Err(err);
+ return Err(sess.create_err(AsmUnderscoreForInputOperands { span: p.token.span }));
}
let expr = p.parse_expr()?;
if p.eat(&token::FatArrow) {
@@ -140,8 +137,7 @@ pub fn parse_asm_args<'a>(
} else if !is_global_asm && p.eat_keyword(sym::inlateout) {
let reg = parse_reg(p, &mut explicit_reg)?;
if p.eat_keyword(kw::Underscore) {
- let err = diag.struct_span_err(p.token.span, "_ cannot be used for input operands");
- return Err(err);
+ return Err(sess.create_err(AsmUnderscoreForInputOperands { span: p.token.span }));
}
let expr = p.parse_expr()?;
if p.eat(&token::FatArrow) {
@@ -157,9 +153,7 @@ pub fn parse_asm_args<'a>(
} else if p.eat_keyword(sym::sym) {
let expr = p.parse_expr()?;
let ast::ExprKind::Path(qself, path) = &expr.kind else {
- let err = diag
- .struct_span_err(expr.span, "expected a path for argument to `sym`");
- return Err(err);
+ return Err(sess.create_err(AsmExpectedPathArgToSym{span: expr.span}));
};
let sym = ast::InlineAsmSym {
id: ast::DUMMY_NODE_ID,
@@ -175,13 +169,15 @@ pub fn parse_asm_args<'a>(
ast::ExprKind::Lit(ast::Lit { kind: ast::LitKind::Str(..), .. }) => {}
ast::ExprKind::MacCall(..) => {}
_ => {
- let errstr = if is_global_asm {
- "expected operand, options, or additional template string"
+ let err = if is_global_asm {
+ sess.create_err(AsmExpectedOperandOptionsOrTemplateString {
+ span: template.span,
+ })
} else {
- "expected operand, clobber_abi, options, or additional template string"
+ sess.create_err(AsmExpectedOperandClobberAbiOptionsOrTemplateString {
+ span: template.span,
+ })
};
- let mut err = diag.struct_span_err(template.span, errstr);
- err.span_label(template.span, errstr);
return Err(err);
}
}
@@ -200,56 +196,49 @@ pub fn parse_asm_args<'a>(
// clobber_abi/options. We do this at the end once we have the full span
// of the argument available.
if !args.options_spans.is_empty() {
- diag.struct_span_err(span, "arguments are not allowed after options")
- .span_labels(args.options_spans.clone(), "previous options")
- .span_label(span, "argument")
- .emit();
+ sess.create_err(AsmArgsAfterOptions {
+ span,
+ options_spans: args.options_spans.clone(),
+ })
+ .emit();
} else if let Some((_, abi_span)) = args.clobber_abis.last() {
- diag.struct_span_err(span, "arguments are not allowed after clobber_abi")
- .span_label(*abi_span, "clobber_abi")
- .span_label(span, "argument")
- .emit();
+ sess.create_err(AsmArgsAfterClobberAbi { span, abi_span: *abi_span }).emit();
}
if explicit_reg {
if name.is_some() {
- diag.struct_span_err(span, "explicit register arguments cannot have names").emit();
+ sess.create_err(AsmExplicitRegisterArgWithName { span }).emit();
}
args.reg_args.insert(slot);
} else if let Some(name) = name {
if let Some(&prev) = args.named_args.get(&name) {
- diag.struct_span_err(span, &format!("duplicate argument named `{}`", name))
- .span_label(args.operands[prev].1, "previously here")
- .span_label(span, "duplicate argument")
- .emit();
+ sess.create_err(AsmDuplicateArgument {
+ name,
+ span,
+ prev_span: args.operands[prev].1,
+ })
+ .emit();
continue;
}
if !args.reg_args.is_empty() {
- let mut err = diag.struct_span_err(
+ sess.create_err(AsmArgsNamedAfterExplicitRegister {
span,
- "named arguments cannot follow explicit register arguments",
- );
- err.span_label(span, "named argument");
- for pos in &args.reg_args {
- err.span_label(args.operands[*pos].1, "explicit register argument");
- }
- err.emit();
+ register_spans: args.reg_args.iter().map(|pos| args.operands[*pos].1).collect(),
+ })
+ .emit();
}
args.named_args.insert(name, slot);
} else {
if !args.named_args.is_empty() || !args.reg_args.is_empty() {
- let mut err = diag.struct_span_err(
+ sess.create_err(AsmArgsPositionalAfterNamedOrExplicitRegister {
span,
- "positional arguments cannot follow named arguments \
- or explicit register arguments",
- );
- err.span_label(span, "positional argument");
- for pos in args.named_args.values() {
- err.span_label(args.operands[*pos].1, "named argument");
- }
- for pos in &args.reg_args {
- err.span_label(args.operands[*pos].1, "explicit register argument");
- }
- err.emit();
+ named_spans: args
+ .named_args
+ .values()
+ .map(|pos| args.operands[*pos].1)
+ .collect(),
+ register_spans: args.reg_args.iter().map(|pos| args.operands[*pos].1).collect(),
+ })
+ .emit();
}
}
}
@@ -258,24 +247,26 @@ pub fn parse_asm_args<'a>(
&& args.options.contains(ast::InlineAsmOptions::READONLY)
{
let spans = args.options_spans.clone();
- diag.struct_span_err(spans, "the `nomem` and `readonly` options are mutually exclusive")
+ sess.create_err(AsmOptionsMutuallyExclusive { left: "nomem", right: "readonly", spans })
.emit();
}
if args.options.contains(ast::InlineAsmOptions::PURE)
&& args.options.contains(ast::InlineAsmOptions::NORETURN)
{
let spans = args.options_spans.clone();
- diag.struct_span_err(spans, "the `pure` and `noreturn` options are mutually exclusive")
+ sess.create_err(AsmOptionsMutuallyExclusive { left: "pure", right: "noreturn", spans })
.emit();
}
if args.options.contains(ast::InlineAsmOptions::PURE)
&& !args.options.intersects(ast::InlineAsmOptions::NOMEM | ast::InlineAsmOptions::READONLY)
{
let spans = args.options_spans.clone();
- diag.struct_span_err(
+ sess.create_err(AsmOptionMustBeCombinedWithEither {
+ option: "pure",
+ left: "nomem",
+ right: "readonly",
spans,
- "the `pure` option must be combined with either `nomem` or `readonly`",
- )
+ })
.emit();
}
@@ -303,15 +294,10 @@ pub fn parse_asm_args<'a>(
}
}
if args.options.contains(ast::InlineAsmOptions::PURE) && !have_real_output {
- diag.struct_span_err(
- args.options_spans.clone(),
- "asm with the `pure` option must have at least one output",
- )
- .emit();
+ sess.create_err(AsmOptionPureNeedsOneOutput { spans: args.options_spans.clone() }).emit();
}
if args.options.contains(ast::InlineAsmOptions::NORETURN) && !outputs_sp.is_empty() {
- let err = diag
- .struct_span_err(outputs_sp, "asm outputs are not allowed with the `noreturn` option");
+ let err = sess.create_err(AsmOptionNoreturnWithOutputs { spans: outputs_sp });
// Bail out now since this is likely to confuse MIR
return Err(err);
@@ -319,24 +305,20 @@ pub fn parse_asm_args<'a>(
if args.clobber_abis.len() > 0 {
if is_global_asm {
- let err = diag.struct_span_err(
- args.clobber_abis.iter().map(|(_, span)| *span).collect::>(),
- "`clobber_abi` cannot be used with `global_asm!`",
- );
+ let err = sess.create_err(AsmCannotBeUsedWith {
+ left: "clobber_abi",
+ right: "global_asm!",
+ spans: args.clobber_abis.iter().map(|(_, span)| *span).collect(),
+ });
// Bail out now since this is likely to confuse later stages
return Err(err);
}
if !regclass_outputs.is_empty() {
- diag.struct_span_err(
- regclass_outputs.clone(),
- "asm with `clobber_abi` must specify explicit registers for outputs",
- )
- .span_labels(
- args.clobber_abis.iter().map(|(_, span)| *span).collect::>(),
- "clobber_abi",
- )
- .span_labels(regclass_outputs, "generic outputs")
+ sess.create_err(AsmClobberAbiNeedsExplicitRegisters {
+ spans: regclass_outputs,
+ abi_spans: args.clobber_abis.iter().map(|(_, span)| *span).collect(),
+ })
.emit();
}
}
@@ -349,25 +331,13 @@ pub fn parse_asm_args<'a>(
/// This function must be called immediately after the option token is parsed.
/// Otherwise, the suggestion will be incorrect.
fn err_duplicate_option<'a>(p: &mut Parser<'a>, symbol: Symbol, span: Span) {
- let mut err = p
- .sess
- .span_diagnostic
- .struct_span_err(span, &format!("the `{}` option was already provided", symbol));
- err.span_label(span, "this option was already provided");
-
// Tool-only output
let mut full_span = span;
if p.token.kind == token::Comma {
full_span = full_span.to(p.token.span);
}
- err.tool_only_span_suggestion(
- full_span,
- "remove this option",
- "",
- Applicability::MachineApplicable,
- );
-
- err.emit();
+
+ p.sess.create_err(AsmDuplicateOption { symbol, span, full_span }).emit();
}
/// Try to set the provided option in the provided `AsmArgs`.
@@ -439,11 +409,7 @@ fn parse_clobber_abi<'a>(p: &mut Parser<'a>, args: &mut AsmArgs) -> PResult<'a,
p.expect(&token::OpenDelim(Delimiter::Parenthesis))?;
if p.eat(&token::CloseDelim(Delimiter::Parenthesis)) {
- let err = p.sess.span_diagnostic.struct_span_err(
- p.token.span,
- "at least one abi must be provided as an argument to `clobber_abi`",
- );
- return Err(err);
+ return Err(p.sess.create_err(AsmClobberAbiNeedsAnAbi { span: p.token.span }));
}
let mut new_abis = Vec::new();
@@ -458,10 +424,7 @@ fn parse_clobber_abi<'a>(p: &mut Parser<'a>, args: &mut AsmArgs) -> PResult<'a,
break;
}
let span = opt_lit.map_or(p.token.span, |lit| lit.span);
- let mut err =
- p.sess.span_diagnostic.struct_span_err(span, "expected string literal");
- err.span_label(span, "not a string literal");
- return Err(err);
+ return Err(p.sess.create_err(AsmExpectedStringLiteral { span }));
}
};
@@ -475,12 +438,10 @@ fn parse_clobber_abi<'a>(p: &mut Parser<'a>, args: &mut AsmArgs) -> PResult<'a,
let full_span = span_start.to(p.prev_token.span);
if !args.options_spans.is_empty() {
- let mut err = p
- .sess
- .span_diagnostic
- .struct_span_err(full_span, "clobber_abi is not allowed after options");
- err.span_labels(args.options_spans.clone(), "options");
- return Err(err);
+ return Err(p.sess.create_err(AsmClobberAbiAfterOptions {
+ span: full_span,
+ options_spans: args.options_spans.clone(),
+ }));
}
match &new_abis[..] {
@@ -509,9 +470,9 @@ fn parse_reg<'a>(
ast::InlineAsmRegOrRegClass::Reg(symbol)
}
_ => {
- return Err(
- p.struct_span_err(p.token.span, "expected register class or explicit register")
- );
+ return Err(p
+ .sess
+ .create_err(AsmExpectedRegisterClassOrExplicitRegister { span: p.token.span }));
}
};
p.bump();
@@ -706,13 +667,12 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option Some(idx),
None => {
- let msg = format!("there is no argument named `{}`", name);
let span = arg.position_span;
- ecx.struct_span_err(
- template_span
+ ecx.create_err(AsmNoArgumentNamed {
+ name: name.to_owned(),
+ span: template_span
.from_inner(InnerSpan::new(span.start, span.end)),
- &msg,
- )
+ })
.emit();
None
}
@@ -728,11 +688,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option(cx: &mut ExtCtxt<'a>, sp: Span, stream: TokenStream) -> PRes
let mut parser = cx.new_parser_from_tts(stream);
if parser.token == token::Eof {
- let mut err = cx.struct_span_err(sp, "macro requires a boolean expression as an argument");
- err.span_label(sp, "boolean expression required");
- return Err(err);
+ return Err(cx.create_err(errors::BooleanExpressionRequired { span: sp }));
}
let cond_expr = parser.parse_expr()?;
@@ -128,14 +127,7 @@ fn parse_assert<'a>(cx: &mut ExtCtxt<'a>, sp: Span, stream: TokenStream) -> PRes
//
// Emit an error about semicolon and suggest removing it.
if parser.token == token::Semi {
- let mut err = cx.struct_span_err(sp, "macro requires an expression as an argument");
- err.span_suggestion(
- parser.token.span,
- "try removing semicolon",
- "",
- Applicability::MaybeIncorrect,
- );
- err.emit();
+ cx.emit_err(ArgumentExpressionRequired { span: sp });
parser.bump();
}
@@ -148,16 +140,7 @@ fn parse_assert<'a>(cx: &mut ExtCtxt<'a>, sp: Span, stream: TokenStream) -> PRes
// Emit an error and suggest inserting a comma.
let custom_message =
if let token::Literal(token::Lit { kind: token::Str, .. }) = parser.token.kind {
- let mut err = cx.struct_span_err(parser.token.span, "unexpected string literal");
- let comma_span = parser.prev_token.span.shrink_to_hi();
- err.span_suggestion_short(
- comma_span,
- "try adding a comma",
- ", ",
- Applicability::MaybeIncorrect,
- );
- err.emit();
-
+ cx.sess.emit_err(errors::UnexpectedStringLiteral { span: parser.token.span });
parse_custom_message(&mut parser)
} else if parser.eat(&token::Comma) {
parse_custom_message(&mut parser)
@@ -174,5 +157,9 @@ fn parse_assert<'a>(cx: &mut ExtCtxt<'a>, sp: Span, stream: TokenStream) -> PRes
fn parse_custom_message(parser: &mut Parser<'_>) -> Option {
let ts = parser.parse_tokens();
- if !ts.is_empty() { Some(ts) } else { None }
+ if !ts.is_empty() {
+ Some(ts)
+ } else {
+ None
+ }
}
diff --git a/compiler/rustc_builtin_macros/src/cfg_accessible.rs b/compiler/rustc_builtin_macros/src/cfg_accessible.rs
index cb5359dd1e27e..84484b13ec3c5 100644
--- a/compiler/rustc_builtin_macros/src/cfg_accessible.rs
+++ b/compiler/rustc_builtin_macros/src/cfg_accessible.rs
@@ -7,18 +7,29 @@ use rustc_parse::validate_attr;
use rustc_span::symbol::sym;
use rustc_span::Span;
+use crate::errors::{
+ MultiplePathsSpecified, NondeterministicAccess, NotSpecified, UnacceptedArguments,
+ UnallowedLiteralPath,
+};
+
pub(crate) struct Expander;
fn validate_input<'a>(ecx: &mut ExtCtxt<'_>, mi: &'a ast::MetaItem) -> Option<&'a ast::Path> {
match mi.meta_item_list() {
None => {}
- Some([]) => ecx.span_err(mi.span, "`cfg_accessible` path is not specified"),
- Some([_, .., l]) => ecx.span_err(l.span(), "multiple `cfg_accessible` paths are specified"),
+ Some([]) => {
+ ecx.emit_err(NotSpecified { span: mi.span });
+ }
+ Some([_, .., l]) => {
+ ecx.emit_err(MultiplePathsSpecified { span: l.span() });
+ }
Some([nmi]) => match nmi.meta_item() {
- None => ecx.span_err(nmi.span(), "`cfg_accessible` path cannot be a literal"),
+ None => {
+ ecx.emit_err(UnallowedLiteralPath { span: nmi.span() });
+ }
Some(mi) => {
if !mi.is_word() {
- ecx.span_err(mi.span, "`cfg_accessible` path cannot accept arguments");
+ ecx.emit_err(UnacceptedArguments { span: mi.span });
}
return Some(&mi.path);
}
@@ -52,7 +63,7 @@ impl MultiItemModifier for Expander {
Ok(true) => ExpandResult::Ready(vec![item]),
Ok(false) => ExpandResult::Ready(Vec::new()),
Err(Indeterminate) if ecx.force_mode => {
- ecx.span_err(span, "cannot determine whether the path is accessible or not");
+ ecx.emit_err(NondeterministicAccess { span });
ExpandResult::Ready(vec![item])
}
Err(Indeterminate) => ExpandResult::Retry(item),
diff --git a/compiler/rustc_builtin_macros/src/compile_error.rs b/compiler/rustc_builtin_macros/src/compile_error.rs
index 72397aa2500f9..20ef85e81c677 100644
--- a/compiler/rustc_builtin_macros/src/compile_error.rs
+++ b/compiler/rustc_builtin_macros/src/compile_error.rs
@@ -4,6 +4,8 @@ use rustc_ast::tokenstream::TokenStream;
use rustc_expand::base::{self, *};
use rustc_span::Span;
+use crate::errors::CompileError;
+
pub fn expand_compile_error<'cx>(
cx: &'cx mut ExtCtxt<'_>,
sp: Span,
@@ -13,7 +15,7 @@ pub fn expand_compile_error<'cx>(
return DummyResult::any(sp);
};
- cx.span_err(sp, var.as_str());
+ cx.emit_err(CompileError { span: sp, msg: var.as_str().to_owned() });
DummyResult::any(sp)
}
diff --git a/compiler/rustc_builtin_macros/src/concat.rs b/compiler/rustc_builtin_macros/src/concat.rs
index 41f4e8c234d5a..00a81622e557b 100644
--- a/compiler/rustc_builtin_macros/src/concat.rs
+++ b/compiler/rustc_builtin_macros/src/concat.rs
@@ -5,6 +5,8 @@ use rustc_span::symbol::Symbol;
use std::string::String;
+use crate::errors::{ByteStringLiteralConcatenate, MissingLiteral};
+
pub fn expand_concat(
cx: &mut base::ExtCtxt<'_>,
sp: rustc_span::Span,
@@ -37,7 +39,7 @@ pub fn expand_concat(
accumulator.push_str(&b.to_string());
}
ast::LitKind::Byte(..) | ast::LitKind::ByteStr(..) => {
- cx.span_err(e.span, "cannot concatenate a byte string literal");
+ cx.emit_err(ByteStringLiteralConcatenate { span: e.span });
}
ast::LitKind::Err => {
has_errors = true;
@@ -52,9 +54,7 @@ pub fn expand_concat(
}
}
if !missing_literal.is_empty() {
- let mut err = cx.struct_span_err(missing_literal, "expected a literal");
- err.note("only literals (like `\"foo\"`, `42` and `3.14`) can be passed to `concat!()`");
- err.emit();
+ cx.emit_err(MissingLiteral { span: sp });
return DummyResult::any(sp);
} else if has_errors {
return DummyResult::any(sp);
diff --git a/compiler/rustc_builtin_macros/src/concat_bytes.rs b/compiler/rustc_builtin_macros/src/concat_bytes.rs
index 66e86bf218267..f6acf305cd51f 100644
--- a/compiler/rustc_builtin_macros/src/concat_bytes.rs
+++ b/compiler/rustc_builtin_macros/src/concat_bytes.rs
@@ -1,8 +1,14 @@
use rustc_ast as ast;
use rustc_ast::{ptr::P, tokenstream::TokenStream};
-use rustc_errors::Applicability;
use rustc_expand::base::{self, DummyResult};
+use crate::errors::{
+ BooleanLiteralsConcatenate, ByteLiteralExpected, CharacterLiteralsConcatenate,
+ DoublyNestedArrayConcatenate, FloatLiteralsConcatenate, InvalidNumericLiteral,
+ InvalidRepeatCount, NumericLiteralsConcatenate, OutOfBoundNumericLiteral, Snippet,
+ StringLiteralsConcatenate,
+};
+
/// Emits errors for literal expressions that are invalid inside and outside of an array.
fn invalid_type_err(cx: &mut base::ExtCtxt<'_>, expr: &P, is_nested: bool) {
let ast::ExprKind::Lit(lit) = &expr.kind else {
@@ -10,60 +16,49 @@ fn invalid_type_err(cx: &mut base::ExtCtxt<'_>, expr: &P, is_ne
};
match lit.kind {
ast::LitKind::Char(_) => {
- let mut err = cx.struct_span_err(expr.span, "cannot concatenate character literals");
- if let Ok(snippet) = cx.sess.source_map().span_to_snippet(expr.span) {
- err.span_suggestion(
- expr.span,
- "try using a byte character",
- format!("b{}", snippet),
- Applicability::MachineApplicable,
- )
- .emit();
- }
+ let sub = cx
+ .sess
+ .source_map()
+ .span_to_snippet(expr.span)
+ .ok()
+ .map(|s| Snippet::ByteCharacter { span: expr.span, snippet: s });
+ cx.emit_err(CharacterLiteralsConcatenate { span: expr.span, sub });
}
ast::LitKind::Str(_, _) => {
- let mut err = cx.struct_span_err(expr.span, "cannot concatenate string literals");
// suggestion would be invalid if we are nested
- if !is_nested {
- if let Ok(snippet) = cx.sess.source_map().span_to_snippet(expr.span) {
- err.span_suggestion(
- expr.span,
- "try using a byte string",
- format!("b{}", snippet),
- Applicability::MachineApplicable,
- );
- }
- }
- err.emit();
+ let sub = if !is_nested {
+ cx.sess
+ .source_map()
+ .span_to_snippet(expr.span)
+ .ok()
+ .map(|s| Snippet::ByteString { span: expr.span, snippet: s })
+ } else {
+ None
+ };
+ cx.emit_err(StringLiteralsConcatenate { span: expr.span, sub });
}
ast::LitKind::Float(_, _) => {
- cx.span_err(expr.span, "cannot concatenate float literals");
+ cx.emit_err(FloatLiteralsConcatenate { span: expr.span });
}
ast::LitKind::Bool(_) => {
- cx.span_err(expr.span, "cannot concatenate boolean literals");
+ cx.emit_err(BooleanLiteralsConcatenate { span: expr.span });
}
ast::LitKind::Err => {}
ast::LitKind::Int(_, _) if !is_nested => {
- let mut err = cx.struct_span_err(expr.span, "cannot concatenate numeric literals");
- if let Ok(snippet) = cx.sess.source_map().span_to_snippet(expr.span) {
- err.span_suggestion(
- expr.span,
- "try wrapping the number in an array",
- format!("[{}]", snippet),
- Applicability::MachineApplicable,
- );
- }
- err.emit();
+ let sub = cx.sess.source_map().span_to_snippet(expr.span).ok().map(|s| {
+ Snippet::WrappingNumberInArray { span: expr.span, snippet: format!("[{}]", s) }
+ });
+ cx.emit_err(NumericLiteralsConcatenate { span: expr.span, sub });
}
ast::LitKind::Int(
val,
ast::LitIntType::Unsuffixed | ast::LitIntType::Unsigned(ast::UintTy::U8),
) => {
assert!(val > u8::MAX.into()); // must be an error
- cx.span_err(expr.span, "numeric literal is out of bounds");
+ cx.emit_err(OutOfBoundNumericLiteral { span: expr.span });
}
ast::LitKind::Int(_, _) => {
- cx.span_err(expr.span, "numeric literal is not a `u8`");
+ cx.emit_err(InvalidNumericLiteral { span: expr.span });
}
_ => unreachable!(),
}
@@ -78,7 +73,11 @@ fn handle_array_element(
match expr.kind {
ast::ExprKind::Array(_) | ast::ExprKind::Repeat(_, _) => {
if !*has_errors {
- cx.span_err(expr.span, "cannot concatenate doubly nested array");
+ cx.emit_err(DoublyNestedArrayConcatenate {
+ span: expr.span,
+ note: None,
+ help: None,
+ });
}
*has_errors = true;
None
@@ -92,10 +91,11 @@ fn handle_array_element(
ast::LitKind::Byte(val) => Some(val),
ast::LitKind::ByteStr(_) => {
if !*has_errors {
- cx.struct_span_err(expr.span, "cannot concatenate doubly nested array")
- .note("byte strings are treated as arrays of bytes")
- .help("try flattening the array")
- .emit();
+ cx.emit_err(DoublyNestedArrayConcatenate {
+ span: expr.span,
+ note: Some(()),
+ help: Some(()),
+ });
}
*has_errors = true;
None
@@ -150,7 +150,7 @@ pub fn expand_concat_bytes(
}
}
} else {
- cx.span_err(count.value.span, "repeat count is not a positive number");
+ cx.emit_err(InvalidRepeatCount { span: count.value.span });
}
}
ast::ExprKind::Lit(ref lit) => match lit.kind {
@@ -176,9 +176,7 @@ pub fn expand_concat_bytes(
}
}
if !missing_literals.is_empty() {
- let mut err = cx.struct_span_err(missing_literals.clone(), "expected a byte literal");
- err.note("only byte literals (like `b\"foo\"`, `b's'`, and `[3, 4, 5]`) can be passed to `concat_bytes!()`");
- err.emit();
+ cx.emit_err(ByteLiteralExpected { spans: missing_literals.clone() });
return base::MacEager::expr(DummyResult::raw_expr(sp, true));
} else if has_errors {
return base::MacEager::expr(DummyResult::raw_expr(sp, true));
diff --git a/compiler/rustc_builtin_macros/src/concat_idents.rs b/compiler/rustc_builtin_macros/src/concat_idents.rs
index 297c604e02043..86a37c9a4c0a8 100644
--- a/compiler/rustc_builtin_macros/src/concat_idents.rs
+++ b/compiler/rustc_builtin_macros/src/concat_idents.rs
@@ -6,13 +6,15 @@ use rustc_expand::base::{self, *};
use rustc_span::symbol::{Ident, Symbol};
use rustc_span::Span;
+use crate::errors::{CommaExpected, IdentArgsRequired, MissingArguments};
+
pub fn expand_concat_idents<'cx>(
cx: &'cx mut ExtCtxt<'_>,
sp: Span,
tts: TokenStream,
) -> Box {
if tts.is_empty() {
- cx.span_err(sp, "concat_idents! takes 1 or more arguments");
+ cx.emit_err(MissingArguments { span: sp });
return DummyResult::any(sp);
}
@@ -22,7 +24,7 @@ pub fn expand_concat_idents<'cx>(
match e {
TokenTree::Token(Token { kind: token::Comma, .. }, _) => {}
_ => {
- cx.span_err(sp, "concat_idents! expecting comma");
+ cx.emit_err(CommaExpected { span: sp });
return DummyResult::any(sp);
}
}
@@ -34,7 +36,7 @@ pub fn expand_concat_idents<'cx>(
}
}
- cx.span_err(sp, "concat_idents! requires ident args");
+ cx.emit_err(IdentArgsRequired { span: sp });
return DummyResult::any(sp);
}
}
diff --git a/compiler/rustc_builtin_macros/src/derive.rs b/compiler/rustc_builtin_macros/src/derive.rs
index 467ac34ded942..e583c91e8f008 100644
--- a/compiler/rustc_builtin_macros/src/derive.rs
+++ b/compiler/rustc_builtin_macros/src/derive.rs
@@ -1,8 +1,8 @@
use crate::cfg_eval::cfg_eval;
+use crate::errors::{NotApplicableDerive, PathRejected, TraitPathExpected};
use rustc_ast as ast;
use rustc_ast::{attr, token, GenericParamKind, ItemKind, MetaItemKind, NestedMetaItem, StmtKind};
-use rustc_errors::{struct_span_err, Applicability};
use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, Indeterminate, MultiItemModifier};
use rustc_feature::AttributeTemplate;
use rustc_parse::validate_attr;
@@ -112,15 +112,7 @@ fn report_bad_target(sess: &Session, item: &Annotatable, span: Span) -> bool {
let bad_target =
!matches!(item_kind, Some(ItemKind::Struct(..) | ItemKind::Enum(..) | ItemKind::Union(..)));
if bad_target {
- struct_span_err!(
- sess,
- span,
- E0774,
- "`derive` may only be applied to `struct`s, `enum`s and `union`s",
- )
- .span_label(span, "not applicable here")
- .span_label(item.span(), "not a `struct`, `enum` or `union`")
- .emit();
+ sess.emit_err(NotApplicableDerive { span, item_span: item.span() });
}
bad_target
}
@@ -132,18 +124,13 @@ fn report_unexpected_literal(sess: &Session, lit: &ast::Lit) {
}
_ => "for example, write `#[derive(Debug)]` for `Debug`".to_string(),
};
- struct_span_err!(sess, lit.span, E0777, "expected path to a trait, found literal",)
- .span_label(lit.span, "not a trait")
- .help(&help_msg)
- .emit();
+ sess.emit_err(TraitPathExpected { span: lit.span, help_msg: &help_msg });
}
fn report_path_args(sess: &Session, meta: &ast::MetaItem) {
let report_error = |title, action| {
let span = meta.span.with_lo(meta.path.span.hi());
- sess.struct_span_err(span, title)
- .span_suggestion(span, action, "", Applicability::MachineApplicable)
- .emit();
+ sess.emit_err(PathRejected { span, title, action });
};
match meta.kind {
MetaItemKind::Word => {}
diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs
index a94c8a996e642..3c23bae908e7b 100644
--- a/compiler/rustc_builtin_macros/src/deriving/default.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/default.rs
@@ -1,8 +1,12 @@
use crate::deriving::generic::ty::*;
use crate::deriving::generic::*;
+use crate::errors::{
+ DefaultNonExhaustive, DefaultNotAcceptValue, DefaultNotAllowed, MultipleDeclaredDefaults,
+ MultipleDeclaredDefaultsSuggestion, MultipleDefaultAttributes,
+ MultipleDefaultAttributesSuggestions, NoDefault, NoDefaultSuggestion,
+};
use rustc_ast as ast;
use rustc_ast::{walk_list, EnumDef, VariantData};
-use rustc_errors::Applicability;
use rustc_expand::base::{Annotatable, DummyResult, ExtCtxt};
use rustc_span::symbol::Ident;
use rustc_span::symbol::{kw, sym};
@@ -119,68 +123,52 @@ fn extract_default_variant<'a>(
.filter(|variant| matches!(variant.data, VariantData::Unit(..)))
.filter(|variant| !cx.sess.contains_name(&variant.attrs, sym::non_exhaustive));
- let mut diag = cx.struct_span_err(trait_span, "no default declared");
- diag.help("make a unit variant default by placing `#[default]` above it");
- for variant in possible_defaults {
- // Suggest making each unit variant default.
- diag.tool_only_span_suggestion(
- variant.span,
- &format!("make `{}` default", variant.ident),
- format!("#[default] {}", variant.ident),
- Applicability::MaybeIncorrect,
- );
- }
- diag.emit();
-
+ cx.emit_err(NoDefault {
+ span: trait_span,
+ suggestions: possible_defaults
+ .map(|variant| NoDefaultSuggestion { span: variant.span, ident: variant.ident })
+ .collect(),
+ });
return Err(());
}
[first, rest @ ..] => {
- let mut diag = cx.struct_span_err(trait_span, "multiple declared defaults");
- diag.span_label(first.span, "first default");
- diag.span_labels(rest.iter().map(|variant| variant.span), "additional default");
- diag.note("only one variant can be default");
- for variant in &default_variants {
- // Suggest making each variant already tagged default.
- let suggestion = default_variants
- .iter()
- .filter_map(|v| {
- if v.ident == variant.ident {
- None
- } else {
- Some((cx.sess.find_by_name(&v.attrs, kw::Default)?.span, String::new()))
- }
- })
- .collect();
-
- diag.tool_only_multipart_suggestion(
- &format!("make `{}` default", variant.ident),
- suggestion,
- Applicability::MaybeIncorrect,
- );
- }
- diag.emit();
+ let suggestions = default_variants
+ .iter()
+ .map(|variant| {
+ let suggestion = default_variants
+ .iter()
+ .filter_map(|v| {
+ if v.ident == variant.ident {
+ None
+ } else {
+ Some(cx.sess.find_by_name(&v.attrs, kw::Default)?.span)
+ }
+ })
+ .collect::>();
+ MultipleDeclaredDefaultsSuggestion { span: suggestion }
+ })
+ .collect();
+ cx.emit_err(MultipleDeclaredDefaults {
+ span: trait_span,
+ first: first.span,
+ variants: rest.iter().map(|variant| variant.span).collect(),
+ suggestions,
+ });
return Err(());
}
};
if !matches!(variant.data, VariantData::Unit(..)) {
- cx.struct_span_err(
- variant.ident.span,
- "the `#[default]` attribute may only be used on unit enum variants",
- )
- .help("consider a manual implementation of `Default`")
- .emit();
-
+ cx.emit_err(DefaultNotAllowed { span: variant.ident.span, help: None });
return Err(());
}
if let Some(non_exhaustive_attr) = cx.sess.find_by_name(&variant.attrs, sym::non_exhaustive) {
- cx.struct_span_err(variant.ident.span, "default variant must be exhaustive")
- .span_label(non_exhaustive_attr.span, "declared `#[non_exhaustive]` here")
- .help("consider a manual implementation of `Default`")
- .emit();
-
+ cx.emit_err(DefaultNonExhaustive {
+ span: variant.ident.span,
+ non_exhustive_attr: non_exhaustive_attr.span,
+ });
return Err(());
}
@@ -203,33 +191,21 @@ fn validate_default_attribute(
let suggestion_text =
if rest.len() == 1 { "try removing this" } else { "try removing these" };
- cx.struct_span_err(default_variant.ident.span, "multiple `#[default]` attributes")
- .note("only one `#[default]` attribute is needed")
- .span_label(first.span, "`#[default]` used here")
- .span_label(rest[0].span, "`#[default]` used again here")
- .span_help(rest.iter().map(|attr| attr.span).collect::>(), suggestion_text)
- // This would otherwise display the empty replacement, hence the otherwise
- // repetitive `.span_help` call above.
- .tool_only_multipart_suggestion(
- suggestion_text,
- rest.iter().map(|attr| (attr.span, String::new())).collect(),
- Applicability::MachineApplicable,
- )
- .emit();
-
+ cx.emit_err(MultipleDefaultAttributes {
+ span: default_variant.ident.span,
+ first: first.span,
+ rest: rest[0].span,
+ help: rest.iter().map(|attr| attr.span).collect::>(),
+ suggestion_text,
+ suggestions: MultipleDefaultAttributesSuggestions {
+ span: rest.iter().map(|attr| attr.span).collect(),
+ },
+ });
return Err(());
}
};
if !attr.is_word() {
- cx.struct_span_err(attr.span, "`#[default]` attribute does not accept a value")
- .span_suggestion_hidden(
- attr.span,
- "try using `#[default]`",
- "#[default]",
- Applicability::MaybeIncorrect,
- )
- .emit();
-
+ cx.emit_err(DefaultNotAcceptValue { span: attr.span });
return Err(());
}
Ok(())
@@ -242,12 +218,7 @@ struct DetectNonVariantDefaultAttr<'a, 'b> {
impl<'a, 'b> rustc_ast::visit::Visitor<'a> for DetectNonVariantDefaultAttr<'a, 'b> {
fn visit_attribute(&mut self, attr: &'a rustc_ast::Attribute) {
if attr.has_name(kw::Default) {
- self.cx
- .struct_span_err(
- attr.span,
- "the `#[default]` attribute may only be used on unit enum variants",
- )
- .emit();
+ self.cx.emit_err(DefaultNotAllowed { span: attr.span, help: Some(()) });
}
rustc_ast::visit::walk_attribute(self, attr);
diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
index 3cc160adb5397..c73cb266fd075 100644
--- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
@@ -163,6 +163,7 @@ pub use StaticFields::*;
pub use SubstructureFields::*;
use crate::deriving;
+use crate::errors::{CannotBeDerivedUnions, UnallowedDerive};
use rustc_ast::ptr::P;
use rustc_ast::{
self as ast, BindingAnnotation, ByRef, EnumDef, Expr, Generics, Mutability, PatKind,
@@ -391,7 +392,7 @@ fn find_type_parameters(
}
fn visit_mac_call(&mut self, mac: &ast::MacCall) {
- self.cx.span_err(mac.span(), "`derive` cannot be used on items with type macros");
+ self.cx.emit_err(UnallowedDerive { span: mac.span() });
}
}
@@ -478,7 +479,7 @@ impl<'a> TraitDef<'a> {
always_copy,
)
} else {
- cx.span_err(mitem.span, "this trait cannot be derived for unions");
+ cx.emit_err(CannotBeDerivedUnions { span: mitem.span });
return;
}
}
diff --git a/compiler/rustc_builtin_macros/src/env.rs b/compiler/rustc_builtin_macros/src/env.rs
index b8828fa671a5d..64696a56cb489 100644
--- a/compiler/rustc_builtin_macros/src/env.rs
+++ b/compiler/rustc_builtin_macros/src/env.rs
@@ -11,6 +11,8 @@ use rustc_span::Span;
use std::env;
+use crate::errors::{EmptyArgument, EnvExpandError};
+
pub fn expand_option_env<'cx>(
cx: &'cx mut ExtCtxt<'_>,
sp: Span,
@@ -54,7 +56,7 @@ pub fn expand_env<'cx>(
) -> Box {
let mut exprs = match get_exprs_from_tts(cx, sp, tts) {
Some(ref exprs) if exprs.is_empty() => {
- cx.span_err(sp, "env! takes 1 or 2 arguments");
+ cx.emit_err(EmptyArgument { span: sp });
return DummyResult::any(sp);
}
None => return DummyResult::any(sp),
@@ -73,7 +75,7 @@ pub fn expand_env<'cx>(
};
if exprs.next().is_some() {
- cx.span_err(sp, "env! takes 1 or 2 arguments");
+ cx.emit_err(EmptyArgument { span: sp });
return DummyResult::any(sp);
}
@@ -82,7 +84,7 @@ pub fn expand_env<'cx>(
cx.sess.parse_sess.env_depinfo.borrow_mut().insert((var, value));
let e = match value {
None => {
- cx.span_err(sp, msg.as_str());
+ cx.emit_err(EnvExpandError { span: sp, msg: msg.as_str() });
return DummyResult::any(sp);
}
Some(value) => cx.expr_str(sp, value),
diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs
new file mode 100644
index 0000000000000..481f06c3ed6db
--- /dev/null
+++ b/compiler/rustc_builtin_macros/src/errors.rs
@@ -0,0 +1,620 @@
+use rustc_errors::{fluent, AddSubdiagnostic, Applicability, Diagnostic};
+use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic};
+use rustc_span::{symbol::Ident, Span, Symbol};
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::asm_args_after_clobber_abi)]
+pub(crate) struct AsmArgsAfterClobberAbi {
+ #[primary_span]
+ #[label]
+ pub(crate) span: Span,
+ #[label(builtin_macros::abi_label)]
+ pub(crate) abi_span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::asm_args_after_options)]
+pub(crate) struct AsmArgsAfterOptions {
+ #[primary_span]
+ #[label]
+ pub(crate) span: Span,
+ #[label(builtin_macros::previous_options_label)]
+ pub(crate) options_spans: Vec,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::asm_args_named_after_explicit_register)]
+pub(crate) struct AsmArgsNamedAfterExplicitRegister {
+ #[primary_span]
+ #[label]
+ pub(crate) span: Span,
+ #[label(builtin_macros::register_label)]
+ pub(crate) register_spans: Vec,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::asm_args_positional_after_named_or_explicit_register)]
+pub(crate) struct AsmArgsPositionalAfterNamedOrExplicitRegister {
+ #[primary_span]
+ #[label]
+ pub(crate) span: Span,
+ #[label(builtin_macros::named_label)]
+ pub(crate) named_spans: Vec,
+ #[label(builtin_macros::register_label)]
+ pub(crate) register_spans: Vec,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::asm_cannot_be_used_with)]
+pub(crate) struct AsmCannotBeUsedWith {
+ pub(crate) left: &'static str,
+ pub(crate) right: &'static str,
+ #[primary_span]
+ pub(crate) spans: Vec,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::asm_clobber_abi_after_options)]
+pub(crate) struct AsmClobberAbiAfterOptions {
+ #[primary_span]
+ pub(crate) span: Span,
+ #[label(builtin_macros::options_label)]
+ pub(crate) options_spans: Vec,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::asm_clobber_abi_needs_an_abi)]
+pub(crate) struct AsmClobberAbiNeedsAnAbi {
+ #[primary_span]
+ #[label]
+ pub(crate) span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::asm_clobber_abi_needs_explicit_registers)]
+pub(crate) struct AsmClobberAbiNeedsExplicitRegisters {
+ #[primary_span]
+ #[label]
+ pub(crate) spans: Vec,
+ #[label(builtin_macros::abi_label)]
+ pub(crate) abi_spans: Vec,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::asm_duplicate_argument)]
+pub(crate) struct AsmDuplicateArgument {
+ pub(crate) name: Symbol,
+ #[primary_span]
+ #[label]
+ pub(crate) span: Span,
+ #[label(builtin_macros::previously_label)]
+ pub(crate) prev_span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::asm_duplicate_option)]
+pub(crate) struct AsmDuplicateOption {
+ pub(crate) symbol: Symbol,
+ #[primary_span]
+ #[label]
+ pub(crate) span: Span,
+ // FIXME: This should be a `tool_only_span_suggestion`
+ #[suggestion(code = "", applicability = "machine-applicable")]
+ pub(crate) full_span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::asm_expected_operand_options_or_template_string)]
+pub(crate) struct AsmExpectedOperandOptionsOrTemplateString {
+ #[primary_span]
+ #[label]
+ pub(crate) span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::asm_expected_operand_clobber_abi_options_or_template_string)]
+pub(crate) struct AsmExpectedOperandClobberAbiOptionsOrTemplateString {
+ #[primary_span]
+ #[label]
+ pub(crate) span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::asm_expected_path_arg_to_sym)]
+pub(crate) struct AsmExpectedPathArgToSym {
+ #[primary_span]
+ pub(crate) span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::asm_expected_register_class_or_explicit_register)]
+pub(crate) struct AsmExpectedRegisterClassOrExplicitRegister {
+ #[primary_span]
+ pub(crate) span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::asm_expected_string_literal)]
+pub(crate) struct AsmExpectedStringLiteral {
+ #[primary_span]
+ #[label]
+ pub(crate) span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::asm_expected_token_comma)]
+pub(crate) struct AsmExpectedTokenComma {
+ #[primary_span]
+ #[label]
+ pub(crate) span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::asm_explicit_register_arg_with_name)]
+pub(crate) struct AsmExplicitRegisterArgWithName {
+ #[primary_span]
+ pub(crate) span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::asm_no_argument_named)]
+pub(crate) struct AsmNoArgumentNamed {
+ pub(crate) name: String,
+ #[primary_span]
+ pub(crate) span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::asm_option_must_be_combined_with_either)]
+pub(crate) struct AsmOptionMustBeCombinedWithEither {
+ pub(crate) option: &'static str,
+ pub(crate) left: &'static str,
+ pub(crate) right: &'static str,
+ #[primary_span]
+ pub(crate) spans: Vec,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::asm_option_noreturn_with_outputs)]
+pub(crate) struct AsmOptionNoreturnWithOutputs {
+ #[primary_span]
+ pub(crate) spans: Vec,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::asm_option_pure_needs_one_output)]
+pub(crate) struct AsmOptionPureNeedsOneOutput {
+ #[primary_span]
+ pub(crate) spans: Vec,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::asm_options_mutually_exclusive)]
+pub(crate) struct AsmOptionsMutuallyExclusive {
+ pub(crate) left: &'static str,
+ pub(crate) right: &'static str,
+ #[primary_span]
+ pub(crate) spans: Vec,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::asm_requires_template_string_arg)]
+pub(crate) struct AsmRequiresTemplateStringArg {
+ #[primary_span]
+ pub(crate) span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::asm_template_modifier_single_char)]
+pub(crate) struct AsmTemplateModifierSingleChar {
+ #[primary_span]
+ pub(crate) span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::asm_underscore_for_input_operands)]
+pub(crate) struct AsmUnderscoreForInputOperands {
+ #[primary_span]
+ pub(crate) span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::boolean_expression_required)]
+pub struct BooleanExpressionRequired {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::unexpected_string_literal)]
+pub struct UnexpectedStringLiteral {
+ #[primary_span]
+ #[suggestion_short(code = ", ", applicability = "maybe-incorrect")]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::argument_expression_required)]
+pub struct ArgumentExpressionRequired {
+ #[primary_span]
+ #[suggestion(code = "", applicability = "maybe-incorrect")]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::not_specified)]
+pub struct NotSpecified {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::multiple_paths_specified)]
+pub struct MultiplePathsSpecified {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::unallowed_literal_path)]
+pub struct UnallowedLiteralPath {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::unaccepted_arguments)]
+pub struct UnacceptedArguments {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::nondeterministic_access)]
+pub struct NondeterministicAccess {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::compile_error)]
+pub struct CompileError {
+ #[primary_span]
+ pub span: Span,
+ pub msg: String,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::byte_string_literal_concatenate)]
+pub struct ByteStringLiteralConcatenate {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::missing_literal)]
+#[note]
+pub struct MissingLiteral {
+ #[primary_span]
+ pub span: Span,
+}
+
+pub enum Snippet {
+ ByteCharacter { span: Span, snippet: String },
+ ByteString { span: Span, snippet: String },
+ WrappingNumberInArray { span: Span, snippet: String },
+}
+
+impl AddSubdiagnostic for Snippet {
+ fn add_to_diagnostic(self, diag: &mut Diagnostic) {
+ match self {
+ Self::ByteCharacter { span, snippet } => {
+ diag.span_suggestion(
+ span,
+ fluent::builtin_macros::use_byte_character,
+ snippet,
+ Applicability::MachineApplicable,
+ );
+ }
+ Self::ByteString { span, snippet } => {
+ diag.span_suggestion(
+ span,
+ fluent::builtin_macros::use_byte_string,
+ snippet,
+ Applicability::MachineApplicable,
+ );
+ }
+ Self::WrappingNumberInArray { span, snippet } => {
+ diag.span_suggestion(
+ span,
+ fluent::builtin_macros::wrap_number_in_array,
+ snippet,
+ Applicability::MachineApplicable,
+ );
+ }
+ }
+ }
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::character_literals_concatenate)]
+pub struct CharacterLiteralsConcatenate {
+ #[primary_span]
+ pub span: Span,
+ #[subdiagnostic]
+ pub sub: Option,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::string_literals_concatenate)]
+pub struct StringLiteralsConcatenate {
+ #[primary_span]
+ pub span: Span,
+ #[subdiagnostic]
+ pub sub: Option,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::float_literals_concatenate)]
+pub struct FloatLiteralsConcatenate {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::boolean_literals_concatenate)]
+pub struct BooleanLiteralsConcatenate {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::numeric_literals_concatenate)]
+pub struct NumericLiteralsConcatenate {
+ #[primary_span]
+ pub span: Span,
+ #[subdiagnostic]
+ pub sub: Option,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::out_of_bound_numeric_literal)]
+pub struct OutOfBoundNumericLiteral {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::invalid_numeric_literal)]
+pub struct InvalidNumericLiteral {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::doubly_nested_array_concatenate)]
+pub struct DoublyNestedArrayConcatenate {
+ #[primary_span]
+ pub span: Span,
+ #[note]
+ pub note: Option<()>,
+ #[help]
+ pub help: Option<()>,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::invalid_repeat_count)]
+pub struct InvalidRepeatCount {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[note]
+#[diag(builtin_macros::byte_literal_expected)]
+pub struct ByteLiteralExpected {
+ #[primary_span]
+ pub spans: Vec,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::missing_arguments)]
+pub struct MissingArguments {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::comma_expected)]
+pub struct CommaExpected {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::ident_args_required)]
+pub struct IdentArgsRequired {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::not_applicable_derive, code = "E0774")]
+pub struct NotApplicableDerive {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ #[label(builtin_macros::item_label)]
+ pub item_span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::trait_path_expected, code = "E0777")]
+pub struct TraitPathExpected<'a> {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ pub help_msg: &'a str,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::path_rejected)]
+pub struct PathRejected<'a> {
+ #[primary_span]
+ #[label]
+ #[suggestion(code = "", applicability = "machine-applicable")]
+ pub span: Span,
+ pub title: &'a str,
+ pub action: &'a str,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::no_default)]
+pub struct NoDefault {
+ #[primary_span]
+ pub span: Span,
+ // FIXME: This should be a `tool_only_span_suggestion`
+ #[subdiagnostic]
+ pub suggestions: Vec,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[suggestion(
+ builtin_macros::variant_suggestion,
+ code = "#[default] {ident}",
+ applicability = "maybe-incorrect"
+)]
+pub struct NoDefaultSuggestion {
+ #[primary_span]
+ pub span: Span,
+ pub ident: Ident,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::multiple_declared_defaults)]
+pub struct MultipleDeclaredDefaults {
+ #[primary_span]
+ pub span: Span,
+ #[label(builtin_macros::multiple_declared_defaults_first)]
+ pub first: Span,
+ #[label(builtin_macros::multiple_declared_defaults_additional)]
+ pub variants: Vec,
+ // FIXME: This should be a `tool_only_multipart_suggestion`
+ #[subdiagnostic]
+ pub suggestions: Vec,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[multipart_suggestion(builtin_macros::variant_suggestion, applicability = "maybe-incorrect")]
+pub struct MultipleDeclaredDefaultsSuggestion {
+ #[suggestion_part(code = "")]
+ pub span: Vec,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::default_not_allowed)]
+pub struct DefaultNotAllowed {
+ #[primary_span]
+ pub span: Span,
+ #[help]
+ pub help: Option<()>,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::default_non_exhaustive)]
+pub struct DefaultNonExhaustive {
+ #[primary_span]
+ pub span: Span,
+ #[label(builtin_macros::default_non_exhaustive_instruction)]
+ pub non_exhustive_attr: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::multiple_default_attributes)]
+pub struct MultipleDefaultAttributes<'a> {
+ #[primary_span]
+ pub span: Span,
+ #[label(builtin_macros::multiple_default_attributes_first)]
+ pub first: Span,
+ #[label(builtin_macros::multiple_default_attributes_rest)]
+ pub rest: Span,
+ #[help(builtin_macros::multiple_default_attributes_suggestion_text)]
+ pub help: Vec,
+ pub suggestion_text: &'a str,
+ // FIXME: This should be a `tool_only_multipart_suggestion`
+ #[subdiagnostic]
+ pub suggestions: MultipleDefaultAttributesSuggestions,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[multipart_suggestion(
+ builtin_macros::multiple_default_attributes_suggestion_text,
+ applicability = "machine-applicable"
+)]
+pub struct MultipleDefaultAttributesSuggestions {
+ #[suggestion_part(code = "")]
+ pub span: Vec,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::default_not_accept_value)]
+pub struct DefaultNotAcceptValue {
+ #[primary_span]
+ #[suggestion_hidden(code = "#[default]", applicability = "maybe-incorrect")]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::unallowed_derive)]
+pub struct UnallowedDerive {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::cannot_be_derived_unions)]
+pub struct CannotBeDerivedUnions {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::empty_argument)]
+pub struct EmptyArgument {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::env_expand_error)]
+pub struct EnvExpandError<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub msg: &'a str,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::format_string_argument_required)]
+pub struct FormatStringArgumentRequired {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::duplicated_argument)]
+pub struct DuplicatedArgument {
+ #[primary_span]
+ pub span: Span,
+ #[label(builtin_macros::multiple_default_attributes_first)]
+ pub prev_span: Span,
+ pub ident: Ident,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(builtin_macros::invalid_positional_arguments)]
+pub struct InvalidPositionalArguments {
+ #[primary_span]
+ pub span: Span,
+ #[label(builtin_macros::invalid_positional_arguments_names)]
+ pub names: Vec,
+}
diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs
index 2100487107517..ecbf1f8487612 100644
--- a/compiler/rustc_builtin_macros/src/format.rs
+++ b/compiler/rustc_builtin_macros/src/format.rs
@@ -20,6 +20,8 @@ use rustc_parse_format::Count;
use std::borrow::Cow;
use std::collections::hash_map::Entry;
+use crate::errors::{DuplicatedArgument, FormatStringArgumentRequired, InvalidPositionalArguments};
+
#[derive(PartialEq)]
enum ArgumentType {
Placeholder(&'static str),
@@ -287,7 +289,7 @@ fn parse_args<'a>(
let mut p = ecx.new_parser_from_tts(tts);
if p.token == token::Eof {
- return Err(ecx.struct_span_err(sp, "requires at least a format string argument"));
+ return Err(ecx.create_err(FormatStringArgumentRequired { span: sp }));
}
let first_token = &p.token;
@@ -348,10 +350,11 @@ fn parse_args<'a>(
p.expect(&token::Eq)?;
let e = p.parse_expr()?;
if let Some(&prev) = names.get(&ident.name) {
- ecx.struct_span_err(e.span, &format!("duplicate argument named `{}`", ident))
- .span_label(args[prev].expr.span, "previously here")
- .span_label(e.span, "duplicate argument")
- .emit();
+ ecx.emit_err(DuplicatedArgument {
+ span: e.span,
+ prev_span: args[prev].expr.span,
+ ident,
+ });
continue;
}
@@ -366,15 +369,10 @@ fn parse_args<'a>(
_ => {
let e = p.parse_expr()?;
if named {
- let mut err = ecx.struct_span_err(
- e.span,
- "positional arguments cannot follow named arguments",
- );
- err.span_label(e.span, "positional arguments must be before named arguments");
- for &pos in names.values() {
- err.span_label(args[pos].expr.span, "named argument");
- }
- err.emit();
+ ecx.emit_err(InvalidPositionalArguments {
+ span: e.span,
+ names: names.values().map(|&pos| args[pos].expr.span).collect(),
+ });
}
args.push(FormatArg { expr: e, name: None });
}
diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs
index 280fa70451141..3bcfe61cb486f 100644
--- a/compiler/rustc_builtin_macros/src/lib.rs
+++ b/compiler/rustc_builtin_macros/src/lib.rs
@@ -13,6 +13,8 @@
#![feature(proc_macro_internals)]
#![feature(proc_macro_quote)]
#![recursion_limit = "256"]
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
extern crate proc_macro;
@@ -37,6 +39,7 @@ mod derive;
mod deriving;
mod edition_panic;
mod env;
+mod errors;
mod format;
mod format_foreign;
mod global_allocator;
diff --git a/compiler/rustc_error_messages/locales/en-US/builtin_macros.ftl b/compiler/rustc_error_messages/locales/en-US/builtin_macros.ftl
index 4d088e27b364a..485368e712071 100644
--- a/compiler/rustc_error_messages/locales/en-US/builtin_macros.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/builtin_macros.ftl
@@ -1,5 +1,228 @@
+builtin_macros_asm_args_after_clobber_abi =
+ arguments are not allowed after clobber_abi
+ .label = argument
+ .abi_label = clobber_abi
+
+builtin_macros_asm_args_after_options =
+ arguments are not allowed after options
+ .label = argument
+ .previous_options_label = previous options
+
+builtin_macros_asm_args_named_after_explicit_register =
+ named arguments cannot follow explicit register arguments
+ .label = named argument
+ .register_label = explicit register argument
+
+builtin_macros_asm_args_positional_after_named_or_explicit_register =
+ positional arguments cannot follow named arguments or explicit register arguments
+ .label = positional argument
+ .named_label = named argument
+ .register_label = explicit register argument
+
+builtin_macros_asm_cannot_be_used_with = `{$left}` cannot be used with `{$right}`
+
+builtin_macros_asm_clobber_abi_after_options =
+ clobber_abi is not allowed after options
+ .options_label = options
+
+builtin_macros_asm_clobber_abi_needs_an_abi =
+ at least one abi must be provided as an argument to `clobber_abi`
+
+builtin_macros_asm_clobber_abi_needs_explicit_registers =
+ asm with `clobber_abi` must specify explicit registers for outputs
+ .label = generic outputs
+ .abi_label = clobber_abi
+
+builtin_macros_asm_duplicate_argument =
+ duplicate argument named `{$name}`
+ .label = duplicate argument
+ .previously_label = previously here
+
+builtin_macros_asm_duplicate_option =
+ the `{$symbol}` option was already provided
+ .label = this option was already provided
+ .suggestion = remove this option
+
+builtin_macros_asm_expected_operand_options_or_template_string =
+ expected operand, options, or additional template string
+ .label = expected operand, options, or additional template string
+
+builtin_macros_asm_expected_operand_clobber_abi_options_or_template_string =
+ expected operand, clobber_abi, options, or additional template string
+ .label = expected operand, clobber_abi, options, or additional template string
+
+builtin_macros_asm_expected_path_arg_to_sym = expected a path for argument to `sym`
+
+builtin_macros_asm_expected_register_class_or_explicit_register =
+ expected register class or explicit register
+
+builtin_macros_asm_expected_string_literal =
+ expected string literal
+ .label = not a string literal
+
+builtin_macros_asm_expected_token_comma =
+ expected token: `,`
+ .label = expected `,`
+
+builtin_macros_asm_explicit_register_arg_with_name = explicit register arguments cannot have names
+
+builtin_macros_asm_no_argument_named = there is no argument named `{$name}`
+
+builtin_macros_asm_option_must_be_combined_with_either =
+ the `{$option}` option must be combined with either `{$left}` or `{$right}`
+
+builtin_macros_asm_option_noreturn_with_outputs =
+ asm outputs are not allowed with the `noreturn` option
+
+builtin_macros_asm_option_pure_needs_one_output =
+ asm with the `pure` option must have at least one output
+
+builtin_macros_asm_options_mutually_exclusive =
+ the `{$left}` and `${right}` options are mutually exclusive
+
+builtin_macros_asm_requires_template_string_arg = requires at least a template string argument
+
+builtin_macros_asm_template_modifier_single_char = asm template modifier must be a single character
+
+builtin_macros_asm_underscore_for_input_operands = _ cannot be used for input operands
+
builtin_macros_requires_cfg_pattern =
macro requires a cfg-pattern as an argument
.label = cfg-pattern required
builtin_macros_expected_one_cfg_pattern = expected 1 cfg-pattern
+
+builtin_macros_boolean_expression_required =
+ macro requires a boolean expression as an argument
+ .label = boolean expression required
+
+builtin_macros_unexpected_string_literal = unexpected string literal
+ .suggestion = try adding a comma
+
+builtin_macros_argument_expression_required =
+ macro requires an expression as an argument
+ .suggestion = try removing semicolon
+
+builtin_macros_not_specified =
+ `cfg_accessible` path is not specified
+
+builtin_macros_multiple_paths_specified =
+ multiple `cfg_accessible` paths are specified
+
+builtin_macros_unallowed_literal_path =
+ `cfg_accessible` path cannot be a literal
+
+builtin_macros_unaccepted_arguments =
+ `cfg_accessible` path cannot accept arguments
+
+builtin_macros_nondeterministic_access =
+ cannot determine whether the path is accessible or not
+
+builtin_macros_compile_error = {$msg}
+
+builtin_macros_byte_string_literal_concatenate =
+ cannot concatenate a byte string literal
+
+builtin_macros_missing_literal = expected a literal
+ .note = only literals (like `\"foo\"`, `42` and `3.14`) can be passed to `concat!()`
+
+builtin_macros_character_literals_concatenate = cannot concatenate character literals
+
+builtin_macros_string_literals_concatenate = cannot concatenate string literals
+
+builtin_macros_use_byte_character = try using a byte character
+
+builtin_macros_use_byte_string = try using a byte string
+
+builtin_macros_float_literals_concatenate = cannot concatenate float literals
+
+builtin_macros_boolean_literals_concatenate = cannot concatenate boolean literals
+
+builtin_macros_wrap_number_in_array = try wrapping the number in an array
+
+builtin_macros_numeric_literals_concatenate = cannot concatenate numeric literals
+
+builtin_macros_out_of_bound_numeric_literal = numeric literal is out of bounds
+
+builtin_macros_invalid_numeric_literal = numeric literal is not a `u8`
+
+builtin_macros_doubly_nested_array_concatenate = cannot concatenate doubly nested array
+ .note = byte strings are treated as arrays of bytes
+ .help = try flattening the array
+
+builtin_macros_invalid_repeat_count = repeat count is not a positive number
+
+builtin_macros_byte_literal_expected = expected a byte literal
+ .note = only byte literals (like `b\"foo\"`, `b's'`, and `[3, 4, 5]`) can be passed to `concat_bytes!()`
+
+builtin_macros_missing_arguments = concat_idents! takes 1 or more arguments
+
+builtin_macros_comma_expected = concat_idents! expecting comma
+
+builtin_macros_ident_args_required = concat_idents! requires ident args
+
+builtin_macros_not_applicable_derive =
+ `derive` may only be applied to `struct`s, `enum`s and `union`s
+ .label = not applicable here
+ .item_label = not a `struct`, `enum` or `union`
+
+builtin_macros_trait_path_expected =
+ expected path to a trait, found literal
+ .label = not a trait
+ .help = {$help_msg}
+
+builtin_macros_path_rejected = {$title}
+ .suggestion = {$action}
+
+builtin_macros_no_default = no default declared
+ .help = make a unit variant default by placing `#[default]` above it
+
+builtin_macros_variant_suggestion = make `{$ident}` default
+
+builtin_macros_multiple_declared_defaults_first = = first default
+
+builtin_macros_multiple_declared_defaults_additional = additional default
+
+builtin_macros_multiple_declared_defaults = multiple declared defaults
+ .note = only one variant can be default
+
+builtin_macros_default_not_allowed =
+ the `#[default]` attribute may only be used on unit enum variants
+ .help = consider a manual implementation of `Default`
+
+builtin_macros_default_non_exhaustive = default variant must be exhaustive
+ .help = consider a manual implementation of `Default`
+
+builtin_macros_default_non_exhaustive_instruction = declared `#[non_exhaustive]` here
+
+builtin_macros_multiple_default_attributes_first = `#[default]` used here
+
+builtin_macros_multiple_default_attributes_rest = `#[default]` used again here
+
+builtin_macros_multiple_default_attributes_suggestion_text = {$suggestion_text}
+
+builtin_macros_multiple_default_attributes = multiple `#[default]` attributes
+ .note = only one `#[default]` attribute is needed
+
+builtin_macros_default_not_accept_value = `#[default]` attribute does not accept a value
+ .suggestion = try using `#[default]`
+
+builtin_macros_unallowed_derive = `derive` cannot be used on items with type macros
+
+builtin_macros_cannot_be_derived_unions = this trait cannot be derived for unions
+
+builtin_macros_empty_argument = env! takes 1 or 2 arguments
+
+builtin_macros_env_expand_error = {$msg}
+
+builtin_macros_format_string_argument_required = requires at least a format string argument
+
+builtin_macros_duplicated_argument = duplicate argument named `{$ident}`
+ .label = duplicate argument
+
+builtin_macros_duplicated_argument_prev = previously here
+
+builtin_macros_invalid_positional_arguments = positional arguments cannot follow named arguments
+ .label = positional arguments must be before named arguments
+
+builtin_macros_invalid_positional_arguments_names = named argument