]> git.proxmox.com Git - rustc.git/blame - src/libsyntax_ext/deriving/default.rs
New upstream version 1.37.0+dfsg1
[rustc.git] / src / libsyntax_ext / deriving / default.rs
CommitLineData
9fa01778
XL
1use crate::deriving::path_std;
2use crate::deriving::generic::*;
3use crate::deriving::generic::ty::*;
9cc50fc6 4
5bcae85e 5use syntax::ast::{Expr, MetaItem};
0731742a 6use syntax::ext::base::{Annotatable, DummyResult, ExtCtxt};
9cc50fc6 7use syntax::ext::build::AstBuilder;
9cc50fc6 8use syntax::ptr::P;
dc9dc135 9use syntax::symbol::{kw, sym};
9fa01778 10use syntax::span_err;
3157f602 11use syntax_pos::Span;
1a4d82fc 12
9fa01778 13pub fn expand_deriving_default(cx: &mut ExtCtxt<'_>,
d9579d0f
AL
14 span: Span,
15 mitem: &MetaItem,
62682a34 16 item: &Annotatable,
8faf50e0 17 push: &mut dyn FnMut(Annotatable)) {
dc9dc135 18 let inline = cx.meta_word(span, sym::inline);
5bcae85e 19 let attrs = vec![cx.attribute(span, inline)];
1a4d82fc 20 let trait_def = TraitDef {
3b2f2976 21 span,
1a4d82fc 22 attributes: Vec::new(),
ff7c6d11 23 path: path_std!(cx, default::Default),
1a4d82fc
JJ
24 additional_bounds: Vec::new(),
25 generics: LifetimeBounds::empty(),
e9174d1e 26 is_unsafe: false,
9e0c209e 27 supports_unions: false,
5bcae85e
SL
28 methods: vec![MethodDef {
29 name: "default",
30 generics: LifetimeBounds::empty(),
31 explicit_self: None,
32 args: Vec::new(),
33 ret_ty: Self_,
34 attributes: attrs,
35 is_unsafe: false,
36 unify_fieldless_variants: false,
37 combine_substructure: combine_substructure(Box::new(|a, b, c| {
38 default_substructure(a, b, c)
39 })),
40 }],
85aaf69f 41 associated_types: Vec::new(),
1a4d82fc 42 };
62682a34 43 trait_def.expand(cx, mitem, item, push)
1a4d82fc
JJ
44}
45
9fa01778
XL
46fn default_substructure(cx: &mut ExtCtxt<'_>,
47 trait_span: Span,
48 substr: &Substructure<'_>)
49 -> P<Expr> {
dc9dc135
XL
50 // Note that `kw::Default` is "default" and `sym::Default` is "Default"!
51 let default_ident = cx.std_path(&[kw::Default, sym::Default, kw::Default]);
85aaf69f 52 let default_call = |span| cx.expr_call_global(span, default_ident.clone(), Vec::new());
1a4d82fc
JJ
53
54 return match *substr.fields {
55 StaticStruct(_, ref summary) => {
56 match *summary {
9e0c209e
SL
57 Unnamed(ref fields, is_tuple) => {
58 if !is_tuple {
1a4d82fc
JJ
59 cx.expr_ident(trait_span, substr.type_ident)
60 } else {
61 let exprs = fields.iter().map(|sp| default_call(*sp)).collect();
62 cx.expr_call_ident(trait_span, substr.type_ident, exprs)
63 }
64 }
65 Named(ref fields) => {
5bcae85e
SL
66 let default_fields = fields.iter()
67 .map(|&(ident, span)| cx.field_imm(span, ident, default_call(span)))
68 .collect();
1a4d82fc
JJ
69 cx.expr_struct_ident(trait_span, substr.type_ident, default_fields)
70 }
71 }
72 }
73 StaticEnum(..) => {
b7449926
XL
74 span_err!(cx, trait_span, E0665,
75 "`Default` cannot be derived for enums, only structs");
1a4d82fc 76 // let compilation continue
0731742a 77 DummyResult::raw_expr(trait_span, true)
1a4d82fc 78 }
5bcae85e 79 _ => cx.span_bug(trait_span, "Non-static method in `derive(Default)`"),
1a4d82fc
JJ
80 };
81}