syntax: Use MultiItemModifier
for built-in derives
This commit is contained in:
parent
5a6ebec018
commit
edb925a91f
3 changed files with 42 additions and 29 deletions
|
@ -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<Symbol> /* inert attribute names */, Edition),
|
||||
|
||||
/// An attribute-like procedural macro that derives a builtin trait.
|
||||
BuiltinDerive(BuiltinDeriveFn),
|
||||
BuiltinDerive(Box<dyn MultiItemModifier + sync::Sync + sync::Send>),
|
||||
|
||||
/// A declarative macro, e.g., `macro m() {}`.
|
||||
DeclMacro {
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
_ => {
|
||||
|
|
|
@ -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<Annotatable> {
|
||||
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))))
|
||||
);
|
||||
)*
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue