rustc_builtin_macros/deriving/
mod.rs
1use rustc_ast as ast;
4use rustc_ast::ptr::P;
5use rustc_ast::{GenericArg, MetaItem};
6use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, MultiItemModifier};
7use rustc_span::{Span, Symbol, sym};
8use thin_vec::{ThinVec, thin_vec};
9
10macro path_local($x:ident) {
11 generic::ty::Path::new_local(sym::$x)
12}
13
14macro pathvec_std($($rest:ident)::+) {{
15 vec![ $( sym::$rest ),+ ]
16}}
17
18macro path_std($($x:tt)*) {
19 generic::ty::Path::new( pathvec_std!( $($x)* ) )
20}
21
22pub(crate) mod bounds;
23pub(crate) mod clone;
24pub(crate) mod coerce_pointee;
25pub(crate) mod debug;
26pub(crate) mod default;
27pub(crate) mod hash;
28
29#[path = "cmp/eq.rs"]
30pub(crate) mod eq;
31#[path = "cmp/ord.rs"]
32pub(crate) mod ord;
33#[path = "cmp/partial_eq.rs"]
34pub(crate) mod partial_eq;
35#[path = "cmp/partial_ord.rs"]
36pub(crate) mod partial_ord;
37
38pub(crate) mod generic;
39
40pub(crate) type BuiltinDeriveFn =
41 fn(&ExtCtxt<'_>, Span, &MetaItem, &Annotatable, &mut dyn FnMut(Annotatable), bool);
42
43pub(crate) struct BuiltinDerive(pub(crate) BuiltinDeriveFn);
44
45impl MultiItemModifier for BuiltinDerive {
46 fn expand(
47 &self,
48 ecx: &mut ExtCtxt<'_>,
49 span: Span,
50 meta_item: &MetaItem,
51 item: Annotatable,
52 is_derive_const: bool,
53 ) -> ExpandResult<Vec<Annotatable>, Annotatable> {
54 let span = ecx.with_def_site_ctxt(span);
57 let mut items = Vec::new();
58 match item {
59 Annotatable::Stmt(stmt) => {
60 if let ast::StmtKind::Item(item) = stmt.into_inner().kind {
61 (self.0)(
62 ecx,
63 span,
64 meta_item,
65 &Annotatable::Item(item),
66 &mut |a| {
67 items.push(Annotatable::Stmt(P(ast::Stmt {
70 id: ast::DUMMY_NODE_ID,
71 kind: ast::StmtKind::Item(a.expect_item()),
72 span,
73 })));
74 },
75 is_derive_const,
76 );
77 } else {
78 unreachable!("should have already errored on non-item statement")
79 }
80 }
81 _ => {
82 (self.0)(ecx, span, meta_item, &item, &mut |a| items.push(a), is_derive_const);
83 }
84 }
85 ExpandResult::Ready(items)
86 }
87}
88
89fn call_intrinsic(
91 cx: &ExtCtxt<'_>,
92 span: Span,
93 intrinsic: Symbol,
94 args: ThinVec<P<ast::Expr>>,
95) -> P<ast::Expr> {
96 let span = cx.with_def_site_ctxt(span);
97 let path = cx.std_path(&[sym::intrinsics, intrinsic]);
98 cx.expr_call_global(span, path, args)
99}
100
101fn call_unreachable(cx: &ExtCtxt<'_>, span: Span) -> P<ast::Expr> {
103 let span = cx.with_def_site_ctxt(span);
104 let path = cx.std_path(&[sym::intrinsics, sym::unreachable]);
105 let call = cx.expr_call_global(span, path, ThinVec::new());
106
107 cx.expr_block(P(ast::Block {
108 stmts: thin_vec![cx.stmt_expr(call)],
109 id: ast::DUMMY_NODE_ID,
110 rules: ast::BlockCheckMode::Unsafe(ast::CompilerGenerated),
111 span,
112 tokens: None,
113 could_be_bare_literal: false,
114 }))
115}
116
117fn assert_ty_bounds(
118 cx: &ExtCtxt<'_>,
119 stmts: &mut ThinVec<ast::Stmt>,
120 ty: P<ast::Ty>,
121 span: Span,
122 assert_path: &[Symbol],
123) {
124 let span = cx.with_def_site_ctxt(span);
126 let assert_path = cx.path_all(span, true, cx.std_path(assert_path), vec![GenericArg::Type(ty)]);
127 stmts.push(cx.stmt_let_type_only(span, cx.ty_path(assert_path)));
128}