diff options
Diffstat (limited to 'compiler/rustc_builtin_macros/src/derive.rs')
-rw-r--r-- | compiler/rustc_builtin_macros/src/derive.rs | 59 |
1 files changed, 31 insertions, 28 deletions
diff --git a/compiler/rustc_builtin_macros/src/derive.rs b/compiler/rustc_builtin_macros/src/derive.rs index e0fb7affb..fa5a45730 100644 --- a/compiler/rustc_builtin_macros/src/derive.rs +++ b/compiler/rustc_builtin_macros/src/derive.rs @@ -1,7 +1,7 @@ use crate::cfg_eval::cfg_eval; use rustc_ast as ast; -use rustc_ast::{attr, token, GenericParamKind, ItemKind, MetaItemKind, NestedMetaItem, StmtKind}; +use rustc_ast::{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; @@ -10,7 +10,7 @@ use rustc_session::Session; use rustc_span::symbol::{sym, Ident}; use rustc_span::Span; -pub(crate) struct Expander; +pub(crate) struct Expander(pub bool); impl MultiItemModifier for Expander { fn expand( @@ -19,6 +19,7 @@ impl MultiItemModifier for Expander { span: Span, meta_item: &ast::MetaItem, item: Annotatable, + _: bool, ) -> ExpandResult<Vec<Annotatable>, Annotatable> { let sess = ecx.sess; if report_bad_target(sess, &item, span) { @@ -32,46 +33,48 @@ impl MultiItemModifier for Expander { ecx.resolver.resolve_derives(ecx.current_expansion.id, ecx.force_mode, &|| { let template = AttributeTemplate { list: Some("Trait1, Trait2, ..."), ..Default::default() }; - let attr = - attr::mk_attr_outer(&sess.parse_sess.attr_id_generator, meta_item.clone()); - validate_attr::check_builtin_attribute( + validate_attr::check_builtin_meta_item( &sess.parse_sess, - &attr, + &meta_item, + ast::AttrStyle::Outer, sym::derive, template, ); - let mut resolutions: Vec<_> = attr - .meta_item_list() - .unwrap_or_default() - .into_iter() - .filter_map(|nested_meta| match nested_meta { - NestedMetaItem::MetaItem(meta) => Some(meta), - NestedMetaItem::Literal(lit) => { - // Reject `#[derive("Debug")]`. - report_unexpected_literal(sess, &lit); - None - } - }) - .map(|meta| { - // Reject `#[derive(Debug = "value", Debug(abc))]`, but recover the paths. - report_path_args(sess, &meta); - meta.path - }) - .map(|path| (path, dummy_annotatable(), None)) - .collect(); + let mut resolutions = match &meta_item.kind { + MetaItemKind::List(list) => { + list.iter() + .filter_map(|nested_meta| match nested_meta { + NestedMetaItem::MetaItem(meta) => Some(meta), + NestedMetaItem::Lit(lit) => { + // Reject `#[derive("Debug")]`. + report_unexpected_meta_item_lit(sess, &lit); + None + } + }) + .map(|meta| { + // Reject `#[derive(Debug = "value", Debug(abc))]`, but recover the + // paths. + report_path_args(sess, &meta); + meta.path.clone() + }) + .map(|path| (path, dummy_annotatable(), None, self.0)) + .collect() + } + _ => vec![], + }; // Do not configure or clone items unless necessary. match &mut resolutions[..] { [] => {} - [(_, first_item, _), others @ ..] => { + [(_, first_item, ..), others @ ..] => { *first_item = cfg_eval( sess, features, item.clone(), ecx.current_expansion.lint_node_id, ); - for (_, item, _) in others { + for (_, item, _, _) in others { *item = first_item.clone(); } } @@ -126,7 +129,7 @@ fn report_bad_target(sess: &Session, item: &Annotatable, span: Span) -> bool { bad_target } -fn report_unexpected_literal(sess: &Session, lit: &ast::Lit) { +fn report_unexpected_meta_item_lit(sess: &Session, lit: &ast::MetaItemLit) { let help_msg = match lit.token_lit.kind { token::Str if rustc_lexer::is_ident(lit.token_lit.symbol.as_str()) => { format!("try using `#[derive({})]`", lit.token_lit.symbol) |