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

Migrate most of rustc_builtin_macros to diagnostic impls #110092

Merged
merged 1 commit into from
Apr 11, 2023
Merged
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
146 changes: 146 additions & 0 deletions compiler/rustc_builtin_macros/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,149 @@ builtin_macros_requires_cfg_pattern =
.label = cfg-pattern required

builtin_macros_expected_one_cfg_pattern = expected 1 cfg-pattern

builtin_macros_alloc_error_must_be_fn = alloc_error_handler must be a function

builtin_macros_assert_requires_boolean = macro requires a boolean expression as an argument
.label = boolean expression required

builtin_macros_assert_requires_expression = macro requires an expression as an argument
.suggestion = try removing semicolon

builtin_macros_assert_missing_comma = unexpected string literal
.suggestion = try adding a comma

builtin_macros_cfg_accessible_unspecified_path = `cfg_accessible` path is not specified
builtin_macros_cfg_accessible_multiple_paths = multiple `cfg_accessible` paths are specified
builtin_macros_cfg_accessible_literal_path = `cfg_accessible` path cannot be a literal
builtin_macros_cfg_accessible_has_args = `cfg_accessible` path cannot accept arguments

builtin_macros_cfg_accessible_indeterminate = cannot determine whether the path is accessible or not

builtin_macros_concat_bytestr = cannot concatenate a byte string literal

builtin_macros_concat_missing_literal = expected a literal
.note = only literals (like `"foo"`, `-42` and `3.14`) can be passed to `concat!()`

builtin_macros_concat_bytes_missing_literal = 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_concat_bytes_invalid = cannot concatenate {$lit_kind} literals
.byte_char = try using a byte character
.byte_str = try using a byte string
.number_array = try wrapping the number in an array

builtin_macros_concat_bytes_oob = numeric literal is out of bounds

builtin_macros_concat_bytes_non_u8 = numeric literal is not a `u8`

builtin_macros_concat_bytes_array = cannot concatenate doubly nested array
.note = byte strings are treated as arrays of bytes
.help = try flattening the array

builtin_macros_concat_bytes_bad_repeat = repeat count is not a positive number

builtin_macros_concat_idents_missing_args = `concat_idents!()` takes 1 or more arguments
builtin_macros_concat_idents_missing_comma = `concat_idents!()` expecting comma
builtin_macros_concat_idents_ident_args = `concat_idents!()` requires ident args

builtin_macros_bad_derive_target = `derive` may only be applied to `struct`s, `enum`s and `union`s
.label = not applicable here
.label2 = not a `struct`, `enum` or `union`

builtin_macros_unexpected_lit = expected path to a trait, found literal
.label = not a trait
.str_lit = try using `#[derive({$sym})]`
.other = for example, write `#[derive(Debug)]` for `Debug`

builtin_macros_derive_path_args_list = traits in `#[derive(...)]` don't accept arguments
.suggestion = remove the arguments

builtin_macros_derive_path_args_value = traits in `#[derive(...)]` don't accept values
.suggestion = remove the value

builtin_macros_derive_macro_call = `derive` cannot be used on items with type macros

builtin_macros_cannot_derive_union = this trait cannot be derived for unions

builtin_macros_no_default_variant = no default declared
.help = make a unit variant default by placing `#[default]` above it
.suggestion = make `{$ident}` default

builtin_macros_multiple_defaults = multiple declared defaults
.label = first default
.additional = additional default
.note = only one variant can be default
.suggestion = make `{$ident}` default

builtin_macros_non_unit_default = the `#[default]` attribute may only be used on unit enum variants
.help = consider a manual implementation of `Default`

builtin_macros_non_exhaustive_default = default variant must be exhaustive
.label = declared `#[non_exhaustive]` here
.help = consider a manual implementation of `Default`

builtin_macros_multiple_default_attrs = multiple `#[default]` attributes
.note = only one `#[default]` attribute is needed
.label = `#[default]` used here
.label_again = `#[default]` used again here
.help = try removing {$only_one ->
[true] this
*[false] these
}

