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