]> git.lizzy.rs Git - rust.git/blob - src/libsyntax_ext/deriving/mod.rs
cad79917af284a623841f5e7104a718482f96a2b
[rust.git] / src / libsyntax_ext / deriving / mod.rs
1 //! The compiler code necessary to implement the `#[derive]` extensions.
2
3 use syntax::ast::{self, MetaItem};
4 use syntax::ext::base::{Annotatable, ExtCtxt, MultiItemModifier};
5 use syntax::ext::build::AstBuilder;
6 use syntax::ptr::P;
7 use syntax::symbol::{Symbol, sym};
8 use syntax_pos::Span;
9
10 macro path_local($x:ident) {
11     generic::ty::Path::new_local(stringify!($x))
12 }
13
14 macro pathvec_std($cx:expr, $($rest:ident)::+) {{
15     vec![ $( stringify!($rest) ),+ ]
16 }}
17
18 macro path_std($($x:tt)*) {
19     generic::ty::Path::new( pathvec_std!( $($x)* ) )
20 }
21
22 pub mod bounds;
23 pub mod clone;
24 pub mod encodable;
25 pub mod decodable;
26 pub mod hash;
27 pub mod debug;
28 pub mod default;
29
30 #[path="cmp/partial_eq.rs"]
31 pub mod partial_eq;
32 #[path="cmp/eq.rs"]
33 pub mod eq;
34 #[path="cmp/partial_ord.rs"]
35 pub mod partial_ord;
36 #[path="cmp/ord.rs"]
37 pub mod ord;
38
39 pub mod generic;
40
41 crate struct BuiltinDerive(
42     crate fn(&mut ExtCtxt<'_>, Span, &MetaItem, &Annotatable, &mut dyn FnMut(Annotatable))
43 );
44
45 impl MultiItemModifier for BuiltinDerive {
46     fn expand(&self,
47               ecx: &mut ExtCtxt<'_>,
48               span: Span,
49               meta_item: &MetaItem,
50               item: Annotatable)
51               -> Vec<Annotatable> {
52         let mut items = Vec::new();
53         (self.0)(ecx, span, meta_item, &item, &mut |a| items.push(a));
54         items
55     }
56 }
57
58 /// Construct a name for the inner type parameter that can't collide with any type parameters of
59 /// the item. This is achieved by starting with a base and then concatenating the names of all
60 /// other type parameters.
61 // FIXME(aburka): use real hygiene when that becomes possible
62 fn hygienic_type_parameter(item: &Annotatable, base: &str) -> String {
63     let mut typaram = String::from(base);
64     if let Annotatable::Item(ref item) = *item {
65         match item.node {
66             ast::ItemKind::Struct(_, ast::Generics { ref params, .. }) |
67             ast::ItemKind::Enum(_, ast::Generics { ref params, .. }) => {
68                 for param in params {
69                     match param.kind {
70                         ast::GenericParamKind::Type { .. } => {
71                             typaram.push_str(&param.ident.as_str());
72                         }
73                         _ => {}
74                     }
75                 }
76             }
77
78             _ => {}
79         }
80     }
81
82     typaram
83 }
84
85 /// Constructs an expression that calls an intrinsic
86 fn call_intrinsic(cx: &ExtCtxt<'_>,
87                   span: Span,
88                   intrinsic: &str,
89                   args: Vec<P<ast::Expr>>)
90                   -> P<ast::Expr> {
91     let span = span.with_ctxt(cx.backtrace());
92     let path = cx.std_path(&[sym::intrinsics, Symbol::intern(intrinsic)]);
93     let call = cx.expr_call_global(span, path, args);
94
95     cx.expr_block(P(ast::Block {
96         stmts: vec![cx.stmt_expr(call)],
97         id: ast::DUMMY_NODE_ID,
98         rules: ast::BlockCheckMode::Unsafe(ast::CompilerGenerated),
99         span,
100     }))
101 }