builtin_macros_default_arg = `#[default]` attribute does not accept a value
.suggestion = try using `#[default]`

builtin_macros_env_takes_args = `env!()` takes 1 or 2 arguments

builtin_macros_env_not_defined = environment variable `{$var}` not defined at compile time
.cargo = Cargo sets build script variables at run time. Use `std::env::var("{$var}")` instead
.other = use `std::env::var("{$var}")` to read the variable at run time

builtin_macros_format_requires_string = requires at least a format string argument

builtin_macros_format_duplicate_arg = duplicate argument named `{$ident}`
.label1 = previously here
.label2 = duplicate argument

builtin_macros_format_positional_after_named = positional arguments cannot follow named arguments
.label = positional arguments must be before named arguments
.named_args = named argument

builtin_macros_format_string_invalid = invalid format string: {$desc}
.label = {$label1} in format string
.note = {$note}
.second_label = {$label}

builtin_macros_sugg = consider using a positional formatting argument instead

builtin_macros_format_no_arg_named = there is no argument named `{$name}`
.note = did you intend to capture a variable `{$name}` from the surrounding scope?
.note2 = to avoid ambiguity, `format_args!` cannot capture variables when the format string is expanded from a macro

builtin_macros_format_unknown_trait = unknown format trait `{$ty}`
.note = the only appropriate formatting traits are:
- ``, which uses the `Display` trait
- `?`, which uses the `Debug` trait
- `e`, which uses the `LowerExp` trait
- `E`, which uses the `UpperExp` trait
- `o`, which uses the `Octal` trait
- `p`, which uses the `Pointer` trait
- `b`, which uses the `Binary` trait
- `x`, which uses the `LowerHex` trait
- `X`, which uses the `UpperHex` trait
.suggestion = use the `{$trait_name}` trait

builtin_macros_format_unused_arg = {$named ->
[true] named argument
*[false] argument
} never used

builtin_macros_format_unused_args = multiple unused formatting arguments
.label = multiple missing formatting specifiers

builtin_macros_format_pos_mismatch = {$n} positional {$n ->
[one] argument
*[more] arguments
} in format string, but {$desc}
3 changes: 2 additions & 1 deletion compiler/rustc_builtin_macros/src/alloc_error_handler.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::errors;
use crate::util::check_builtin_macro_attribute;

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

Expand Down
28 changes: 6 additions & 22 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;
use rustc_ast::ptr::P;
use rustc_ast::token;
use rustc_ast::tokenstream::{DelimSpan, TokenStream};
use rustc_ast::{DelimArgs, Expr, ExprKind, 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 @@ -114,9 +115,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::AssertRequiresBoolean { span: sp }));
}

let cond_expr = parser.parse_expr()?;
Expand All @@ -129,15 +128,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(errors::AssertRequiresExpression { span: sp, token: parser.token.span });
parser.bump();
}

Expand All @@ -149,15 +140,8 @@ 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();
let comma = parser.prev_token.span.shrink_to_hi();
cx.emit_err(errors::AssertMissingComma { span: parser.token.span, comma });

parse_custom_message(&mut parser)
} else if parser.eat(&token::Comma) {
Expand Down
21 changes: 3 additions & 18 deletions compiler/rustc_builtin_macros/src/cfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
//! a literal `true` or `false` based on whether the given cfg matches the
//! current compilation environment.

use crate::errors;
use rustc_ast as ast;
use rustc_ast::token;
use rustc_ast::tokenstream::TokenStream;
use rustc_attr as attr;
use rustc_errors::PResult;
use rustc_expand::base::{self, *};
use rustc_macros::Diagnostic;
use rustc_span::Span;

pub fn expand_cfg(
Expand All @@ -35,34 +35,19 @@ pub fn expand_cfg(
}
}

#[derive(Diagnostic)]
#[diag(builtin_macros_requires_cfg_pattern)]
struct RequiresCfgPattern {
#[primary_span]
#[label]
span: Span,
}

#[derive(Diagnostic)]
#[diag(builtin_macros_expected_one_cfg_pattern)]
struct OneCfgPattern {
#[primary_span]
span: Span,
}

fn parse_cfg<'a>(cx: &mut ExtCtxt<'a>, span: Span, tts: TokenStream) -> PResult<'a, ast::MetaItem> {
let mut p = cx.new_parser_from_tts(tts);

