diff options
| author | bors <bors@rust-lang.org> | 2013-03-12 10:09:55 -0700 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2013-03-12 10:09:55 -0700 |
| commit | a9643d39f8243dceb1184f446d988081a607d824 (patch) | |
| tree | f18385c4e082fe3769e4c9e79b1b713937962b89 /src | |
| parent | 15d78fc398527c5035c092c1c67db600543902d5 (diff) | |
| parent | 24efea720860e1dc8d4d1035f1ea8d56a3498614 (diff) | |
| download | rust-a9643d39f8243dceb1184f446d988081a607d824.tar.gz rust-a9643d39f8243dceb1184f446d988081a607d824.zip | |
auto merge of #5320 : apasel422/rust/metaderive, r=graydon
This is the first in a series of patches I'm working on to clean up the code related to `deriving`. This patch allows
```
#[deriving_eq]
#[deriving_iter_bytes]
#[deriving_clone]
struct Foo { bar: uint }
```
to be replaced with:
```
#[deriving(Eq, IterBytes, Clone)]
struct Foo { bar: uint }
```
It leaves the old attributes alone for the time being.
Eventually I'd like to incorporate the new closest-match-suggestion infrastructure for mistyped trait names, and also pass the sub-attributes to the deriving code, so that the following will be possible:
```
#[deriving(TotalOrd(qux, bar))]
struct Foo { bar: uint, baz: char, qux: int }
```
This says to derive an `impl` in which the objects' `qux` fields are compared first, followed by `bar`, while `baz` is ignored in the comparison. If no fields are specified explicitly, all fields will be compared in the order they're defined in the `struct`. This might also be useful for `Eq`. Coming soon.
Diffstat (limited to 'src')
| -rw-r--r-- | src/libsyntax/ext/base.rs | 3 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving.rs | 42 | ||||
| -rw-r--r-- | src/test/compile-fail/deriving-meta-unknown-trait.rs | 14 | ||||
| -rw-r--r-- | src/test/run-pass/deriving-meta-empty-trait-list.rs | 19 | ||||
| -rw-r--r-- | src/test/run-pass/deriving-meta-multiple.rs | 29 | ||||
| -rw-r--r-- | src/test/run-pass/deriving-meta.rs | 27 |
6 files changed, 134 insertions, 0 deletions
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 1eae4b84cc9..c8363e3daa8 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -148,6 +148,9 @@ pub fn syntax_expander_table() -> SyntaxEnv { syntax_expanders.insert(@~"log_syntax", builtin_normal_tt( ext::log_syntax::expand_syntax_ext)); + syntax_expanders.insert(@~"deriving", + @SE(ItemDecorator( + ext::deriving::expand_meta_deriving))); syntax_expanders.insert(@~"deriving_eq", @SE(ItemDecorator( ext::deriving::expand_deriving_eq))); diff --git a/src/libsyntax/ext/deriving.rs b/src/libsyntax/ext/deriving.rs index efea962a089..093327ec32e 100644 --- a/src/libsyntax/ext/deriving.rs +++ b/src/libsyntax/ext/deriving.rs @@ -56,6 +56,48 @@ type ExpandDerivingEnumDefFn = &self/fn(ext_ctxt, ident, y: &Generics) -> @item; +pub fn expand_meta_deriving(cx: ext_ctxt, + _span: span, + mitem: @meta_item, + in_items: ~[@item]) + -> ~[@item] { + use ast::{meta_list, meta_name_value, meta_word}; + + match mitem.node { + meta_name_value(_, l) => { + cx.span_err(l.span, ~"unexpected value in `deriving`"); + in_items + } + meta_word(_) | meta_list(_, []) => { + cx.span_warn(mitem.span, ~"empty trait list in `deriving`"); + in_items + } + meta_list(_, titems) => { + do titems.foldr(in_items) |&titem, in_items| { + match titem.node { + meta_name_value(tname, _) | + meta_list(tname, _) | + meta_word(tname) => { + match *tname { + ~"Clone" => expand_deriving_clone(cx, + titem.span, titem, in_items), + ~"Eq" => expand_deriving_eq(cx, titem.span, + titem, in_items), + ~"IterBytes" => expand_deriving_iter_bytes(cx, + titem.span, titem, in_items), + tname => { + cx.span_err(titem.span, fmt!("unknown \ + `deriving` trait: `%s`", tname)); + in_items + } + } + } + } + } + } + } +} + pub fn expand_deriving_eq(cx: ext_ctxt, span: span, _mitem: @meta_item, diff --git a/src/test/compile-fail/deriving-meta-unknown-trait.rs b/src/test/compile-fail/deriving-meta-unknown-trait.rs new file mode 100644 index 00000000000..0b9f61dac9e --- /dev/null +++ b/src/test/compile-fail/deriving-meta-unknown-trait.rs @@ -0,0 +1,14 @@ +// 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(Eqr)] //~ ERROR unknown `deriving` trait: `Eqr` +struct Foo; + +pub fn main() {} diff --git a/src/test/run-pass/deriving-meta-empty-trait-list.rs b/src/test/run-pass/deriving-meta-empty-trait-list.rs new file mode 100644 index 00000000000..8e7afffaf0d --- /dev/null +++ b/src/test/run-pass/deriving-meta-empty-trait-list.rs @@ -0,0 +1,19 @@ +// xfail-pretty + +// 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] //~ WARNING empty trait list in `deriving` +struct Foo; + +#[deriving()] //~ WARNING empty trait list in `deriving` +struct Bar; + +pub fn main() {} diff --git a/src/test/run-pass/deriving-meta-multiple.rs b/src/test/run-pass/deriving-meta-multiple.rs new file mode 100644 index 00000000000..d94b6fcb415 --- /dev/null +++ b/src/test/run-pass/deriving-meta-multiple.rs @@ -0,0 +1,29 @@ +// xfail-fast + +// 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(Eq)] +#[deriving(Clone)] +#[deriving(IterBytes)] +struct Foo { + bar: uint, + baz: int +} + +pub fn main() { + use core::hash::{Hash, HashUtil}; // necessary for IterBytes check + + let a = Foo {bar: 4, baz: -3}; + + a == a; // check for Eq impl w/o testing its correctness + a.clone(); // check for Clone impl w/o testing its correctness + a.hash(); // check for IterBytes impl w/o testing its correctness +} diff --git a/src/test/run-pass/deriving-meta.rs b/src/test/run-pass/deriving-meta.rs new file mode 100644 index 00000000000..efb202028f3 --- /dev/null +++ b/src/test/run-pass/deriving-meta.rs @@ -0,0 +1,27 @@ +// xfail-fast + +// 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(Eq, Clone, IterBytes)] +struct Foo { + bar: uint, + baz: int +} + +pub fn main() { + use core::hash::{Hash, HashUtil}; // necessary for IterBytes check + + let a = Foo {bar: 4, baz: -3}; + + a == a; // check for Eq impl w/o testing its correctness + a.clone(); // check for Clone impl w/o testing its correctness + a.hash(); // check for IterBytes impl w/o testing its correctness +} |
