diff options
Diffstat (limited to 'compiler/rustc_builtin_macros/src')
| -rw-r--r-- | compiler/rustc_builtin_macros/src/asm.rs | 28 | ||||
| -rw-r--r-- | compiler/rustc_builtin_macros/src/assert/context.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_builtin_macros/src/errors.rs | 68 | ||||
| -rw-r--r-- | compiler/rustc_builtin_macros/src/format.rs | 8 | ||||
| -rw-r--r-- | compiler/rustc_builtin_macros/src/lib.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_builtin_macros/src/offset_of.rs | 99 | ||||
| -rw-r--r-- | compiler/rustc_builtin_macros/src/test.rs | 16 | ||||
| -rw-r--r-- | compiler/rustc_builtin_macros/src/test_harness.rs | 6 |
8 files changed, 188 insertions, 42 deletions
diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index 8c1579baacb..bcdd58a0901 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -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<P<ast::Expr>>, pub operands: Vec<(ast::InlineAsmOperand, Span)>, @@ -205,7 +207,7 @@ pub fn parse_asm_args<'a>( // of the argument available. if explicit_reg { if name.is_some() { - diag.struct_span_err(span, "explicit register arguments cannot have names").emit(); + diag.emit_err(errors::AsmExplicitRegisterName { span }); } args.reg_args.insert(slot); } else if let Some(name) = name { @@ -240,25 +242,19 @@ 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") - .emit(); + diag.emit_err(errors::AsmMutuallyExclusive { spans, opt1: "nomem", opt2: "readonly" }); } 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") - .emit(); + diag.emit_err(errors::AsmMutuallyExclusive { spans, opt1: "pure", opt2: "noreturn" }); } 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( - spans, - "the `pure` option must be combined with either `nomem` or `readonly`", - ) - .emit(); + diag.emit_err(errors::AsmPureCombine { spans }); } let mut have_real_output = false; @@ -285,11 +281,7 @@ 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(); + diag.emit_err(errors::AsmPureNoOutput { spans: args.options_spans.clone() }); } if args.options.contains(ast::InlineAsmOptions::NORETURN) && !outputs_sp.is_empty() { let err = diag @@ -705,11 +697,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl .ty_span .map(|sp| template_sp.from_inner(InnerSpan::new(sp.start, sp.end))) .unwrap_or(template_sp); - ecx.struct_span_err( - span, - "asm template modifier must be a single character", - ) - .emit(); + ecx.emit_err(errors::AsmModifierInvalid { span }); modifier = None; } diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs index c9e3cd486f8..090e00616fb 100644 --- a/compiler/rustc_builtin_macros/src/assert/context.rs +++ b/compiler/rustc_builtin_macros/src/assert/context.rs @@ -301,6 +301,7 @@ impl<'cx, 'a> Context<'cx, 'a> { | ExprKind::If(_, _, _) | ExprKind::IncludedBytes(..) | ExprKind::InlineAsm(_) + | ExprKind::OffsetOf(_, _) | ExprKind::Let(_, _, _) | ExprKind::Lit(_) | ExprKind::Loop(_, _, _) diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index 630f9b87bc3..b146988a3c2 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -551,3 +551,71 @@ pub(crate) struct FormatPositionalMismatch { #[subdiagnostic] pub(crate) highlight: SingleLabelManySpans, } + +#[derive(Diagnostic)] +#[diag(builtin_macros_test_case_non_item)] +pub(crate) struct TestCaseNonItem { + #[primary_span] + pub(crate) span: Span, +} + +#[derive(Diagnostic)] +#[diag(builtin_macros_test_bad_fn)] +pub(crate) struct TestBadFn { + #[primary_span] + pub(crate) span: Span, + #[label] + pub(crate) cause: Span, + pub(crate) kind: &'static str, +} + +#[derive(Diagnostic)] +#[diag(builtin_macros_asm_explicit_register_name)] +pub(crate) struct AsmExplicitRegisterName { + #[primary_span] + pub(crate) span: Span, +} + +#[derive(Diagnostic)] +#[diag(builtin_macros_asm_mutually_exclusive)] +pub(crate) struct AsmMutuallyExclusive { + #[primary_span] + pub(crate) spans: Vec<Span>, + pub(crate) opt1: &'static str, + pub(crate) opt2: &'static str, +} + +#[derive(Diagnostic)] +#[diag(builtin_macros_asm_pure_combine)] +pub(crate) struct AsmPureCombine { + #[primary_span] + pub(crate) spans: Vec<Span>, +} + +#[derive(Diagnostic)] +#[diag(builtin_macros_asm_pure_no_output)] +pub(crate) struct AsmPureNoOutput { + #[primary_span] + pub(crate) spans: Vec<Span>, +} + +#[derive(Diagnostic)] +#[diag(builtin_macros_asm_modifier_invalid)] +pub(crate) struct AsmModifierInvalid { + #[primary_span] + pub(crate) span: Span, +} + +#[derive(Diagnostic)] +#[diag(builtin_macros_test_runner_invalid)] +pub(crate) struct TestRunnerInvalid { + #[primary_span] + pub(crate) span: Span, +} + +#[derive(Diagnostic)] +#[diag(builtin_macros_test_runner_nargs)] +pub(crate) struct TestRunnerNargs { + #[primary_span] + pub(crate) span: Span, +} diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index f0fc61d7c4f..f17df5b0a83 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -141,13 +141,7 @@ fn parse_args<'a>(ecx: &mut ExtCtxt<'a>, sp: Span, tts: TokenStream) -> PResult< args: args .named_args() .iter() - .filter_map(|a| { - if let Some(ident) = a.kind.ident() { - Some((a, ident)) - } else { - None - } - }) + .filter_map(|a| a.kind.ident().map(|ident| (a, ident))) .map(|(arg, n)| n.span.to(arg.expr.span)) .collect(), }); diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index 37fbd03a6a2..8f86ef44aa3 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -24,7 +24,7 @@ use crate::deriving::*; use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; use rustc_expand::base::{MacroExpanderFn, ResolverExpand, SyntaxExtensionKind}; use rustc_expand::proc_macro::BangProcMacro; -use rustc_macros::fluent_messages; +use rustc_fluent_macro::fluent_messages; use rustc_span::symbol::sym; mod alloc_error_handler; @@ -45,6 +45,7 @@ mod format; mod format_foreign; mod global_allocator; mod log_syntax; +mod offset_of; mod source_util; mod test; mod trace_macros; @@ -92,6 +93,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) { line: source_util::expand_line, log_syntax: log_syntax::expand_log_syntax, module_path: source_util::expand_mod, + offset_of: offset_of::expand_offset_of, option_env: env::expand_option_env, core_panic: edition_panic::expand_panic, std_panic: edition_panic::expand_panic, diff --git a/compiler/rustc_builtin_macros/src/offset_of.rs b/compiler/rustc_builtin_macros/src/offset_of.rs new file mode 100644 index 00000000000..0ef3e000e41 --- /dev/null +++ b/compiler/rustc_builtin_macros/src/offset_of.rs @@ -0,0 +1,99 @@ +use rustc_ast as ast; +use rustc_ast::ptr::P; +use rustc_ast::token; +use rustc_ast::tokenstream::TokenStream; +use rustc_errors::PResult; +use rustc_expand::base::{self, *}; +use rustc_macros::Diagnostic; +use rustc_parse::parser::Parser; +use rustc_span::{symbol::Ident, Span}; + +#[derive(Diagnostic)] +#[diag(builtin_macros_offset_of_expected_field)] +struct ExpectedField { + #[primary_span] + span: Span, +} + +#[derive(Diagnostic)] +#[diag(builtin_macros_offset_of_expected_two_args)] +struct ExpectedTwoArgs { + #[primary_span] + span: Span, +} + +fn parse_field<'a>(cx: &ExtCtxt<'a>, p: &mut Parser<'a>) -> PResult<'a, Ident> { + let token = p.token.uninterpolate(); + let field = match token.kind { + token::Ident(name, _) => Ident::new(name, token.span), + token::Literal(token::Lit { kind: token::Integer, symbol, suffix: None }) => { + Ident::new(symbol, token.span) + } + _ => return Err(cx.create_err(ExpectedField { span: p.token.span })), + }; + + p.bump(); + + Ok(field) +} + +fn parse_args<'a>( + cx: &mut ExtCtxt<'a>, + sp: Span, + tts: TokenStream, +) -> PResult<'a, (P<ast::Ty>, P<[Ident]>)> { + let mut p = cx.new_parser_from_tts(tts); + + let container = p.parse_ty()?; + + p.expect(&token::Comma)?; + + if p.eat(&token::Eof) { + return Err(cx.create_err(ExpectedTwoArgs { span: sp })); + } + + let mut fields = Vec::new(); + + loop { + let field = parse_field(cx, &mut p)?; + fields.push(field); + + if p.eat(&token::Dot) { + continue; + } + + p.eat(&token::Comma); + + if !p.eat(&token::Eof) { + return Err(cx.create_err(ExpectedTwoArgs { span: sp })); + } + + break; + } + + Ok((container, fields.into())) +} + +pub fn expand_offset_of<'cx>( + cx: &'cx mut ExtCtxt<'_>, + sp: Span, + tts: TokenStream, +) -> Box<dyn base::MacResult + 'cx> { + match parse_args(cx, sp, tts) { + Ok((container, fields)) => { + let expr = P(ast::Expr { + id: ast::DUMMY_NODE_ID, + kind: ast::ExprKind::OffsetOf(container, fields), + span: sp, + attrs: ast::AttrVec::new(), + tokens: None, + }); + + MacEager::expr(expr) + } + Err(mut err) => { + err.emit(); + DummyResult::any(sp) + } + } +} diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index 79d8be2484b..49ee276af4e 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -1,3 +1,4 @@ +use crate::errors; /// The expansion from a test function to the appropriate test struct for libtest /// Ideally, this code would be in libtest but for efficiency and error messages it lives here. use crate::util::{check_builtin_macro_attribute, warn_on_duplicate_attribute}; @@ -40,12 +41,7 @@ pub fn expand_test_case( unreachable!() }, _ => { - ecx.struct_span_err( - anno_item.span(), - "`#[test_case]` attribute is only allowed on items", - ) - .emit(); - + ecx.emit_err(errors::TestCaseNonItem { span: anno_item.span() }); return vec![]; } }; @@ -533,15 +529,11 @@ fn has_test_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool { match &i.kind { ast::ItemKind::Fn(box ast::Fn { sig, generics, .. }) => { if let ast::Unsafe::Yes(span) = sig.header.unsafety { - sd.struct_span_err(i.span, "unsafe functions cannot be used for tests") - .span_label(span, "`unsafe` because of this") - .emit(); + sd.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "unsafe" }); return false; } if let ast::Async::Yes { span, .. } = sig.header.asyncness { - sd.struct_span_err(i.span, "async functions cannot be used for tests") - .span_label(span, "`async` because of this") - .emit(); + sd.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "async" }); return false; } diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs index 80f497333a6..be4ba66c082 100644 --- a/compiler/rustc_builtin_macros/src/test_harness.rs +++ b/compiler/rustc_builtin_macros/src/test_harness.rs @@ -19,6 +19,8 @@ use tracing::debug; use std::{iter, mem}; +use crate::errors; + #[derive(Clone)] struct Test { span: Span, @@ -385,11 +387,11 @@ fn get_test_runner(sd: &rustc_errors::Handler, krate: &ast::Crate) -> Option<ast [single] => match single.meta_item() { Some(meta_item) if meta_item.is_word() => return Some(meta_item.path.clone()), _ => { - sd.struct_span_err(span, "`test_runner` argument must be a path").emit(); + sd.emit_err(errors::TestRunnerInvalid { span }); } }, _ => { - sd.struct_span_err(span, "`#![test_runner(..)]` accepts exactly 1 argument").emit(); + sd.emit_err(errors::TestRunnerNargs { span }); } } None |