if p.token == token::Eof {
return Err(cx.create_err(RequiresCfgPattern { span }));
return Err(cx.create_err(errors::RequiresCfgPattern { span }));
}

let cfg = p.parse_meta_item()?;

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

if !p.eat(&token::Eof) {
return Err(cx.create_err(OneCfgPattern { span }));
return Err(cx.create_err(errors::OneCfgPattern { span }));
}

Ok(cfg)
Expand Down
18 changes: 13 additions & 5 deletions compiler/rustc_builtin_macros/src/cfg_accessible.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! Implementation of the `#[cfg_accessible(path)]` attribute macro.

use crate::errors;
use rustc_ast as ast;
use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, Indeterminate, MultiItemModifier};
use rustc_feature::AttributeTemplate;
Expand All @@ -10,15 +11,22 @@ use rustc_span::Span;
pub(crate) struct Expander;

fn validate_input<'a>(ecx: &mut ExtCtxt<'_>, mi: &'a ast::MetaItem) -> Option<&'a ast::Path> {
use errors::CfgAccessibleInvalid::*;
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(UnspecifiedPath(mi.span));
}
Some([_, .., l]) => {
ecx.emit_err(MultiplePaths(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(LiteralPath(nmi.span()));
}
Some(mi) => {
if !mi.is_word() {
ecx.span_err(mi.span, "`cfg_accessible` path cannot accept arguments");
ecx.emit_err(HasArguments(mi.span));
}
return Some(&mi.path);
}
Expand Down Expand Up @@ -53,7 +61,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(errors::CfgAccessibleIndeterminate { span });
ExpandResult::Ready(vec![item])
}
Err(Indeterminate) => ExpandResult::Retry(item),
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_builtin_macros/src/compile_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ pub fn expand_compile_error<'cx>(
return DummyResult::any(sp);
};

#[expect(
rustc::diagnostic_outside_of_impl,
reason = "diagnostic message is specified by user"
)]
#[expect(rustc::untranslatable_diagnostic, reason = "diagnostic message is specified by user")]
cx.span_err(sp, var.as_str());

DummyResult::any(sp)
Expand Down
10 changes: 5 additions & 5 deletions compiler/rustc_builtin_macros/src/concat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ use rustc_expand::base::{self, DummyResult};
use rustc_session::errors::report_lit_error;
use rustc_span::symbol::Symbol;

use crate::errors;

pub fn expand_concat(
cx: &mut base::ExtCtxt<'_>,
sp: rustc_span::Span,
Expand Down Expand Up @@ -31,7 +33,7 @@ pub fn expand_concat(
accumulator.push_str(&b.to_string());
}
Ok(ast::LitKind::Byte(..) | ast::LitKind::ByteStr(..)) => {
cx.span_err(e.span, "cannot concatenate a byte string literal");
cx.emit_err(errors::ConcatBytestr { span: e.span });
has_errors = true;
}
Ok(ast::LitKind::Err) => {
Expand All @@ -55,7 +57,7 @@ pub fn expand_concat(
}
}
ast::ExprKind::IncludedBytes(..) => {
cx.span_err(e.span, "cannot concatenate a byte string literal")
cx.emit_err(errors::ConcatBytestr { span: e.span });
}
ast::ExprKind::Err => {
has_errors = true;
Expand All @@ -67,9 +69,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(errors::ConcatMissingLiteral { spans: missing_literal });
return DummyResult::any(sp);
} else if has_errors {
return DummyResult::any(sp);
Expand Down
Loading