rustc_builtin_macros/deriving/
mod.rs1use rustc_ast as ast;
4use rustc_ast::{GenericArg, MetaItem};
5use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, MultiItemModifier};
6use rustc_span::{Span, Symbol, sym};
7use thin_vec::{ThinVec, thin_vec};
8
9macro pathvec($($rest:ident)::+) {{
10 &[ $( sym::$rest ),+ ]
11}}
12
13macro path_std($cx: expr, $span: expr, $($x:tt)*) {
14 generic::ty::new_path($cx, $span, pathvec!( $($x)* ), &[] )
15}
16
17pub(crate) mod clone;
18pub(crate) mod coerce_pointee;
19pub(crate) mod const_param_ty;
20pub(crate) mod copy;
21pub(crate) mod debug;
22pub(crate) mod default;
23pub(crate) mod eq;
24pub(crate) mod from;
25pub(crate) mod hash;
26pub(crate) mod ord;
27pub(crate) mod partial_eq;
28pub(crate) mod partial_ord;
29pub(crate) mod reborrow;
30
31pub(crate) mod generic;
32
33pub(crate) type BuiltinDeriveFn =
34 fn(&ExtCtxt<'_>, Span, &ast::Item, &mut dyn FnMut(Box<ast::Item>), bool);
35
36pub(crate) struct BuiltinDerive(pub(crate) BuiltinDeriveFn);
37
38impl MultiItemModifier for BuiltinDerive {
39 fn expand(
40 &self,
41 ecx: &mut ExtCtxt<'_>,
42 span: Span,
43 _: &MetaItem,
44 item: Annotatable,
45 is_derive_const: bool,
46 ) -> ExpandResult<Vec<Annotatable>, Annotatable> {
47 let span = ecx.with_def_site_ctxt(span);
50 let mut items = Vec::new();
51 match item {
52 Annotatable::Stmt(stmt) => {
53 if let ast::StmtKind::Item(item) = stmt.kind {
54 (self.0)(
55 ecx,
56 span,
57 &item,
58 &mut |a| items.push(Annotatable::Stmt(Box::new(ecx.stmt_item(span, a)))),
59 is_derive_const,
60 );
61 } else {
62 {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("should have already errored on non-item statement")));
}unreachable!("should have already errored on non-item statement")
63 }
64 }
65 Annotatable::Item(item) => (self.0)(
66 ecx,
67 span,
68 &item,
69 &mut |a| items.push(Annotatable::Item(a)),
70 is_derive_const,
71 ),
72 _ => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
73 }
74 ExpandResult::Ready(items)
75 }
76}
77
78fn call_intrinsic(
80 cx: &ExtCtxt<'_>,
81 span: Span,
82 intrinsic: Symbol,
83 args: ThinVec<Box<ast::Expr>>,
84) -> Box<ast::Expr> {
85 let span = cx.with_def_site_ctxt(span);
86 let path = cx.std_path(&[sym::intrinsics, intrinsic]);
87 cx.expr_call_global(span, path, args)
88}
89
90fn call_unreachable(cx: &ExtCtxt<'_>, span: Span) -> Box<ast::Expr> {
92 let call = call_intrinsic(cx, span, sym::unreachable, ThinVec::new());
93 cx.expr_block(Box::new(ast::Block {
94 stmts: {
let len = [()].len();
let mut vec = ::thin_vec::ThinVec::with_capacity(len);
vec.push(cx.stmt_expr(call));
vec
}thin_vec![cx.stmt_expr(call)],
95 id: ast::DUMMY_NODE_ID,
96 rules: ast::BlockCheckMode::Unsafe(ast::CompilerGenerated),
97 span,
98 }))
99}
100
101fn assert_ty_bounds(
102 cx: &ExtCtxt<'_>,
103 stmts: &mut ThinVec<ast::Stmt>,
104 ty: Box<ast::Ty>,
105 span: Span,
106 assert_path: &[Symbol],
107) {
108 let span = cx.with_def_site_ctxt(span);
110 let assert_path = cx.path_all(span, true, cx.std_path(assert_path), ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[GenericArg::Type(ty)]))vec![GenericArg::Type(ty)]);
111 stmts.push(cx.stmt_let_type_only(span, cx.ty_path(assert_path)));
112}