]> git.lizzy.rs Git - rust.git/blob - src/test/run-pass-fulldeps/auxiliary/custom-derive-plugin-attr.rs
Auto merge of #60252 - davidtwco:issue-57672, r=Mark-Simulacrum
[rust.git] / src / test / run-pass-fulldeps / auxiliary / custom-derive-plugin-attr.rs
1 // force-host
2
3 #![feature(plugin_registrar)]
4 #![feature(box_syntax)]
5 #![feature(rustc_private)]
6
7 extern crate syntax;
8 extern crate syntax_ext;
9 extern crate syntax_pos;
10 extern crate rustc;
11 extern crate rustc_plugin;
12
13 use syntax::ast;
14 use syntax::attr;
15 use syntax::ext::base::{MultiDecorator, ExtCtxt, Annotatable};
16 use syntax::ext::build::AstBuilder;
17 use syntax::symbol::{Symbol, sym};
18 use syntax::ptr::P;
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};
22 use syntax_pos::Span;
23 use rustc_plugin::Registry;
24
25 #[plugin_registrar]
26 pub fn plugin_registrar(reg: &mut Registry) {
27     reg.register_syntax_extension(
28         Symbol::intern("rustc_derive_TotalSum"),
29         MultiDecorator(box expand));
30 }
31
32 fn expand(cx: &mut ExtCtxt,
33           span: Span,
34           mitem: &ast::MetaItem,
35           item: &Annotatable,
36           push: &mut FnMut(Annotatable)) {
37     let trait_def = TraitDef {
38         span: span,
39         attributes: vec![],
40         path: Path::new_local("TotalSum"),
41         additional_bounds: vec![],
42         generics: LifetimeBounds::empty(),
43         associated_types: vec![],
44         is_unsafe: false,
45         supports_unions: false,
46         methods: vec![
47             MethodDef {
48                 name: "total_sum",
49                 generics: LifetimeBounds::empty(),
50                 explicit_self: borrowed_explicit_self(),
51                 args: vec![],
52                 ret_ty: Literal(Path::new_local("isize")),
53                 attributes: vec![],
54                 is_unsafe: false,
55                 unify_fieldless_variants: true,
56                 combine_substructure: combine_substructure(Box::new(totalsum_substructure)),
57             },
58         ],
59     };
60
61     trait_def.expand(cx, mitem, item, push)
62 }
63
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")
71     };
72
73     fields.iter().fold(cx.expr_isize(trait_span, 0), |acc, ref item| {
74         if attr::contains_name(&item.attrs, sym::ignore) {
75             acc
76         } else {
77             cx.expr_binary(item.span, ast::BinOpKind::Add, acc,
78                            cx.expr_method_call(item.span,
79                                                item.self_.clone(),
80                                                substr.method_ident,
81                                                Vec::new()))
82         }
83     })
84 }