Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

builtin_macros: Migrate diagnostic #101935

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
198 changes: 77 additions & 121 deletions compiler/rustc_builtin_macros/src/asm.rs

Large diffs are not rendered by default.

33 changes: 10 additions & 23 deletions compiler/rustc_builtin_macros/src/assert.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
mod context;

use crate::edition_panic::use_panic_2021;
use crate::errors::{self, ArgumentExpressionRequired};
use rustc_ast::ptr::P;
use rustc_ast::token;
use rustc_ast::tokenstream::{DelimSpan, TokenStream};
use rustc_ast::{Expr, ExprKind, MacArgs, MacCall, MacDelimiter, Path, PathSegment, UnOp};
use rustc_ast_pretty::pprust;
use rustc_errors::{Applicability, PResult};
use rustc_errors::PResult;
use rustc_expand::base::{DummyResult, ExtCtxt, MacEager, MacResult};
use rustc_parse::parser::Parser;
use rustc_span::symbol::{sym, Ident, Symbol};
Expand Down Expand Up @@ -113,9 +114,7 @@ fn parse_assert<'a>(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()?;
Expand All @@ -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();
}
Expand All @@ -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)
Expand All @@ -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<TokenStream> {
let ts = parser.parse_tokens();
if !ts.is_empty() { Some(ts) } else { None }
if !ts.is_empty() {
Some(ts)
} else {
None
}
}
21 changes: 16 additions & 5 deletions compiler/rustc_builtin_macros/src/cfg_accessible.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down Expand Up @@ -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),
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_builtin_macros/src/compile_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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)
}
8 changes: 4 additions & 4 deletions compiler/rustc_builtin_macros/src/concat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand Down
90 changes: 44 additions & 46 deletions compiler/rustc_builtin_macros/src/concat_bytes.rs
Original file line number Diff line number Diff line change
@@ -1,69 +1,64 @@
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<rustc_ast::Expr>, is_nested: bool) {
let ast::ExprKind::Lit(lit) = &expr.kind else {
unreachable!();
};
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!(),
}
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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 {
Expand All @@ -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));
Expand Down
8 changes: 5 additions & 3 deletions compiler/rustc_builtin_macros/src/concat_idents.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<dyn base::MacResult + 'cx> {
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);
}

Expand All @@ -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);
}
}
Expand All @@ -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);
}
}
Expand Down
21 changes: 4 additions & 17 deletions compiler/rustc_builtin_macros/src/derive.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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
}
Expand All @@ -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 => {}
Expand Down
Loading