1 //! The compiler code necessary to implement the `#[derive]` extensions.
3 use syntax::ast::{self, MetaItem};
4 use syntax::ext::base::{Annotatable, ExtCtxt, MultiItemModifier};
5 use syntax::ext::build::AstBuilder;
7 use syntax::symbol::{Symbol, sym};
10 macro path_local($x:ident) {
11 generic::ty::Path::new_local(stringify!($x))
14 macro pathvec_std($cx:expr, $($rest:ident)::+) {{
15 vec![ $( stringify!($rest) ),+ ]
18 macro path_std($($x:tt)*) {
19 generic::ty::Path::new( pathvec_std!( $($x)* ) )
30 #[path="cmp/partial_eq.rs"]
34 #[path="cmp/partial_ord.rs"]
41 crate struct BuiltinDerive(
42 crate fn(&mut ExtCtxt<'_>, Span, &MetaItem, &Annotatable, &mut dyn FnMut(Annotatable))
45 impl MultiItemModifier for BuiltinDerive {
47 ecx: &mut ExtCtxt<'_>,
52 let mut items = Vec::new();
53 (self.0)(ecx, span, meta_item, &item, &mut |a| items.push(a));
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 {
66 ast::ItemKind::Struct(_, ast::Generics { ref params, .. }) |
67 ast::ItemKind::Enum(_, ast::Generics { ref params, .. }) => {
70 ast::GenericParamKind::Type { .. } => {
71 typaram.push_str(¶m.ident.as_str());
85 /// Constructs an expression that calls an intrinsic
86 fn call_intrinsic(cx: &ExtCtxt<'_>,
89 args: Vec<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);
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),