syntax: implement #[deriving(DeepClone)]. Fixes #6514.

This commit is contained in:
Huon Wilson 2013-05-16 14:15:37 +10:00
parent 2329651770
commit cd2eb4701f
9 changed files with 94 additions and 18 deletions

View File

@ -1562,7 +1562,7 @@ Supported traits for `deriving` are:
* Comparison traits: `Eq`, `TotalEq`, `Ord`, `TotalOrd`.
* Serialization: `Encodable`, `Decodable`. These require `std`.
* `Clone`, to perform deep copies.
* `Clone` and `DeepClone`, to perform (deep) copies.
* `IterBytes`, to iterate over the bytes in a data type.
* `Rand`, to create a random instance of a data type.
* `ToStr`, to convert to a string. For a type with this instance,

View File

@ -2308,8 +2308,8 @@ enum ABC { A, B, C }
~~~
The full list of derivable traits is `Eq`, `TotalEq`, `Ord`,
`TotalOrd`, `Encodable` `Decodable`, `Clone`, `IterBytes`, `Rand` and
`ToStr`.
`TotalOrd`, `Encodable` `Decodable`, `Clone`, `DeepClone`,
`IterBytes`, `Rand` and `ToStr`.
# Modules and crates

View File

@ -32,7 +32,7 @@ pub fn expand_deriving_clone(cx: @ext_ctxt,
args: ~[],
ret_ty: Self,
const_nonmatching: false,
combine_substructure: cs_clone
combine_substructure: |c, s, sub| cs_clone("Clone", c, s, sub)
}
]
};
@ -42,8 +42,39 @@ pub fn expand_deriving_clone(cx: @ext_ctxt,
&trait_def)
}
fn cs_clone(cx: @ext_ctxt, span: span,
substr: &Substructure) -> @expr {
pub fn expand_deriving_deep_clone(cx: @ext_ctxt,
span: span,
mitem: @meta_item,
in_items: ~[@item])
-> ~[@item] {
let trait_def = TraitDef {
path: Path::new(~[~"core", ~"clone", ~"DeepClone"]),
additional_bounds: ~[],
generics: LifetimeBounds::empty(),
methods: ~[
MethodDef {
name: ~"deep_clone",
generics: LifetimeBounds::empty(),
explicit_self: borrowed_explicit_self(),
args: ~[],
ret_ty: Self,
const_nonmatching: false,
// cs_clone uses the ident passed to it, i.e. it will
// call deep_clone (not clone) here.
combine_substructure: |c, s, sub| cs_clone("DeepClone", c, s, sub)
}
]
};
expand_deriving_generic(cx, span,
mitem, in_items,
&trait_def)
}
fn cs_clone(
name: &str,
cx: @ext_ctxt, span: span,
substr: &Substructure) -> @expr {
let clone_ident = substr.method_ident;
let ctor_ident;
let all_fields;
@ -59,8 +90,12 @@ fn cs_clone(cx: @ext_ctxt, span: span,
ctor_ident = ~[ variant.node.name ];
all_fields = af;
},
EnumNonMatching(*) => cx.span_bug(span, "Non-matching enum variants in `deriving(Clone)`"),
StaticEnum(*) | StaticStruct(*) => cx.span_bug(span, "Static method in `deriving(Clone)`")
EnumNonMatching(*) => cx.span_bug(span,
~"Non-matching enum variants in `deriving(" +
name + ")`"),
StaticEnum(*) | StaticStruct(*) => cx.span_bug(span,
~"Static method in `deriving(" +
name + ")`")
}
match *all_fields {
@ -76,7 +111,7 @@ fn cs_clone(cx: @ext_ctxt, span: span,
Some(i) => i,
None => cx.span_bug(span,
~"unnamed field in normal struct \
in `deriving(Clone)`")
in `deriving(" + name + ")`")
};
build::Field { ident: ident, ex: subcall(self_f) }
};

View File

@ -84,6 +84,7 @@ macro_rules! expand(($func:path) => ($func(cx, titem.span,
titem, in_items)));
match *tname {
~"Clone" => expand!(clone::expand_deriving_clone),
~"DeepClone" => expand!(clone::expand_deriving_deep_clone),
~"IterBytes" => expand!(iter_bytes::expand_deriving_iter_bytes),

View File

@ -8,11 +8,14 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[deriving(Clone)]
#[deriving(Clone, DeepClone)]
enum E {
A,
B(()),
C
}
pub fn main() {}
pub fn main() {
let _ = A.clone();
let _ = B(()).deep_clone();
}

View File

@ -1,8 +1,21 @@
#[deriving(Clone)]
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[deriving(Clone, DeepClone)]
enum E<T,U> {
A(T),
B(T,U),
C
}
fn main() {}
fn main() {
let _ = A::<int, int>(1i).clone();
let _ = B(1i, 1.234).deep_clone();
}

View File

@ -8,11 +8,13 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[deriving(Clone)]
#[deriving(Clone, DeepClone)]
struct S<T> {
foo: (),
bar: (),
baz: T,
}
pub fn main() {}
pub fn main() {
let _ = S { foo: (), bar: (), baz: 1i }.clone().deep_clone();
}

View File

@ -1,4 +1,16 @@
#[deriving(Clone)]
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[deriving(Clone, DeepClone)]
struct S<T>(T, ());
fn main() {}
fn main() {
let _ = S(1i, ()).clone().deep_clone();
}

View File

@ -1,4 +1,14 @@
#[deriving(Clone)]
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[deriving(Clone, DeepClone)]
struct S {
_int: int,
_i8: i8,