3 #![feature(plugin_registrar)]
4 #![feature(box_syntax)]
5 #![feature(rustc_private)]
8 extern crate syntax_ext;
9 extern crate syntax_pos;
11 extern crate rustc_plugin;
15 use syntax::ext::base::{MultiDecorator, ExtCtxt, Annotatable};
16 use syntax::ext::build::AstBuilder;
17 use syntax::symbol::Symbol;
19 use syntax_ext::deriving::generic::{TraitDef, MethodDef, combine_substructure};
20 use syntax_ext::deriving::generic::{Substructure, Struct, EnumMatching};
21 use syntax_ext::deriving::generic::ty::{Literal, LifetimeBounds, Path, borrowed_explicit_self};
23 use rustc_plugin::Registry;
26 pub fn plugin_registrar(reg: &mut Registry) {
27 reg.register_syntax_extension(
28 Symbol::intern("rustc_derive_TotalSum"),
29 MultiDecorator(box expand));
32 fn expand(cx: &mut ExtCtxt,
34 mitem: &ast::MetaItem,
36 push: &mut FnMut(Annotatable)) {
37 let trait_def = TraitDef {
40 path: Path::new_local("TotalSum"),
41 additional_bounds: vec![],
42 generics: LifetimeBounds::empty(),
43 associated_types: vec![],
45 supports_unions: false,
49 generics: LifetimeBounds::empty(),
50 explicit_self: borrowed_explicit_self(),
52 ret_ty: Literal(Path::new_local("isize")),
55 unify_fieldless_variants: true,
56 combine_substructure: combine_substructure(Box::new(totalsum_substructure)),
61 trait_def.expand(cx, mitem, item, push)
64 // Mostly copied from syntax::ext::deriving::hash
65 /// Defines how the implementation for `trace()` is to be generated
66 fn totalsum_substructure(cx: &mut ExtCtxt, trait_span: Span,
67 substr: &Substructure) -> P<ast::Expr> {
68 let fields = match *substr.fields {
69 Struct(_, ref fs) | EnumMatching(.., ref fs) => fs,
70 _ => cx.span_bug(trait_span, "impossible substructure")
73 fields.iter().fold(cx.expr_isize(trait_span, 0), |acc, ref item| {
74 if attr::contains_name(&item.attrs, "ignore") {
77 cx.expr_binary(item.span, ast::BinOpKind::Add, acc,
78 cx.expr_method_call(item.span,