Skip to content

Commit 6690cfe

Browse files
Make builtin derives a SyntaxExtension
This allows builtin derives to be registered and resolved, just like other derive types.
1 parent 2f0463a commit 6690cfe

File tree

6 files changed

+34
-24
lines changed

6 files changed

+34
-24
lines changed

src/libsyntax/ext/base.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
pub use self::SyntaxExtension::{MultiDecorator, MultiModifier, NormalTT, IdentTT};
1212

13-
use ast::{self, Attribute, Name, PatKind};
13+
use ast::{self, Attribute, Name, PatKind, MetaItem};
1414
use attr::HasAttrs;
1515
use codemap::{self, CodeMap, ExpnInfo, Spanned, respan};
1616
use syntax_pos::{Span, ExpnId, NO_EXPANSION};
@@ -471,6 +471,9 @@ impl MacResult for DummyResult {
471471
}
472472
}
473473

474+
pub type BuiltinDeriveFn =
475+
for<'cx> fn(&'cx mut ExtCtxt, Span, &MetaItem, &Annotatable, &mut FnMut(Annotatable));
476+
474477
/// An enum representing the different kinds of syntax extensions.
475478
pub enum SyntaxExtension {
476479
/// A syntax extension that is attached to an item and creates new items
@@ -508,6 +511,9 @@ pub enum SyntaxExtension {
508511
IdentTT(Box<IdentMacroExpander>, Option<Span>, bool),
509512

510513
CustomDerive(Box<MultiItemModifier>),
514+
515+
/// An attribute-like procedural macro that derives a builtin trait.
516+
BuiltinDerive(BuiltinDeriveFn),
511517
}
512518

513519
pub type NamedSyntaxExtension = (Name, SyntaxExtension);

src/libsyntax/ext/expand.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
370370
let tok_result = mac.expand(self.cx, attr.span, attr_toks, item_toks);
371371
self.parse_expansion(tok_result, kind, name, attr.span)
372372
}
373-
SyntaxExtension::CustomDerive(_) => {
373+
SyntaxExtension::CustomDerive(..) | SyntaxExtension::BuiltinDerive(..) => {
374374
self.cx.span_err(attr.span, &format!("`{}` is a derive mode", name));
375375
kind.dummy(attr.span)
376376
}
@@ -440,7 +440,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
440440
return kind.dummy(span);
441441
}
442442

443-
SyntaxExtension::CustomDerive(..) => {
443+
SyntaxExtension::CustomDerive(..) | SyntaxExtension::BuiltinDerive(..) => {
444444
self.cx.span_err(path.span, &format!("`{}` is a derive mode", extname));
445445
return kind.dummy(span);
446446
}

src/libsyntax_ext/deriving/decodable.rs

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ pub fn expand_deriving_decodable(cx: &mut ExtCtxt,
3535
mitem: &MetaItem,
3636
item: &Annotatable,
3737
push: &mut FnMut(Annotatable)) {
38+
deriving::warn_if_deprecated(cx, span, "Decodable");
3839
expand_deriving_decodable_imp(cx, span, mitem, item, push, "serialize")
3940
}
4041

src/libsyntax_ext/deriving/encodable.rs

+1
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ pub fn expand_deriving_encodable(cx: &mut ExtCtxt,
112112
mitem: &MetaItem,
113113
item: &Annotatable,
114114
push: &mut FnMut(Annotatable)) {
115+
deriving::warn_if_deprecated(cx, span, "Encodable");
115116
expand_deriving_encodable_imp(cx, span, mitem, item, push, "serialize")
116117
}
117118

src/libsyntax_ext/deriving/mod.rs

+21-21
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,11 @@
1010

1111
//! The compiler code necessary to implement the `#[derive]` extensions.
1212
13+
use std::rc::Rc;
1314
use syntax::ast::{self, MetaItem};
1415
use syntax::attr::HasAttrs;
1516
use syntax::codemap;
16-
use syntax::ext::base::{Annotatable, ExtCtxt, SyntaxExtension};
17+
use syntax::ext::base::{Annotatable, ExtCtxt, SyntaxExtension, Resolver};
1718
use syntax::ext::build::AstBuilder;
1819
use syntax::feature_gate;
1920
use syntax::ptr::P;
@@ -292,7 +293,10 @@ pub fn expand_derive(cx: &mut ExtCtxt,
292293
for titem in traits.iter() {
293294
let tname = titem.word().unwrap().name();
294295
let name = Symbol::intern(&format!("derive({})", tname));
296+
let tname_cx = ast::Ident::with_empty_ctxt(titem.name().unwrap());
295297
let mitem = cx.meta_word(titem.span, name);
298+
let path = ast::Path::from_ident(titem.span, tname_cx);
299+
let ext = cx.resolver.resolve_macro(cx.current_expansion.mark, &path, false).unwrap();
296300

297301
let span = Span {
298302
expn_id: cx.codemap().record_expansion(codemap::ExpnInfo {
@@ -306,11 +310,15 @@ pub fn expand_derive(cx: &mut ExtCtxt,
306310
..titem.span
307311
};
308312

309-
let my_item = Annotatable::Item(item);
310-
expand_builtin(&tname.as_str(), cx, span, &mitem, &my_item, &mut |a| {
311-
items.push(a);
312-
});
313-
item = my_item.expect_item();
313+
if let SyntaxExtension::BuiltinDerive(ref func) = *ext {
314+
let my_item = Annotatable::Item(item);
315+
func(cx, span, &mitem, &my_item, &mut |a| {
316+
items.push(a)
317+
});
318+
item = my_item.expect_item();
319+
} else {
320+
unreachable!();
321+
}
314322
}
315323

316324
items.insert(0, Annotatable::Item(item));
@@ -326,21 +334,13 @@ macro_rules! derive_traits {
326334
}
327335
}
328336

329-
fn expand_builtin(name: &str,
330-
ecx: &mut ExtCtxt,
331-
span: Span,
332-
mitem: &MetaItem,
333-
item: &Annotatable,
334-
push: &mut FnMut(Annotatable)) {
335-
match name {
336-
$(
337-
$name => {
338-
warn_if_deprecated(ecx, span, $name);
339-
$func(ecx, span, mitem, item, push);
340-
}
341-
)*
342-
_ => panic!("not a builtin derive mode: {}", name),
343-
}
337+
pub fn register_builtin_derives(resolver: &mut Resolver) {
338+
$(
339+
resolver.add_ext(
340+
ast::Ident::with_empty_ctxt(Symbol::intern($name)),
341+
Rc::new(SyntaxExtension::BuiltinDerive($func))
342+
);
343+
)*
344344
}
345345
}
346346
}

src/libsyntax_ext/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ use syntax::symbol::Symbol;
5757
pub fn register_builtins(resolver: &mut syntax::ext::base::Resolver,
5858
user_exts: Vec<NamedSyntaxExtension>,
5959
enable_quotes: bool) {
60+
deriving::register_builtin_derives(resolver);
61+
6062
let mut register = |name, ext| {
6163
resolver.add_ext(ast::Ident::with_empty_ctxt(name), Rc::new(ext));
6264
};

0 commit comments

Comments
 (0)