From edb925a91f4fafb9056d181dd620937992ad6c1b Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 6 Jun 2019 23:21:44 +0300 Subject: [PATCH] syntax: Use `MultiItemModifier` for built-in derives --- src/libsyntax/ext/base.rs | 7 ++---- src/libsyntax/ext/expand.rs | 40 +++++++++++++++---------------- src/libsyntax_ext/deriving/mod.rs | 24 +++++++++++++++---- 3 files changed, 42 insertions(+), 29 deletions(-) diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 9979f5d0a0edf..4a357b0f3121a 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -1,6 +1,6 @@ pub use SyntaxExtension::*; -use crate::ast::{self, Attribute, Name, PatKind, MetaItem}; +use crate::ast::{self, Attribute, Name, PatKind}; use crate::attr::HasAttrs; use crate::source_map::{SourceMap, Spanned, respan}; use crate::edition::Edition; @@ -519,9 +519,6 @@ impl MacResult for DummyResult { } } -pub type BuiltinDeriveFn = - for<'cx> fn(&'cx mut ExtCtxt<'_>, Span, &MetaItem, &Annotatable, &mut dyn FnMut(Annotatable)); - /// Represents different kinds of macro invocations that can be resolved. #[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub enum MacroKind { @@ -607,7 +604,7 @@ pub enum SyntaxExtension { Vec /* inert attribute names */, Edition), /// An attribute-like procedural macro that derives a builtin trait. - BuiltinDerive(BuiltinDeriveFn), + BuiltinDerive(Box), /// A declarative macro, e.g., `macro m() {}`. DeclMacro { diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 715303db17378..892c59bbc0446 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -893,29 +893,29 @@ impl<'a, 'b> MacroExpander<'a, 'b> { edition: ext.edition(self.cx.parse_sess.edition), }; - match *ext { - ProcMacroDerive(ref ext, ..) => { - invoc.expansion_data.mark.set_expn_info(expn_info); - let span = span.with_ctxt(self.cx.backtrace()); - let dummy = ast::MetaItem { // FIXME(jseyfried) avoid this - path: Path::from_ident(Ident::invalid()), - span: DUMMY_SP, - node: ast::MetaItemKind::Word, + match ext { + ProcMacroDerive(expander, ..) | BuiltinDerive(expander) => { + let meta = match ext { + ProcMacroDerive(..) => ast::MetaItem { // FIXME(jseyfried) avoid this + path: Path::from_ident(Ident::invalid()), + span: DUMMY_SP, + node: ast::MetaItemKind::Word, + }, + _ => { + expn_info.allow_internal_unstable = Some(vec![ + sym::rustc_attrs, + Symbol::intern("derive_clone_copy"), + Symbol::intern("derive_eq"), + // RustcDeserialize and RustcSerialize + Symbol::intern("libstd_sys_internals"), + ].into()); + attr.meta()? + } }; - let items = ext.expand(self.cx, span, &dummy, item); - Some(invoc.fragment_kind.expect_from_annotatables(items)) - } - BuiltinDerive(func) => { - expn_info.allow_internal_unstable = Some(vec![ - sym::rustc_attrs, - Symbol::intern("derive_clone_copy"), - Symbol::intern("derive_eq"), - Symbol::intern("libstd_sys_internals"), // RustcDeserialize and RustcSerialize - ].into()); + invoc.expansion_data.mark.set_expn_info(expn_info); let span = span.with_ctxt(self.cx.backtrace()); - let mut items = Vec::new(); - func(self.cx, span, &attr.meta()?, &item, &mut |a| items.push(a)); + let items = expander.expand(self.cx, span, &meta, item); Some(invoc.fragment_kind.expect_from_annotatables(items)) } _ => { diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs index ac41f30e6b39f..2f09ab2087e41 100644 --- a/src/libsyntax_ext/deriving/mod.rs +++ b/src/libsyntax_ext/deriving/mod.rs @@ -1,8 +1,8 @@ //! The compiler code necessary to implement the `#[derive]` extensions. use rustc_data_structures::sync::Lrc; -use syntax::ast; -use syntax::ext::base::{Annotatable, ExtCtxt, SyntaxExtension, Resolver}; +use syntax::ast::{self, MetaItem}; +use syntax::ext::base::{Annotatable, ExtCtxt, SyntaxExtension, Resolver, MultiItemModifier}; use syntax::ext::build::AstBuilder; use syntax::ext::hygiene::{Mark, SyntaxContext}; use syntax::ptr::P; @@ -39,9 +39,25 @@ pub mod partial_ord; #[path="cmp/ord.rs"] pub mod ord; - pub mod generic; +struct BuiltinDerive( + fn(&mut ExtCtxt<'_>, Span, &MetaItem, &Annotatable, &mut dyn FnMut(Annotatable)) +); + +impl MultiItemModifier for BuiltinDerive { + fn expand(&self, + ecx: &mut ExtCtxt<'_>, + span: Span, + meta_item: &MetaItem, + item: Annotatable) + -> Vec { + let mut items = Vec::new(); + (self.0)(ecx, span, meta_item, &item, &mut |a| items.push(a)); + items + } +} + macro_rules! derive_traits { ($( $name:expr => $func:path, )+) => { pub fn is_builtin_trait(name: ast::Name) -> bool { @@ -55,7 +71,7 @@ macro_rules! derive_traits { $( resolver.add_builtin( ast::Ident::with_empty_ctxt(Symbol::intern($name)), - Lrc::new(SyntaxExtension::BuiltinDerive($func)) + Lrc::new(SyntaxExtension::BuiltinDerive(Box::new(BuiltinDerive($func)))) ); )* }