diff options
Diffstat (limited to 'compiler/rustc_builtin_macros')
| -rw-r--r-- | compiler/rustc_builtin_macros/Cargo.toml | 4 | ||||
| -rw-r--r-- | compiler/rustc_builtin_macros/messages.ftl | 33 | ||||
| -rw-r--r-- | compiler/rustc_builtin_macros/src/asm.rs | 527 | ||||
| -rw-r--r-- | compiler/rustc_builtin_macros/src/autodiff.rs | 140 | ||||
| -rw-r--r-- | compiler/rustc_builtin_macros/src/deriving/clone.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_builtin_macros/src/deriving/generic/mod.rs | 9 | ||||
| -rw-r--r-- | compiler/rustc_builtin_macros/src/errors.rs | 88 | ||||
| -rw-r--r-- | compiler/rustc_builtin_macros/src/lib.rs | 9 | ||||
| -rw-r--r-- | compiler/rustc_builtin_macros/src/test_harness.rs | 6 |
11 files changed, 300 insertions, 524 deletions
diff --git a/compiler/rustc_builtin_macros/Cargo.toml b/compiler/rustc_builtin_macros/Cargo.toml index 1289d21308b..4c1264c6f1c 100644 --- a/compiler/rustc_builtin_macros/Cargo.toml +++ b/compiler/rustc_builtin_macros/Cargo.toml @@ -10,6 +10,7 @@ doctest = false # tidy-alphabetical-start rustc_ast = { path = "../rustc_ast" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } +rustc_attr_data_structures = { path = "../rustc_attr_data_structures" } rustc_attr_parsing = { path = "../rustc_attr_parsing" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } @@ -23,6 +24,9 @@ rustc_lint_defs = { path = "../rustc_lint_defs" } rustc_macros = { path = "../rustc_macros" } rustc_parse = { path = "../rustc_parse" } rustc_parse_format = { path = "../rustc_parse_format" } +# We must use the proc_macro version that we will compile proc-macros against, +# not the one from our own sysroot. +rustc_proc_macro = { path = "../rustc_proc_macro" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl index 73be954cefd..d32e6f1558e 100644 --- a/compiler/rustc_builtin_macros/messages.ftl +++ b/compiler/rustc_builtin_macros/messages.ftl @@ -1,6 +1,11 @@ builtin_macros_alloc_error_must_be_fn = alloc_error_handler must be a function builtin_macros_alloc_must_statics = allocators must be statics +builtin_macros_asm_attribute_not_supported = + this attribute is not supported on assembly +builtin_macros_asm_cfg = + the `#[cfg(/* ... */)]` and `#[cfg_attr(/* ... */)]` attributes on assembly are unstable + builtin_macros_asm_clobber_abi = clobber_abi builtin_macros_asm_clobber_no_reg = asm with `clobber_abi` must specify explicit registers for outputs builtin_macros_asm_clobber_outputs = generic outputs @@ -9,17 +14,6 @@ builtin_macros_asm_duplicate_arg = duplicate argument named `{$name}` .label = previously here .arg = duplicate argument -builtin_macros_asm_expected_comma = expected token: `,` - .label = expected `,` - -builtin_macros_asm_expected_other = expected operand, {$is_inline_asm -> - [false] options - *[true] clobber_abi, options - }, or additional template string - -builtin_macros_asm_expected_string_literal = expected string literal - .label = not a string literal - builtin_macros_asm_explicit_register_name = explicit register arguments cannot have names builtin_macros_asm_mayunwind = asm labels are not allowed with the `may_unwind` option @@ -45,17 +39,8 @@ builtin_macros_asm_pure_combine = the `pure` option must be combined with either builtin_macros_asm_pure_no_output = asm with the `pure` option must have at least one output -builtin_macros_asm_requires_template = requires at least a template string argument - -builtin_macros_asm_sym_no_path = expected a path for argument to `sym` - -builtin_macros_asm_underscore_input = _ cannot be used for input operands - builtin_macros_asm_unsupported_clobber_abi = `clobber_abi` cannot be used with `{$macro_name}!` -builtin_macros_asm_unsupported_operand = the `{$symbol}` operand cannot be used with `{$macro_name}!` - .label = the `{$symbol}` operand is not meaningful for global-scoped inline assembly, remove it - builtin_macros_asm_unsupported_option = the `{$symbol}` option cannot be used with `{$macro_name}!` .label = the `{$symbol}` option is not meaningful for global-scoped inline assembly .suggestion = remove this option @@ -71,7 +56,6 @@ builtin_macros_assert_requires_expression = macro requires an expression as an a builtin_macros_autodiff = autodiff must be applied to function builtin_macros_autodiff_missing_config = autodiff requires at least a name and mode -builtin_macros_autodiff_mode = unknown Mode: `{$mode}`. Use `Forward` or `Reverse` builtin_macros_autodiff_mode_activity = {$act} can not be used in {$mode} Mode builtin_macros_autodiff_not_build = this rustc version does not support autodiff builtin_macros_autodiff_number_activities = expected {$expected} activities, but found {$found} @@ -162,7 +146,10 @@ builtin_macros_expected_comma_in_list = expected token: `,` builtin_macros_expected_one_cfg_pattern = expected 1 cfg-pattern -builtin_macros_expected_register_class_or_explicit_register = expected register class or explicit register +builtin_macros_expected_other = expected operand, {$is_inline_asm -> + [false] options + *[true] clobber_abi, options + }, or additional template string builtin_macros_export_macro_rules = cannot export macro_rules! macros from a `proc-macro` crate type currently @@ -255,8 +242,6 @@ builtin_macros_no_default_variant = `#[derive(Default)]` on enum with no `#[defa .label = this enum needs a unit variant marked with `#[default]` .suggestion = make this unit variant default by placing `#[default]` on it -builtin_macros_non_abi = at least one abi must be provided as an argument to `clobber_abi` - builtin_macros_non_exhaustive_default = default variant must be exhaustive .label = declared `#[non_exhaustive]` here .help = consider a manual implementation of `Default` diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index 3e8ddb8abd4..1fb99817222 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -1,4 +1,3 @@ -use ast::token::IdentIsRaw; use lint::BuiltinLintDiag; use rustc_ast::ptr::P; use rustc_ast::tokenstream::TokenStream; @@ -7,18 +6,19 @@ use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_errors::PResult; use rustc_expand::base::*; use rustc_index::bit_set::GrowableBitSet; -use rustc_parse::exp; -use rustc_parse::parser::{ExpKeywordPair, Parser}; +use rustc_parse::parser::asm::*; use rustc_session::lint; -use rustc_span::{ErrorGuaranteed, InnerSpan, Span, Symbol, kw}; +use rustc_session::parse::feature_err; +use rustc_span::{ErrorGuaranteed, InnerSpan, Span, Symbol, sym}; use rustc_target::asm::InlineAsmArch; use smallvec::smallvec; use {rustc_ast as ast, rustc_parse_format as parse}; -use crate::errors; use crate::util::{ExprToSpannedString, expr_to_spanned_string}; +use crate::{errors, fluent_generated as fluent}; -pub struct AsmArgs { +/// Validated assembly arguments, ready for macro expansion. +struct ValidatedAsmArgs { pub templates: Vec<P<ast::Expr>>, pub operands: Vec<(ast::InlineAsmOperand, Span)>, named_args: FxIndexMap<Symbol, usize>, @@ -28,63 +28,32 @@ pub struct AsmArgs { pub options_spans: Vec<Span>, } -/// Used for better error messages when operand types are used that are not -/// supported by the current macro (e.g. `in` or `out` for `global_asm!`) -/// -/// returns -/// -/// - `Ok(true)` if the current token matches the keyword, and was expected -/// - `Ok(false)` if the current token does not match the keyword -/// - `Err(_)` if the current token matches the keyword, but was not expected -fn eat_operand_keyword<'a>( - p: &mut Parser<'a>, - exp: ExpKeywordPair, - asm_macro: AsmMacro, -) -> PResult<'a, bool> { - if matches!(asm_macro, AsmMacro::Asm) { - Ok(p.eat_keyword(exp)) - } else { - let span = p.token.span; - if p.eat_keyword_noexpect(exp.kw) { - // in gets printed as `r#in` otherwise - let symbol = if exp.kw == kw::In { "in" } else { exp.kw.as_str() }; - Err(p.dcx().create_err(errors::AsmUnsupportedOperand { - span, - symbol, - macro_name: asm_macro.macro_name(), - })) - } else { - Ok(false) - } - } -} - fn parse_args<'a>( ecx: &ExtCtxt<'a>, sp: Span, tts: TokenStream, asm_macro: AsmMacro, -) -> PResult<'a, AsmArgs> { - let mut p = ecx.new_parser_from_tts(tts); - parse_asm_args(&mut p, sp, asm_macro) +) -> PResult<'a, ValidatedAsmArgs> { + let args = parse_asm_args(&mut ecx.new_parser_from_tts(tts), sp, asm_macro)?; + validate_asm_args(ecx, asm_macro, args) } -// Primarily public for rustfmt consumption. -// Internal consumers should continue to leverage `expand_asm`/`expand__global_asm` -pub fn parse_asm_args<'a>( - p: &mut Parser<'a>, - sp: Span, +fn validate_asm_args<'a>( + ecx: &ExtCtxt<'a>, asm_macro: AsmMacro, -) -> PResult<'a, AsmArgs> { - let dcx = p.dcx(); - - if p.token == token::Eof { - return Err(dcx.create_err(errors::AsmRequiresTemplate { span: sp })); - } + args: Vec<AsmArg>, +) -> PResult<'a, ValidatedAsmArgs> { + let dcx = ecx.dcx(); + + let strip_unconfigured = rustc_expand::config::StripUnconfigured { + sess: ecx.sess, + features: Some(ecx.ecfg.features), + config_tokens: false, + lint_node_id: ecx.current_expansion.lint_node_id, + }; - let first_template = p.parse_expr()?; - let mut args = AsmArgs { - templates: vec![first_template], + let mut validated = ValidatedAsmArgs { + templates: vec![], operands: vec![], named_args: Default::default(), reg_args: Default::default(), @@ -94,178 +63,146 @@ pub fn parse_asm_args<'a>( }; let mut allow_templates = true; - while p.token != token::Eof { - if !p.eat(exp!(Comma)) { - if allow_templates { - // After a template string, we always expect *only* a comma... - return Err(dcx.create_err(errors::AsmExpectedComma { span: p.token.span })); - } else { - // ...after that delegate to `expect` to also include the other expected tokens. - return Err(p.expect(exp!(Comma)).err().unwrap()); + + for arg in args { + for attr in arg.attributes.0.iter() { + match attr.name() { + Some(sym::cfg | sym::cfg_attr) => { + if !ecx.ecfg.features.asm_cfg() { + let span = attr.span(); + feature_err(ecx.sess, sym::asm_cfg, span, fluent::builtin_macros_asm_cfg) + .emit(); + } + } + _ => { + ecx.dcx().emit_err(errors::AsmAttributeNotSupported { span: attr.span() }); + } } } - if p.token == token::Eof { - break; - } // accept trailing commas - - // Parse clobber_abi - if p.eat_keyword(exp!(ClobberAbi)) { - parse_clobber_abi(p, &mut args)?; - allow_templates = false; - continue; - } - // Parse options - if p.eat_keyword(exp!(Options)) { - parse_options(p, &mut args, asm_macro)?; - allow_templates = false; + // Skip arguments that are configured out. + if ecx.ecfg.features.asm_cfg() && strip_unconfigured.configure(arg.attributes).is_none() { continue; } - let span_start = p.token.span; - - // Parse operand names - let name = if p.token.is_ident() && p.look_ahead(1, |t| *t == token::Eq) { - let (ident, _) = p.token.ident().unwrap(); - p.bump(); - p.expect(exp!(Eq))?; - allow_templates = false; - Some(ident.name) - } else { - None - }; + match arg.kind { + AsmArgKind::Template(template) => { + // The error for the first template is delayed. + if !allow_templates { + match template.kind { + ast::ExprKind::Lit(token_lit) + if matches!( + token_lit.kind, + token::LitKind::Str | token::LitKind::StrRaw(_) + ) => {} + ast::ExprKind::MacCall(..) => {} + _ => { + let err = dcx.create_err(errors::AsmExpectedOther { + span: template.span, + is_inline_asm: matches!(asm_macro, AsmMacro::Asm), + }); + return Err(err); + } + } + } - let mut explicit_reg = false; - let op = if eat_operand_keyword(p, exp!(In), asm_macro)? { - let reg = parse_reg(p, &mut explicit_reg)?; - if p.eat_keyword(exp!(Underscore)) { - let err = dcx.create_err(errors::AsmUnderscoreInput { span: p.token.span }); - return Err(err); + validated.templates.push(template); } - let expr = p.parse_expr()?; - ast::InlineAsmOperand::In { reg, expr } - } else if eat_operand_keyword(p, exp!(Out), asm_macro)? { - let reg = parse_reg(p, &mut explicit_reg)?; - let expr = if p.eat_keyword(exp!(Underscore)) { None } else { Some(p.parse_expr()?) }; - ast::InlineAsmOperand::Out { reg, expr, late: false } - } else if eat_operand_keyword(p, exp!(Lateout), asm_macro)? { - let reg = parse_reg(p, &mut explicit_reg)?; - let expr = if p.eat_keyword(exp!(Underscore)) { None } else { Some(p.parse_expr()?) }; - ast::InlineAsmOperand::Out { reg, expr, late: true } - } else if eat_operand_keyword(p, exp!(Inout), asm_macro)? { - let reg = parse_reg(p, &mut explicit_reg)?; - if p.eat_keyword(exp!(Underscore)) { - let err = dcx.create_err(errors::AsmUnderscoreInput { span: p.token.span }); - return Err(err); - } - let expr = p.parse_expr()?; - if p.eat(exp!(FatArrow)) { - let out_expr = - if p.eat_keyword(exp!(Underscore)) { None } else { Some(p.parse_expr()?) }; - ast::InlineAsmOperand::SplitInOut { reg, in_expr: expr, out_expr, late: false } - } else { - ast::InlineAsmOperand::InOut { reg, expr, late: false } - } - } else if eat_operand_keyword(p, exp!(Inlateout), asm_macro)? { - let reg = parse_reg(p, &mut explicit_reg)?; - if p.eat_keyword(exp!(Underscore)) { - let err = dcx.create_err(errors::AsmUnderscoreInput { span: p.token.span }); - return Err(err); - } - let expr = p.parse_expr()?; - if p.eat(exp!(FatArrow)) { - let out_expr = - if p.eat_keyword(exp!(Underscore)) { None } else { Some(p.parse_expr()?) }; - ast::InlineAsmOperand::SplitInOut { reg, in_expr: expr, out_expr, late: true } - } else { - ast::InlineAsmOperand::InOut { reg, expr, late: true } - } - } else if eat_operand_keyword(p, exp!(Label), asm_macro)? { - let block = p.parse_block()?; - ast::InlineAsmOperand::Label { block } - } else if p.eat_keyword(exp!(Const)) { - let anon_const = p.parse_expr_anon_const()?; - ast::InlineAsmOperand::Const { anon_const } - } else if p.eat_keyword(exp!(Sym)) { - let expr = p.parse_expr()?; - let ast::ExprKind::Path(qself, path) = &expr.kind else { - let err = dcx.create_err(errors::AsmSymNoPath { span: expr.span }); - return Err(err); - }; - let sym = ast::InlineAsmSym { - id: ast::DUMMY_NODE_ID, - qself: qself.clone(), - path: path.clone(), - }; - ast::InlineAsmOperand::Sym { sym } - } else if allow_templates { - let template = p.parse_expr()?; - // If it can't possibly expand to a string, provide diagnostics here to include other - // things it could have been. - match template.kind { - ast::ExprKind::Lit(token_lit) - if matches!( - token_lit.kind, - token::LitKind::Str | token::LitKind::StrRaw(_) - ) => {} - ast::ExprKind::MacCall(..) => {} - _ => { - let err = dcx.create_err(errors::AsmExpectedOther { - span: template.span, - is_inline_asm: matches!(asm_macro, AsmMacro::Asm), - }); - return Err(err); + AsmArgKind::Operand(name, op) => { + allow_templates = false; + + let explicit_reg = matches!(op.reg(), Some(ast::InlineAsmRegOrRegClass::Reg(_))); + let span = arg.span; + let slot = validated.operands.len(); + validated.operands.push((op, span)); + + // Validate the order of named, positional & explicit register operands and + // clobber_abi/options. We do this at the end once we have the full span + // of the argument available. + + if explicit_reg { + if name.is_some() { + dcx.emit_err(errors::AsmExplicitRegisterName { span }); + } + validated.reg_args.insert(slot); + } else if let Some(name) = name { + if let Some(&prev) = validated.named_args.get(&name) { + dcx.emit_err(errors::AsmDuplicateArg { + span, + name, + prev: validated.operands[prev].1, + }); + continue; + } + validated.named_args.insert(name, slot); + } else if !validated.named_args.is_empty() || !validated.reg_args.is_empty() { + let named = + validated.named_args.values().map(|p| validated.operands[*p].1).collect(); + let explicit = + validated.reg_args.iter().map(|p| validated.operands[p].1).collect(); + + dcx.emit_err(errors::AsmPositionalAfter { span, named, explicit }); } } - args.templates.push(template); - continue; - } else { - p.unexpected_any()? - }; + AsmArgKind::Options(new_options) => { + allow_templates = false; - allow_templates = false; - let span = span_start.to(p.prev_token.span); - let slot = args.operands.len(); - args.operands.push((op, span)); - - // Validate the order of named, positional & explicit register operands and - // clobber_abi/options. We do this at the end once we have the full span - // of the argument available. - if explicit_reg { - if name.is_some() { - dcx.emit_err(errors::AsmExplicitRegisterName { span }); + for asm_option in new_options { + let AsmOption { span, symbol, span_with_comma, options } = asm_option; + + if !asm_macro.is_supported_option(options) { + // Tool-only output. + dcx.emit_err(errors::AsmUnsupportedOption { + span, + symbol, + span_with_comma, + macro_name: asm_macro.macro_name(), + }); + } else if validated.options.contains(options) { + // Tool-only output. + dcx.emit_err(errors::AsmOptAlreadyprovided { + span, + symbol, + span_with_comma, + }); + } else { + validated.options |= asm_option.options; + } + } + + validated.options_spans.push(arg.span); } - args.reg_args.insert(slot); - } else if let Some(name) = name { - if let Some(&prev) = args.named_args.get(&name) { - dcx.emit_err(errors::AsmDuplicateArg { span, name, prev: args.operands[prev].1 }); - continue; + AsmArgKind::ClobberAbi(new_abis) => { + allow_templates = false; + + match &new_abis[..] { + // This should have errored above during parsing. + [] => unreachable!(), + [(abi, _span)] => validated.clobber_abis.push((*abi, arg.span)), + _ => validated.clobber_abis.extend(new_abis), + } } - args.named_args.insert(name, slot); - } else if !args.named_args.is_empty() || !args.reg_args.is_empty() { - let named = args.named_args.values().map(|p| args.operands[*p].1).collect(); - let explicit = args.reg_args.iter().map(|p| args.operands[p].1).collect(); - - dcx.emit_err(errors::AsmPositionalAfter { span, named, explicit }); } } - if args.options.contains(ast::InlineAsmOptions::NOMEM) - && args.options.contains(ast::InlineAsmOptions::READONLY) + if validated.options.contains(ast::InlineAsmOptions::NOMEM) + && validated.options.contains(ast::InlineAsmOptions::READONLY) { - let spans = args.options_spans.clone(); + let spans = validated.options_spans.clone(); dcx.emit_err(errors::AsmMutuallyExclusive { spans, opt1: "nomem", opt2: "readonly" }); } - if args.options.contains(ast::InlineAsmOptions::PURE) - && args.options.contains(ast::InlineAsmOptions::NORETURN) + if validated.options.contains(ast::InlineAsmOptions::PURE) + && validated.options.contains(ast::InlineAsmOptions::NORETURN) { - let spans = args.options_spans.clone(); + let spans = validated.options_spans.clone(); dcx.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) + if validated.options.contains(ast::InlineAsmOptions::PURE) + && !validated + .options + .intersects(ast::InlineAsmOptions::NOMEM | ast::InlineAsmOptions::READONLY) { - let spans = args.options_spans.clone(); + let spans = validated.options_spans.clone(); dcx.emit_err(errors::AsmPureCombine { spans }); } @@ -273,7 +210,7 @@ pub fn parse_asm_args<'a>( let mut outputs_sp = vec![]; let mut regclass_outputs = vec![]; let mut labels_sp = vec![]; - for (op, op_sp) in &args.operands { + for (op, op_sp) in &validated.operands { match op { ast::InlineAsmOperand::Out { reg, expr, .. } | ast::InlineAsmOperand::SplitInOut { reg, out_expr: expr, .. } => { @@ -296,10 +233,10 @@ pub fn parse_asm_args<'a>( _ => {} } } - if args.options.contains(ast::InlineAsmOptions::PURE) && !have_real_output { - dcx.emit_err(errors::AsmPureNoOutput { spans: args.options_spans.clone() }); + if validated.options.contains(ast::InlineAsmOptions::PURE) && !have_real_output { + dcx.emit_err(errors::AsmPureNoOutput { spans: validated.options_spans.clone() }); } - if args.options.contains(ast::InlineAsmOptions::NORETURN) + if validated.options.contains(ast::InlineAsmOptions::NORETURN) && !outputs_sp.is_empty() && labels_sp.is_empty() { @@ -307,15 +244,15 @@ pub fn parse_asm_args<'a>( // Bail out now since this is likely to confuse MIR return Err(err); } - if args.options.contains(ast::InlineAsmOptions::MAY_UNWIND) && !labels_sp.is_empty() { + if validated.options.contains(ast::InlineAsmOptions::MAY_UNWIND) && !labels_sp.is_empty() { dcx.emit_err(errors::AsmMayUnwind { labels_sp }); } - if !args.clobber_abis.is_empty() { + if !validated.clobber_abis.is_empty() { match asm_macro { AsmMacro::GlobalAsm | AsmMacro::NakedAsm => { let err = dcx.create_err(errors::AsmUnsupportedClobberAbi { - spans: args.clobber_abis.iter().map(|(_, span)| *span).collect(), + spans: validated.clobber_abis.iter().map(|(_, span)| *span).collect(), macro_name: asm_macro.macro_name(), }); @@ -326,184 +263,20 @@ pub fn parse_asm_args<'a>( if !regclass_outputs.is_empty() { dcx.emit_err(errors::AsmClobberNoReg { spans: regclass_outputs, - clobbers: args.clobber_abis.iter().map(|(_, span)| *span).collect(), + clobbers: validated.clobber_abis.iter().map(|(_, span)| *span).collect(), }); } } } } - Ok(args) -} - -/// Report a duplicate option error. -/// -/// This function must be called immediately after the option token is parsed. -/// Otherwise, the suggestion will be incorrect. -fn err_duplicate_option(p: &Parser<'_>, symbol: Symbol, span: Span) { - // Tool-only output - let full_span = if p.token == token::Comma { span.to(p.token.span) } else { span }; - p.dcx().emit_err(errors::AsmOptAlreadyprovided { span, symbol, full_span }); -} - -/// Report an invalid option error. -/// -/// This function must be called immediately after the option token is parsed. -/// Otherwise, the suggestion will be incorrect. -fn err_unsupported_option(p: &Parser<'_>, asm_macro: AsmMacro, symbol: Symbol, span: Span) { - // Tool-only output - let full_span = if p.token == token::Comma { span.to(p.token.span) } else { span }; - p.dcx().emit_err(errors::AsmUnsupportedOption { - span, - symbol, - full_span, - macro_name: asm_macro.macro_name(), - }); -} - -/// Try to set the provided option in the provided `AsmArgs`. -/// If it is already set, report a duplicate option error. -/// -/// This function must be called immediately after the option token is parsed. -/// Otherwise, the error will not point to the correct spot. -fn try_set_option<'a>( - p: &Parser<'a>, - args: &mut AsmArgs, - asm_macro: AsmMacro, - symbol: Symbol, - option: ast::InlineAsmOptions, -) { - if !asm_macro.is_supported_option(option) { - err_unsupported_option(p, asm_macro, symbol, p.prev_token.span); - } else if args.options.contains(option) { - err_duplicate_option(p, symbol, p.prev_token.span); - } else { - args.options |= option; - } -} - -fn parse_options<'a>( - p: &mut Parser<'a>, - args: &mut AsmArgs, - asm_macro: AsmMacro, -) -> PResult<'a, ()> { - let span_start = p.prev_token.span; - - p.expect(exp!(OpenParen))?; - - while !p.eat(exp!(CloseParen)) { - const OPTIONS: [(ExpKeywordPair, ast::InlineAsmOptions); ast::InlineAsmOptions::COUNT] = [ - (exp!(Pure), ast::InlineAsmOptions::PURE), - (exp!(Nomem), ast::InlineAsmOptions::NOMEM), - (exp!(Readonly), ast::InlineAsmOptions::READONLY), - (exp!(PreservesFlags), ast::InlineAsmOptions::PRESERVES_FLAGS), - (exp!(Noreturn), ast::InlineAsmOptions::NORETURN), - (exp!(Nostack), ast::InlineAsmOptions::NOSTACK), - (exp!(MayUnwind), ast::InlineAsmOptions::MAY_UNWIND), - (exp!(AttSyntax), ast::InlineAsmOptions::ATT_SYNTAX), - (exp!(Raw), ast::InlineAsmOptions::RAW), - ]; - - 'blk: { - for (exp, option) in OPTIONS { - let kw_matched = if asm_macro.is_supported_option(option) { - p.eat_keyword(exp) - } else { - p.eat_keyword_noexpect(exp.kw) - }; - - if kw_matched { - try_set_option(p, args, asm_macro, exp.kw, option); - break 'blk; - } - } - - return p.unexpected(); - } - - // Allow trailing commas - if p.eat(exp!(CloseParen)) { - break; - } - p.expect(exp!(Comma))?; - } - - let new_span = span_start.to(p.prev_token.span); - args.options_spans.push(new_span); - - Ok(()) -} - -fn parse_clobber_abi<'a>(p: &mut Parser<'a>, args: &mut AsmArgs) -> PResult<'a, ()> { - let span_start = p.prev_token.span; - - p.expect(exp!(OpenParen))?; - - if p.eat(exp!(CloseParen)) { - return Err(p.dcx().create_err(errors::NonABI { span: p.token.span })); - } - - let mut new_abis = Vec::new(); - while !p.eat(exp!(CloseParen)) { - match p.parse_str_lit() { - Ok(str_lit) => { - new_abis.push((str_lit.symbol_unescaped, str_lit.span)); - } - Err(opt_lit) => { - let span = opt_lit.map_or(p.token.span, |lit| lit.span); - return Err(p.dcx().create_err(errors::AsmExpectedStringLiteral { span })); - } - }; - - // Allow trailing commas - if p.eat(exp!(CloseParen)) { - break; - } - p.expect(exp!(Comma))?; - } - - let full_span = span_start.to(p.prev_token.span); - - match &new_abis[..] { - // should have errored above during parsing - [] => unreachable!(), - [(abi, _span)] => args.clobber_abis.push((*abi, full_span)), - abis => { - for (abi, span) in abis { - args.clobber_abis.push((*abi, *span)); - } - } - } - - Ok(()) -} - -fn parse_reg<'a>( - p: &mut Parser<'a>, - explicit_reg: &mut bool, -) -> PResult<'a, ast::InlineAsmRegOrRegClass> { - p.expect(exp!(OpenParen))?; - let result = match p.token.uninterpolate().kind { - token::Ident(name, IdentIsRaw::No) => ast::InlineAsmRegOrRegClass::RegClass(name), - token::Literal(token::Lit { kind: token::LitKind::Str, symbol, suffix: _ }) => { - *explicit_reg = true; - ast::InlineAsmRegOrRegClass::Reg(symbol) - } - _ => { - return Err(p.dcx().create_err(errors::ExpectedRegisterClassOrExplicitRegister { - span: p.token.span, - })); - } - }; - p.bump(); - p.expect(exp!(CloseParen))?; - Ok(result) + Ok(validated) } fn expand_preparsed_asm( ecx: &mut ExtCtxt<'_>, asm_macro: AsmMacro, - args: AsmArgs, + args: ValidatedAsmArgs, ) -> ExpandResult<Result<ast::InlineAsm, ErrorGuaranteed>, ()> { let mut template = vec![]; // Register operands are implicitly used since they are not allowed to be diff --git a/compiler/rustc_builtin_macros/src/autodiff.rs b/compiler/rustc_builtin_macros/src/autodiff.rs index 8c5c20c7af4..dc3bb8ab52a 100644 --- a/compiler/rustc_builtin_macros/src/autodiff.rs +++ b/compiler/rustc_builtin_macros/src/autodiff.rs @@ -73,10 +73,10 @@ mod llvm_enzyme { } // Get information about the function the macro is applied to - fn extract_item_info(iitem: &P<ast::Item>) -> Option<(Visibility, FnSig, Ident)> { + fn extract_item_info(iitem: &P<ast::Item>) -> Option<(Visibility, FnSig, Ident, Generics)> { match &iitem.kind { - ItemKind::Fn(box ast::Fn { sig, ident, .. }) => { - Some((iitem.vis.clone(), sig.clone(), ident.clone())) + ItemKind::Fn(box ast::Fn { sig, ident, generics, .. }) => { + Some((iitem.vis.clone(), sig.clone(), ident.clone(), generics.clone())) } _ => None, } @@ -86,27 +86,23 @@ mod llvm_enzyme { ecx: &mut ExtCtxt<'_>, meta_item: &ThinVec<MetaItemInner>, has_ret: bool, + mode: DiffMode, ) -> AutoDiffAttrs { let dcx = ecx.sess.dcx(); - let mode = name(&meta_item[1]); - let Ok(mode) = DiffMode::from_str(&mode) else { - dcx.emit_err(errors::AutoDiffInvalidMode { span: meta_item[1].span(), mode }); - return AutoDiffAttrs::error(); - }; // Now we check, whether the user wants autodiff in batch/vector mode, or scalar mode. // If he doesn't specify an integer (=width), we default to scalar mode, thus width=1. - let mut first_activity = 2; + let mut first_activity = 1; - let width = if let [_, _, x, ..] = &meta_item[..] + let width = if let [_, x, ..] = &meta_item[..] && let Some(x) = width(x) { - first_activity = 3; + first_activity = 2; match x.try_into() { Ok(x) => x, Err(_) => { dcx.emit_err(errors::AutoDiffInvalidWidth { - span: meta_item[2].span(), + span: meta_item[1].span(), width: x, }); return AutoDiffAttrs::error(); @@ -165,6 +161,24 @@ mod llvm_enzyme { ts.push(TokenTree::Token(comma.clone(), Spacing::Alone)); } + pub(crate) fn expand_forward( + ecx: &mut ExtCtxt<'_>, + expand_span: Span, + meta_item: &ast::MetaItem, + item: Annotatable, + ) -> Vec<Annotatable> { + expand_with_mode(ecx, expand_span, meta_item, item, DiffMode::Forward) + } + + pub(crate) fn expand_reverse( + ecx: &mut ExtCtxt<'_>, + expand_span: Span, + meta_item: &ast::MetaItem, + item: Annotatable, + ) -> Vec<Annotatable> { + expand_with_mode(ecx, expand_span, meta_item, item, DiffMode::Reverse) + } + /// We expand the autodiff macro to generate a new placeholder function which passes /// type-checking and can be called by users. The function body of the placeholder function will /// later be replaced on LLVM-IR level, so the design of the body is less important and for now @@ -198,11 +212,12 @@ mod llvm_enzyme { /// ``` /// FIXME(ZuseZ4): Once autodiff is enabled by default, make this a doc comment which is checked /// in CI. - pub(crate) fn expand( + pub(crate) fn expand_with_mode( ecx: &mut ExtCtxt<'_>, expand_span: Span, meta_item: &ast::MetaItem, mut item: Annotatable, + mode: DiffMode, ) -> Vec<Annotatable> { if cfg!(not(llvm_enzyme)) { ecx.sess.dcx().emit_err(errors::AutoDiffSupportNotBuild { span: meta_item.span }); @@ -210,16 +225,18 @@ mod llvm_enzyme { } let dcx = ecx.sess.dcx(); - // first get information about the annotable item: - let Some((vis, sig, primal)) = (match &item { + // first get information about the annotable item: visibility, signature, name and generic + // parameters. + // these will be used to generate the differentiated version of the function + let Some((vis, sig, primal, generics)) = (match &item { Annotatable::Item(iitem) => extract_item_info(iitem), Annotatable::Stmt(stmt) => match &stmt.kind { ast::StmtKind::Item(iitem) => extract_item_info(iitem), _ => None, }, Annotatable::AssocItem(assoc_item, Impl { .. }) => match &assoc_item.kind { - ast::AssocItemKind::Fn(box ast::Fn { sig, ident, .. }) => { - Some((assoc_item.vis.clone(), sig.clone(), ident.clone())) + ast::AssocItemKind::Fn(box ast::Fn { sig, ident, generics, .. }) => { + Some((assoc_item.vis.clone(), sig.clone(), ident.clone(), generics.clone())) } _ => None, }, @@ -243,29 +260,41 @@ mod llvm_enzyme { // create TokenStream from vec elemtents: // meta_item doesn't have a .tokens field let mut ts: Vec<TokenTree> = vec![]; - if meta_item_vec.len() < 2 { - // At the bare minimum, we need a fnc name and a mode, even for a dummy function with no - // input and output args. + if meta_item_vec.len() < 1 { + // At the bare minimum, we need a fnc name. dcx.emit_err(errors::AutoDiffMissingConfig { span: item.span() }); return vec![item]; } - meta_item_inner_to_ts(&meta_item_vec[1], &mut ts); + let mode_symbol = match mode { + DiffMode::Forward => sym::Forward, + DiffMode::Reverse => sym::Reverse, + _ => unreachable!("Unsupported mode: {:?}", mode), + }; + + // Insert mode token + let mode_token = Token::new(TokenKind::Ident(mode_symbol, false.into()), Span::default()); + ts.insert(0, TokenTree::Token(mode_token, Spacing::Joint)); + ts.insert( + 1, + TokenTree::Token(Token::new(TokenKind::Comma, Span::default()), Spacing::Alone), + ); // Now, if the user gave a width (vector aka batch-mode ad), then we copy it. // If it is not given, we default to 1 (scalar mode). let start_position; let kind: LitKind = LitKind::Integer; let symbol; - if meta_item_vec.len() >= 3 - && let Some(width) = width(&meta_item_vec[2]) + if meta_item_vec.len() >= 2 + && let Some(width) = width(&meta_item_vec[1]) { - start_position = 3; + start_position = 2; symbol = Symbol::intern(&width.to_string()); } else { - start_position = 2; + start_position = 1; symbol = sym::integer(1); } + let l: Lit = Lit { kind, symbol, suffix: None }; let t = Token::new(TokenKind::Literal(l), Span::default()); let comma = Token::new(TokenKind::Comma, Span::default()); @@ -287,7 +316,7 @@ mod llvm_enzyme { ts.pop(); let ts: TokenStream = TokenStream::from_iter(ts); - let x: AutoDiffAttrs = from_ast(ecx, &meta_item_vec, has_ret); + let x: AutoDiffAttrs = from_ast(ecx, &meta_item_vec, has_ret, mode); if !x.is_active() { // We encountered an error, so we return the original item. // This allows us to potentially parse other attributes. @@ -303,6 +332,7 @@ mod llvm_enzyme { let (d_sig, new_args, idents, errored) = gen_enzyme_decl(ecx, &sig, &x, span); let d_body = gen_enzyme_body( ecx, &x, n_active, &sig, &d_sig, primal, &new_args, span, sig_span, idents, errored, + &generics, ); // The first element of it is the name of the function to be generated @@ -310,7 +340,7 @@ mod llvm_enzyme { defaultness: ast::Defaultness::Final, sig: d_sig, ident: first_ident(&meta_item_vec[0]), - generics: Generics::default(), + generics, contract: None, body: Some(d_body), define_opaque: None, @@ -475,6 +505,7 @@ mod llvm_enzyme { new_decl_span: Span, idents: &[Ident], errored: bool, + generics: &Generics, ) -> (P<ast::Block>, P<ast::Expr>, P<ast::Expr>, P<ast::Expr>) { let blackbox_path = ecx.std_path(&[sym::hint, sym::black_box]); let noop = ast::InlineAsm { @@ -497,7 +528,7 @@ mod llvm_enzyme { }; let unsf_expr = ecx.expr_block(P(unsf_block)); let blackbox_call_expr = ecx.expr_path(ecx.path(span, blackbox_path)); - let primal_call = gen_primal_call(ecx, span, primal, idents); + let primal_call = gen_primal_call(ecx, span, primal, idents, generics); let black_box_primal_call = ecx.expr_call( new_decl_span, blackbox_call_expr.clone(), @@ -546,6 +577,7 @@ mod llvm_enzyme { sig_span: Span, idents: Vec<Ident>, errored: bool, + generics: &Generics, ) -> P<ast::Block> { let new_decl_span = d_sig.span; @@ -566,6 +598,7 @@ mod llvm_enzyme { new_decl_span, &idents, errored, + generics, ); if !has_ret(&d_sig.decl.output) { @@ -608,7 +641,6 @@ mod llvm_enzyme { panic!("Did not expect Default ret ty: {:?}", span); } }; - if x.mode.is_fwd() { // Fwd mode is easy. If the return activity is Const, we support arbitrary types. // Otherwise, we only support a scalar, a pair of scalars, or an array of scalars. @@ -668,8 +700,10 @@ mod llvm_enzyme { span: Span, primal: Ident, idents: &[Ident], + generics: &Generics, ) -> P<ast::Expr> { let has_self = idents.len() > 0 && idents[0].name == kw::SelfLower; + if has_self { let args: ThinVec<_> = idents[1..].iter().map(|arg| ecx.expr_path(ecx.path_ident(span, *arg))).collect(); @@ -678,7 +712,51 @@ mod llvm_enzyme { } else { let args: ThinVec<_> = idents.iter().map(|arg| ecx.expr_path(ecx.path_ident(span, *arg))).collect(); - let primal_call_expr = ecx.expr_path(ecx.path_ident(span, primal)); + let mut primal_path = ecx.path_ident(span, primal); + + let is_generic = !generics.params.is_empty(); + + match (is_generic, primal_path.segments.last_mut()) { + (true, Some(function_path)) => { + let primal_generic_types = generics + .params + .iter() + .filter(|param| matches!(param.kind, ast::GenericParamKind::Type { .. })); + + let generated_generic_types = primal_generic_types + .map(|type_param| { + let generic_param = TyKind::Path( + None, + ast::Path { + span, + segments: thin_vec![ast::PathSegment { + ident: type_param.ident, + args: None, + id: ast::DUMMY_NODE_ID, + }], + tokens: None, + }, + ); + + ast::AngleBracketedArg::Arg(ast::GenericArg::Type(P(ast::Ty { + id: type_param.id, + span, + kind: generic_param, + tokens: None, + }))) + }) + .collect(); + + function_path.args = + Some(P(ast::GenericArgs::AngleBracketed(ast::AngleBracketedArgs { + span, + args: generated_generic_types, + }))); + } + _ => {} + } + + let primal_call_expr = ecx.expr_path(primal_path); ecx.expr_call(span, primal_call_expr, args) } } @@ -966,4 +1044,4 @@ mod llvm_enzyme { } } -pub(crate) use llvm_enzyme::expand; +pub(crate) use llvm_enzyme::{expand_forward, expand_reverse}; diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs index 44cf215c662..69f8c273797 100644 --- a/compiler/rustc_builtin_macros/src/deriving/clone.rs +++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs @@ -34,8 +34,8 @@ pub(crate) fn expand_deriving_clone( let is_simple; match item { Annotatable::Item(annitem) => match &annitem.kind { - ItemKind::Struct(_, _, Generics { params, .. }) - | ItemKind::Enum(_, _, Generics { params, .. }) => { + ItemKind::Struct(_, Generics { params, .. }, _) + | ItemKind::Enum(_, Generics { params, .. }, _) => { let container_id = cx.current_expansion.id.expn_data().parent.expect_local(); let has_derive_copy = cx.resolver.has_derive_copy(container_id); if has_derive_copy diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs index aa01da3151e..0a076dd670b 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs @@ -21,7 +21,7 @@ pub(crate) fn expand_deriving_partial_ord( // Order in which to perform matching let discr_then_data = if let Annotatable::Item(item) = item - && let ItemKind::Enum(_, def, _) = &item.kind + && let ItemKind::Enum(_, _, def) = &item.kind { let dataful: Vec<bool> = def.variants.iter().map(|v| !v.data.fields().is_empty()).collect(); match dataful.iter().filter(|&&b| b).count() { diff --git a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs index 446d8afeedd..0794192621a 100644 --- a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs +++ b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs @@ -30,7 +30,7 @@ pub(crate) fn expand_deriving_coerce_pointee( item.visit_with(&mut DetectNonGenericPointeeAttr { cx }); let (name_ident, generics) = if let Annotatable::Item(aitem) = item - && let ItemKind::Struct(ident, struct_data, g) = &aitem.kind + && let ItemKind::Struct(ident, g, struct_data) = &aitem.kind { if !matches!( struct_data, diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index d9aac54ee73..f1bef526c10 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -185,7 +185,8 @@ use rustc_ast::{ self as ast, AnonConst, BindingMode, ByRef, EnumDef, Expr, GenericArg, GenericParamKind, Generics, Mutability, PatKind, VariantData, }; -use rustc_attr_parsing::{AttributeKind, AttributeParser, ReprPacked}; +use rustc_attr_data_structures::{AttributeKind, ReprPacked}; +use rustc_attr_parsing::AttributeParser; use rustc_expand::base::{Annotatable, ExtCtxt}; use rustc_hir::Attribute; use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym}; @@ -487,7 +488,7 @@ impl<'a> TraitDef<'a> { ); let newitem = match &item.kind { - ast::ItemKind::Struct(ident, struct_def, generics) => self.expand_struct_def( + ast::ItemKind::Struct(ident, generics, struct_def) => self.expand_struct_def( cx, struct_def, *ident, @@ -495,7 +496,7 @@ impl<'a> TraitDef<'a> { from_scratch, is_packed, ), - ast::ItemKind::Enum(ident, enum_def, generics) => { + ast::ItemKind::Enum(ident, generics, enum_def) => { // We ignore `is_packed` here, because `repr(packed)` // enums cause an error later on. // @@ -503,7 +504,7 @@ impl<'a> TraitDef<'a> { // downstream in blatantly illegal code, so it is fine. self.expand_enum_def(cx, enum_def, *ident, generics, from_scratch) } - ast::ItemKind::Union(ident, struct_def, generics) => { + ast::ItemKind::Union(ident, generics, struct_def) => { if self.supports_unions { self.expand_struct_def( cx, diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index d14ad8f4014..3a2e96a5e5a 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -110,13 +110,6 @@ pub(crate) struct ProcMacro { } #[derive(Diagnostic)] -#[diag(builtin_macros_non_abi)] -pub(crate) struct NonABI { - #[primary_span] - pub(crate) span: Span, -} - -#[derive(Diagnostic)] #[diag(builtin_macros_trace_macros)] pub(crate) struct TraceMacros { #[primary_span] @@ -188,14 +181,6 @@ mod autodiff { } #[derive(Diagnostic)] - #[diag(builtin_macros_autodiff_mode)] - pub(crate) struct AutoDiffInvalidMode { - #[primary_span] - pub(crate) span: Span, - pub(crate) mode: String, - } - - #[derive(Diagnostic)] #[diag(builtin_macros_autodiff_width)] pub(crate) struct AutoDiffInvalidWidth { #[primary_span] @@ -789,52 +774,13 @@ pub(crate) struct AsmModifierInvalid { } #[derive(Diagnostic)] -#[diag(builtin_macros_asm_requires_template)] -pub(crate) struct AsmRequiresTemplate { - #[primary_span] - pub(crate) span: Span, -} - -#[derive(Diagnostic)] -#[diag(builtin_macros_asm_expected_comma)] -pub(crate) struct AsmExpectedComma { - #[primary_span] - #[label] - pub(crate) span: Span, -} - -#[derive(Diagnostic)] -#[diag(builtin_macros_asm_expected_string_literal)] -pub(crate) struct AsmExpectedStringLiteral { +#[diag(builtin_macros_asm_attribute_not_supported)] +pub(crate) struct AsmAttributeNotSupported { #[primary_span] - #[label] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_asm_underscore_input)] -pub(crate) struct AsmUnderscoreInput { - #[primary_span] - pub(crate) span: Span, -} - -#[derive(Diagnostic)] -#[diag(builtin_macros_asm_sym_no_path)] -pub(crate) struct AsmSymNoPath { - #[primary_span] - pub(crate) span: Span, -} - -#[derive(Diagnostic)] -#[diag(builtin_macros_asm_expected_other)] -pub(crate) struct AsmExpectedOther { - #[primary_span] - #[label(builtin_macros_asm_expected_other)] - pub(crate) span: Span, - pub(crate) is_inline_asm: bool, -} - -#[derive(Diagnostic)] #[diag(builtin_macros_asm_duplicate_arg)] pub(crate) struct AsmDuplicateArg { #[primary_span] @@ -910,7 +856,7 @@ pub(crate) struct AsmOptAlreadyprovided { pub(crate) span: Span, pub(crate) symbol: Symbol, #[suggestion(code = "", applicability = "machine-applicable", style = "tool-only")] - pub(crate) full_span: Span, + pub(crate) span_with_comma: Span, } #[derive(Diagnostic)] @@ -921,17 +867,7 @@ pub(crate) struct AsmUnsupportedOption { pub(crate) span: Span, pub(crate) symbol: Symbol, #[suggestion(code = "", applicability = "machine-applicable", style = "tool-only")] - pub(crate) full_span: Span, - pub(crate) macro_name: &'static str, -} - -#[derive(Diagnostic)] -#[diag(builtin_macros_asm_unsupported_operand)] -pub(crate) struct AsmUnsupportedOperand<'a> { - #[primary_span] - #[label] - pub(crate) span: Span, - pub(crate) symbol: &'a str, + pub(crate) span_with_comma: Span, pub(crate) macro_name: &'static str, } @@ -958,13 +894,6 @@ pub(crate) struct TestRunnerNargs { } #[derive(Diagnostic)] -#[diag(builtin_macros_expected_register_class_or_explicit_register)] -pub(crate) struct ExpectedRegisterClassOrExplicitRegister { - #[primary_span] - pub(crate) span: Span, -} - -#[derive(Diagnostic)] #[diag(builtin_macros_expected_comma_in_list)] pub(crate) struct ExpectedCommaInList { #[primary_span] @@ -1027,3 +956,12 @@ pub(crate) struct NonGenericPointee { #[primary_span] pub span: Span, } + +#[derive(Diagnostic)] +#[diag(builtin_macros_expected_other)] +pub(crate) struct AsmExpectedOther { + #[primary_span] + #[label(builtin_macros_expected_other)] + pub(crate) span: Span, + pub(crate) is_inline_asm: bool, +} diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index 9cd4d17059a..667d90429f2 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -5,10 +5,10 @@ #![allow(internal_features)] #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] +#![cfg_attr(not(bootstrap), feature(autodiff))] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(assert_matches)] -#![feature(autodiff)] #![feature(box_patterns)] #![feature(decl_macro)] #![feature(if_let_guard)] @@ -20,8 +20,6 @@ #![recursion_limit = "256"] // tidy-alphabetical-end -extern crate proc_macro; - use std::sync::Arc; use rustc_expand::base::{MacroExpanderFn, ResolverExpand, SyntaxExtensionKind}; @@ -112,7 +110,8 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) { register_attr! { alloc_error_handler: alloc_error_handler::expand, - autodiff: autodiff::expand, + autodiff_forward: autodiff::expand_forward, + autodiff_reverse: autodiff::expand_reverse, bench: test::expand_bench, cfg_accessible: cfg_accessible::Expander, cfg_eval: cfg_eval::expand, @@ -139,7 +138,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) { CoercePointee: coerce_pointee::expand_deriving_coerce_pointee, } - let client = proc_macro::bridge::client::Client::expand1(proc_macro::quote); + let client = rustc_proc_macro::bridge::client::Client::expand1(rustc_proc_macro::quote); register(sym::quote, SyntaxExtensionKind::Bang(Arc::new(BangProcMacro { client }))); let requires = SyntaxExtensionKind::Attr(Arc::new(contracts::ExpandRequires)); register(sym::contracts_requires, requires); diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs index 56a67b0534d..0bc313cbdac 100644 --- a/compiler/rustc_builtin_macros/src/test_harness.rs +++ b/compiler/rustc_builtin_macros/src/test_harness.rs @@ -128,9 +128,7 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> { c.items.push(mk_main(&mut self.cx)); } - fn visit_item(&mut self, item: &mut P<ast::Item>) { - let item = &mut **item; - + fn visit_item(&mut self, item: &mut ast::Item) { if let Some(name) = get_test_name(&item) { debug!("this is a test item"); @@ -193,7 +191,7 @@ struct EntryPointCleaner<'a> { } impl<'a> MutVisitor for EntryPointCleaner<'a> { - fn visit_item(&mut self, item: &mut P<ast::Item>) { + fn visit_item(&mut self, item: &mut ast::Item) { self.depth += 1; ast::mut_visit::walk_item(self, item); self.depth -= 1; |
