diff --git a/src/doc/reference.md b/src/doc/reference.md index 94c76aaa6951..b6684c560c85 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -2436,8 +2436,12 @@ impl<T: PartialEq> PartialEq for Foo<T> { Supported traits for `deriving` are: * Comparison traits: `PartialEq`, `Eq`, `PartialOrd`, `Ord`. -* Serialization: `Encodable`, `Decodable`. These require `serialize`. -* `Clone`, to create `T` from `&T` via a copy. +* Serialization: `RustcEncodable`, `RustcDecodable`. These require `serialize`. +* `Clone`, to create `T` from `&T` via cloning its contents. +* `Copy`, to indicate that this type is allowed to be copied bitwise (if + safe). +* `Sync`, to indicate that this type is safe to use concurrently. +* `Send`, to indicate that this type * `Default`, to create an empty instance of a data type. * `FromPrimitive`, to create an instance from a numeric primitive. * `Hash`, to iterate over the bytes in a data type. @@ -2445,6 +2449,14 @@ Supported traits for `deriving` are: * `Show`, to format a value using the `{}` formatter. * `Zero`, to create a zero instance of a numeric data type. +Each derived trait can have attributes applied to the generated `impl`, such +as: + +``` +#[deriving(Clone(attributes(cfg(not(windows)), unstable)))] +struct X +``` + ### Stability One can indicate the stability of an API using the following attributes: @@ -4149,11 +4161,11 @@ Unwinding the stack of a thread is done by the thread itself, on its own control stack. If a value with a destructor is freed during unwinding, the code for the destructor is run, also on the thread's control stack. Running the destructor code causes a temporary transition to a *running* state, and allows the -destructor code to cause any subsequent state transitions. The original thread +destructor code to cause any subsequent state transitions. The original thread of unwinding and panicking thereby may suspend temporarily, and may involve (recursive) unwinding of the stack of a failed destructor. Nonetheless, the outermost unwinding activity will continue until the stack is unwound and the -thread transitions to the *dead* state. There is no way to "recover" from thread +thread transitions to the *dead* state. There is no way to "recover" from thread panics. Once a thread has temporarily suspended its unwinding in the *panicking* state, a panic occurring from within this destructor results in *hard* panic. A hard panic currently results in the process aborting. diff --git a/src/libsyntax/ext/deriving/bounds.rs b/src/libsyntax/ext/deriving/bounds.rs index cf29bb048d64..eb832b0967d0 100644 --- a/src/libsyntax/ext/deriving/bounds.rs +++ b/src/libsyntax/ext/deriving/bounds.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use ast::{MetaItem, MetaWord, Item}; +use ast::{MetaItem, MetaWord, MetaList, Item}; use codemap::Span; use ext::base::ExtCtxt; use ext::deriving::generic::*; @@ -23,7 +23,8 @@ pub fn expand_deriving_bound<F>(cx: &mut ExtCtxt, F: FnOnce(P<Item>), { let name = match mitem.node { - MetaWord(ref tname) => { + MetaWord(ref tname) | + MetaList(ref tname, _) => { match tname.get() { "Copy" => "Copy", "Send" | "Sync" => { diff --git a/src/libsyntax/ext/deriving/mod.rs b/src/libsyntax/ext/deriving/mod.rs index 75f763b5c38e..8fb73f3eedba 100644 --- a/src/libsyntax/ext/deriving/mod.rs +++ b/src/libsyntax/ext/deriving/mod.rs @@ -13,9 +13,10 @@ //! FIXME (#2810): hygiene. Search for "__" strings (in other files too). We also assume "extra" is //! the standard library, and "std" is the core library. -use ast::{Item, MetaItem, MetaList, MetaNameValue, MetaWord}; +use attr::{mk_attr_id, AttrMetaMethods}; +use ast::{AttrStyle, Attribute_, Item, MetaItem, MetaList, MetaNameValue, MetaWord}; use ext::base::ExtCtxt; -use codemap::Span; +use codemap::{Span, Spanned}; use ptr::P; pub mod bounds; @@ -58,14 +59,59 @@ pub fn expand_meta_deriving(cx: &mut ExtCtxt, } MetaList(_, ref titems) => { for titem in titems.iter().rev() { + let mut attrs = Vec::new(); + match titem.node { + MetaNameValue(_, _) | + MetaWord(_) => { } + MetaList(_, ref alist) => { + if alist.len() != 1 { + cx.span_err(titem.span, "unexpected syntax in `deriving`") + } else { + let alist = &alist[0]; + if alist.name().get() == "attributes" { + match alist.meta_item_list() { + None => cx.span_err(alist.span, + "unexpected syntax in `deriving`"), + Some(metas) => { + for meta in metas.iter() { + attrs.push(Spanned { + span: meta.span, + node: Attribute_ { + id: mk_attr_id(), + style: AttrStyle::AttrOuter, + value: meta.clone() /* bad clone */, + is_sugared_doc: false + } + }); + } + } + } + } + } + } + } + + // so we don't need to clone in the closure below. we also can't move, + // unfortunately, since it would capture the outer `push` as well. + let mut attrs = Some(attrs); + match titem.node { MetaNameValue(ref tname, _) | MetaList(ref tname, _) | MetaWord(ref tname) => { - macro_rules! expand(($func:path) => ($func(cx, titem.span, - &**titem, item, - |i| push.call_mut((i,))))); + // note: for the unwrap to succeed, this macro can't be evaluated more than + // once in any control flow branch. don't use it twice in a match arm + // below! + macro_rules! expand( + ($func:path) => + ($func(cx, titem.span, &**titem, item, + |i| push.call_mut((i.map(|mut i| { + i.attrs.extend(attrs.take().unwrap().into_iter()); + i + }),))))); match tname.get() { + // if you change this list without updating reference.md, cmr will be + // sad "Clone" => expand!(clone::expand_deriving_clone), "Hash" => expand!(hash::expand_deriving_hash), diff --git a/src/test/run-pass/deriving-add-attributes.rs b/src/test/run-pass/deriving-add-attributes.rs new file mode 100644 index 000000000000..fec9aa0c7424 --- /dev/null +++ b/src/test/run-pass/deriving-add-attributes.rs @@ -0,0 +1,14 @@ +// Copyright 2014 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(Copy(attributes(stable)), Clone(attributes(unstable)))] +struct X; + +fn main() {}