1 // Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 use ast::{MetaItem, Item, Expr};
13 use ext::base::ExtCtxt;
14 use ext::build::AstBuilder;
15 use ext::deriving::generic::*;
17 pub fn expand_deriving_clone(cx: &mut ExtCtxt,
22 let trait_def = TraitDef {
24 attributes: Vec::new(),
25 path: Path::new(vec!("std", "clone", "Clone")),
26 additional_bounds: Vec::new(),
27 generics: LifetimeBounds::empty(),
31 generics: LifetimeBounds::empty(),
32 explicit_self: borrowed_explicit_self(),
36 const_nonmatching: false,
37 combine_substructure: |c, s, sub| cs_clone("Clone", c, s, sub)
42 trait_def.expand(cx, mitem, item, push)
45 pub fn expand_deriving_deep_clone(cx: &mut ExtCtxt,
50 let trait_def = TraitDef {
52 attributes: Vec::new(),
53 path: Path::new(vec!("std", "clone", "DeepClone")),
54 additional_bounds: Vec::new(),
55 generics: LifetimeBounds::empty(),
59 generics: LifetimeBounds::empty(),
60 explicit_self: borrowed_explicit_self(),
64 const_nonmatching: false,
65 // cs_clone uses the ident passed to it, i.e. it will
66 // call deep_clone (not clone) here.
67 combine_substructure: |c, s, sub| cs_clone("DeepClone", c, s, sub)
72 trait_def.expand(cx, mitem, item, push)
77 cx: &mut ExtCtxt, trait_span: Span,
78 substr: &Substructure) -> @Expr {
79 let clone_ident = substr.method_ident;
82 let subcall = |field: &FieldInfo|
83 cx.expr_method_call(field.span, field.self_, clone_ident, Vec::new());
85 match *substr.fields {
87 ctor_ident = substr.type_ident;
90 EnumMatching(_, variant, ref af) => {
91 ctor_ident = variant.node.name;
94 EnumNonMatching(..) => cx.span_bug(trait_span,
95 format!("non-matching enum variants in `deriving({})`",
97 StaticEnum(..) | StaticStruct(..) => cx.span_bug(trait_span,
98 format!("static method in `deriving({})`",
102 if all_fields.len() >= 1 && all_fields[0].name.is_none() {
104 let subcalls = all_fields.map(subcall);
105 cx.expr_call_ident(trait_span, ctor_ident, subcalls)
108 let fields = all_fields.map(|field| {
109 let ident = match field.name {
111 None => cx.span_bug(trait_span,
112 format!("unnamed field in normal struct in `deriving({})`",
115 cx.field_imm(field.span, ident, subcall(field))
118 if fields.is_empty() {
119 // no fields, so construct like `None`
120 cx.expr_ident(trait_span, ctor_ident)
122 cx.expr_struct_ident(trait_span, ctor_ident, fields)