]>
Commit | Line | Data |
---|---|---|
9fa01778 XL |
1 | use crate::deriving::path_std; |
2 | use crate::deriving::generic::*; | |
3 | use crate::deriving::generic::ty::*; | |
9cc50fc6 | 4 | |
5bcae85e | 5 | use syntax::ast::{Expr, MetaItem}; |
0731742a | 6 | use syntax::ext::base::{Annotatable, DummyResult, ExtCtxt}; |
9cc50fc6 | 7 | use syntax::ext::build::AstBuilder; |
9cc50fc6 | 8 | use syntax::ptr::P; |
dc9dc135 | 9 | use syntax::symbol::{kw, sym}; |
9fa01778 | 10 | use syntax::span_err; |
3157f602 | 11 | use syntax_pos::Span; |
1a4d82fc | 12 | |
9fa01778 | 13 | pub 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 |
46 | fn 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 | } |