rust/src/libsyntax/ext/deriving/mod.rs

153 lines
5.6 KiB
Rust
Raw Normal View History

// Copyright 2012-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.
//! The compiler code necessary to implement the `#[derive]` extensions.
//!
//! FIXME (#2810): hygiene. Search for "__" strings (in other files too). We also assume "extra" is
//! the standard library, and "std" is the core library.
2014-02-05 14:08:17 +00:00
use ast::{Item, MetaItem, MetaList, MetaNameValue, MetaWord};
use ext::base::ExtCtxt;
use codemap::Span;
2014-09-13 16:06:01 +00:00
use ptr::P;
2014-05-16 07:16:13 +00:00
2014-09-07 20:58:41 +00:00
macro_rules! pathvec {
($($x:ident)::+) => (
vec![ $( stringify!($x) ),+ ]
)
}
macro_rules! path {
($($x:tt)*) => (
::ext::deriving::generic::ty::Path::new( pathvec!( $($x)* ) )
)
}
pub mod bounds;
pub mod clone;
pub mod encodable;
pub mod decodable;
pub mod hash;
pub mod rand;
2014-02-06 12:02:28 +00:00
pub mod show;
pub mod default;
pub mod primitive;
#[path="cmp/eq.rs"]
pub mod eq;
#[path="cmp/totaleq.rs"]
pub mod totaleq;
#[path="cmp/ord.rs"]
pub mod ord;
#[path="cmp/totalord.rs"]
pub mod totalord;
pub mod generic;
pub fn expand_deprecated_deriving(cx: &mut ExtCtxt,
span: Span,
_: &MetaItem,
_: &Item,
_: Box<FnMut(P<Item>)>) {
cx.span_err(span, "`deriving` has been renamed to `derive`");
}
pub fn expand_meta_derive(cx: &mut ExtCtxt,
_span: Span,
mitem: &MetaItem,
item: &Item,
mut push: Box<FnMut(P<Item>)>) {
match mitem.node {
MetaNameValue(_, ref l) => {
cx.span_err(l.span, "unexpected value in `derive`");
}
MetaWord(_) => {
cx.span_warn(mitem.span, "empty trait list in `derive`");
}
MetaList(_, ref titems) if titems.len() == 0 => {
cx.span_warn(mitem.span, "empty trait list in `derive`");
}
MetaList(_, ref titems) => {
2014-09-13 16:06:01 +00:00
for titem in titems.iter().rev() {
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(i)))
}
2015-02-03 22:31:06 +00:00
match &tname[] {
"Clone" => expand!(clone::expand_deriving_clone),
"Hash" => expand!(hash::expand_deriving_hash),
rustc: Start the deprecation of libserialize The primary focus of Rust's stability story at 1.0 is the standard library. All other libraries distributed with the Rust compiler are planned to be #[unstable] and therfore only accessible on the nightly channel of Rust. One of the more widely used libraries today is libserialize, Rust's current solution for encoding and decoding types. The current libserialize library, however, has a number of drawbacks: * The API is not ready to be stabilize as-is and we will likely not have enough resources to stabilize the API for 1.0. * The library is not necessarily the speediest implementations with alternatives being developed out-of-tree (e.g. serde from erickt). * It is not clear how the API of Encodable/Decodable can evolve over time while maintaining backwards compatibility. One of the major pros to the current libserialize, however, is `deriving(Encodable, Decodable)` as short-hands for enabling serializing and deserializing a type. This is unambiguously useful functionality, so we cannot simply deprecate the in-tree libserialize in favor of an external crates.io implementation. For these reasons, this commit starts off a stability story for libserialize by following these steps: 1. The deriving(Encodable, Decodable) modes will be deprecated in favor of a renamed deriving(RustcEncodable, RustcDecodable). 2. The in-tree libserialize will be deprecated in favor of an external rustc-serialize crate shipped on crates.io. The contents of the crate will be the same for now (but they can evolve separately). 3. At 1.0 serialization will be performed through deriving(RustcEncodable, RustcDecodable) and the rustc-serialize crate. The expansions for each deriving mode will change from `::serialize::foo` to `::rustc_serialize::foo`. This story will require that the compiler freezes its implementation of `RustcEncodable` deriving for all of time, but this should be a fairly minimal maintenance burden. Otherwise the crate in crates.io must always maintain the exact definition of its traits, but the implementation of json, for example, can continue to evolve in the semver-sense. The major goal for this stabilization effort is to pave the road for a new official serialization crate which can replace the current one, solving many of its downsides in the process. We are not assuming that this will exist for 1.0, hence the above measures. Some possibilities for replacing libserialize include: * If plugins have a stable API, then any crate can provide a custom `deriving` mode (will require some compiler work). This means that any new serialization crate can provide its own `deriving` with its own backing implementation, entirely obsoleting the current libserialize and fully replacing it. * Erick is exploring the possibility of code generation via preprocessing Rust source files in the near term until plugins are stable. This strategy would provide the same ergonomic benefit that `deriving` does today in theory. So, in summary, the current libserialize crate is being deprecated in favor of the crates.io-based rustc-serialize crate where the `deriving` modes are appropriately renamed. This opens up space for a later implementation of serialization in a more official capacity while allowing alternative implementations to be explored in the meantime. Concretely speaking, this change adds support for the `RustcEncodable` and `RustcDecodable` deriving modes. After a snapshot is made warnings will be turned on for usage of `Encodable` and `Decodable` as well as deprecating the in-tree libserialize crate to encurage users to use rustc-serialize instead.
2014-12-11 20:16:30 +00:00
"RustcEncodable" => {
expand!(encodable::expand_deriving_rustc_encodable)
rustc: Start the deprecation of libserialize The primary focus of Rust's stability story at 1.0 is the standard library. All other libraries distributed with the Rust compiler are planned to be #[unstable] and therfore only accessible on the nightly channel of Rust. One of the more widely used libraries today is libserialize, Rust's current solution for encoding and decoding types. The current libserialize library, however, has a number of drawbacks: * The API is not ready to be stabilize as-is and we will likely not have enough resources to stabilize the API for 1.0. * The library is not necessarily the speediest implementations with alternatives being developed out-of-tree (e.g. serde from erickt). * It is not clear how the API of Encodable/Decodable can evolve over time while maintaining backwards compatibility. One of the major pros to the current libserialize, however, is `deriving(Encodable, Decodable)` as short-hands for enabling serializing and deserializing a type. This is unambiguously useful functionality, so we cannot simply deprecate the in-tree libserialize in favor of an external crates.io implementation. For these reasons, this commit starts off a stability story for libserialize by following these steps: 1. The deriving(Encodable, Decodable) modes will be deprecated in favor of a renamed deriving(RustcEncodable, RustcDecodable). 2. The in-tree libserialize will be deprecated in favor of an external rustc-serialize crate shipped on crates.io. The contents of the crate will be the same for now (but they can evolve separately). 3. At 1.0 serialization will be performed through deriving(RustcEncodable, RustcDecodable) and the rustc-serialize crate. The expansions for each deriving mode will change from `::serialize::foo` to `::rustc_serialize::foo`. This story will require that the compiler freezes its implementation of `RustcEncodable` deriving for all of time, but this should be a fairly minimal maintenance burden. Otherwise the crate in crates.io must always maintain the exact definition of its traits, but the implementation of json, for example, can continue to evolve in the semver-sense. The major goal for this stabilization effort is to pave the road for a new official serialization crate which can replace the current one, solving many of its downsides in the process. We are not assuming that this will exist for 1.0, hence the above measures. Some possibilities for replacing libserialize include: * If plugins have a stable API, then any crate can provide a custom `deriving` mode (will require some compiler work). This means that any new serialization crate can provide its own `deriving` with its own backing implementation, entirely obsoleting the current libserialize and fully replacing it. * Erick is exploring the possibility of code generation via preprocessing Rust source files in the near term until plugins are stable. This strategy would provide the same ergonomic benefit that `deriving` does today in theory. So, in summary, the current libserialize crate is being deprecated in favor of the crates.io-based rustc-serialize crate where the `deriving` modes are appropriately renamed. This opens up space for a later implementation of serialization in a more official capacity while allowing alternative implementations to be explored in the meantime. Concretely speaking, this change adds support for the `RustcEncodable` and `RustcDecodable` deriving modes. After a snapshot is made warnings will be turned on for usage of `Encodable` and `Decodable` as well as deprecating the in-tree libserialize crate to encurage users to use rustc-serialize instead.
2014-12-11 20:16:30 +00:00
}
"RustcDecodable" => {
expand!(decodable::expand_deriving_rustc_decodable)
rustc: Start the deprecation of libserialize The primary focus of Rust's stability story at 1.0 is the standard library. All other libraries distributed with the Rust compiler are planned to be #[unstable] and therfore only accessible on the nightly channel of Rust. One of the more widely used libraries today is libserialize, Rust's current solution for encoding and decoding types. The current libserialize library, however, has a number of drawbacks: * The API is not ready to be stabilize as-is and we will likely not have enough resources to stabilize the API for 1.0. * The library is not necessarily the speediest implementations with alternatives being developed out-of-tree (e.g. serde from erickt). * It is not clear how the API of Encodable/Decodable can evolve over time while maintaining backwards compatibility. One of the major pros to the current libserialize, however, is `deriving(Encodable, Decodable)` as short-hands for enabling serializing and deserializing a type. This is unambiguously useful functionality, so we cannot simply deprecate the in-tree libserialize in favor of an external crates.io implementation. For these reasons, this commit starts off a stability story for libserialize by following these steps: 1. The deriving(Encodable, Decodable) modes will be deprecated in favor of a renamed deriving(RustcEncodable, RustcDecodable). 2. The in-tree libserialize will be deprecated in favor of an external rustc-serialize crate shipped on crates.io. The contents of the crate will be the same for now (but they can evolve separately). 3. At 1.0 serialization will be performed through deriving(RustcEncodable, RustcDecodable) and the rustc-serialize crate. The expansions for each deriving mode will change from `::serialize::foo` to `::rustc_serialize::foo`. This story will require that the compiler freezes its implementation of `RustcEncodable` deriving for all of time, but this should be a fairly minimal maintenance burden. Otherwise the crate in crates.io must always maintain the exact definition of its traits, but the implementation of json, for example, can continue to evolve in the semver-sense. The major goal for this stabilization effort is to pave the road for a new official serialization crate which can replace the current one, solving many of its downsides in the process. We are not assuming that this will exist for 1.0, hence the above measures. Some possibilities for replacing libserialize include: * If plugins have a stable API, then any crate can provide a custom `deriving` mode (will require some compiler work). This means that any new serialization crate can provide its own `deriving` with its own backing implementation, entirely obsoleting the current libserialize and fully replacing it. * Erick is exploring the possibility of code generation via preprocessing Rust source files in the near term until plugins are stable. This strategy would provide the same ergonomic benefit that `deriving` does today in theory. So, in summary, the current libserialize crate is being deprecated in favor of the crates.io-based rustc-serialize crate where the `deriving` modes are appropriately renamed. This opens up space for a later implementation of serialization in a more official capacity while allowing alternative implementations to be explored in the meantime. Concretely speaking, this change adds support for the `RustcEncodable` and `RustcDecodable` deriving modes. After a snapshot is made warnings will be turned on for usage of `Encodable` and `Decodable` as well as deprecating the in-tree libserialize crate to encurage users to use rustc-serialize instead.
2014-12-11 20:16:30 +00:00
}
"Encodable" => {
cx.span_warn(titem.span,
"derive(Encodable) is deprecated \
in favor of derive(RustcEncodable)");
rustc: Start the deprecation of libserialize The primary focus of Rust's stability story at 1.0 is the standard library. All other libraries distributed with the Rust compiler are planned to be #[unstable] and therfore only accessible on the nightly channel of Rust. One of the more widely used libraries today is libserialize, Rust's current solution for encoding and decoding types. The current libserialize library, however, has a number of drawbacks: * The API is not ready to be stabilize as-is and we will likely not have enough resources to stabilize the API for 1.0. * The library is not necessarily the speediest implementations with alternatives being developed out-of-tree (e.g. serde from erickt). * It is not clear how the API of Encodable/Decodable can evolve over time while maintaining backwards compatibility. One of the major pros to the current libserialize, however, is `deriving(Encodable, Decodable)` as short-hands for enabling serializing and deserializing a type. This is unambiguously useful functionality, so we cannot simply deprecate the in-tree libserialize in favor of an external crates.io implementation. For these reasons, this commit starts off a stability story for libserialize by following these steps: 1. The deriving(Encodable, Decodable) modes will be deprecated in favor of a renamed deriving(RustcEncodable, RustcDecodable). 2. The in-tree libserialize will be deprecated in favor of an external rustc-serialize crate shipped on crates.io. The contents of the crate will be the same for now (but they can evolve separately). 3. At 1.0 serialization will be performed through deriving(RustcEncodable, RustcDecodable) and the rustc-serialize crate. The expansions for each deriving mode will change from `::serialize::foo` to `::rustc_serialize::foo`. This story will require that the compiler freezes its implementation of `RustcEncodable` deriving for all of time, but this should be a fairly minimal maintenance burden. Otherwise the crate in crates.io must always maintain the exact definition of its traits, but the implementation of json, for example, can continue to evolve in the semver-sense. The major goal for this stabilization effort is to pave the road for a new official serialization crate which can replace the current one, solving many of its downsides in the process. We are not assuming that this will exist for 1.0, hence the above measures. Some possibilities for replacing libserialize include: * If plugins have a stable API, then any crate can provide a custom `deriving` mode (will require some compiler work). This means that any new serialization crate can provide its own `deriving` with its own backing implementation, entirely obsoleting the current libserialize and fully replacing it. * Erick is exploring the possibility of code generation via preprocessing Rust source files in the near term until plugins are stable. This strategy would provide the same ergonomic benefit that `deriving` does today in theory. So, in summary, the current libserialize crate is being deprecated in favor of the crates.io-based rustc-serialize crate where the `deriving` modes are appropriately renamed. This opens up space for a later implementation of serialization in a more official capacity while allowing alternative implementations to be explored in the meantime. Concretely speaking, this change adds support for the `RustcEncodable` and `RustcDecodable` deriving modes. After a snapshot is made warnings will be turned on for usage of `Encodable` and `Decodable` as well as deprecating the in-tree libserialize crate to encurage users to use rustc-serialize instead.
2014-12-11 20:16:30 +00:00
expand!(encodable::expand_deriving_encodable)
}
2014-12-17 19:26:52 +00:00
"Decodable" => {
cx.span_warn(titem.span,
"derive(Decodable) is deprecated \
in favor of derive(RustcDecodable)");
rustc: Start the deprecation of libserialize The primary focus of Rust's stability story at 1.0 is the standard library. All other libraries distributed with the Rust compiler are planned to be #[unstable] and therfore only accessible on the nightly channel of Rust. One of the more widely used libraries today is libserialize, Rust's current solution for encoding and decoding types. The current libserialize library, however, has a number of drawbacks: * The API is not ready to be stabilize as-is and we will likely not have enough resources to stabilize the API for 1.0. * The library is not necessarily the speediest implementations with alternatives being developed out-of-tree (e.g. serde from erickt). * It is not clear how the API of Encodable/Decodable can evolve over time while maintaining backwards compatibility. One of the major pros to the current libserialize, however, is `deriving(Encodable, Decodable)` as short-hands for enabling serializing and deserializing a type. This is unambiguously useful functionality, so we cannot simply deprecate the in-tree libserialize in favor of an external crates.io implementation. For these reasons, this commit starts off a stability story for libserialize by following these steps: 1. The deriving(Encodable, Decodable) modes will be deprecated in favor of a renamed deriving(RustcEncodable, RustcDecodable). 2. The in-tree libserialize will be deprecated in favor of an external rustc-serialize crate shipped on crates.io. The contents of the crate will be the same for now (but they can evolve separately). 3. At 1.0 serialization will be performed through deriving(RustcEncodable, RustcDecodable) and the rustc-serialize crate. The expansions for each deriving mode will change from `::serialize::foo` to `::rustc_serialize::foo`. This story will require that the compiler freezes its implementation of `RustcEncodable` deriving for all of time, but this should be a fairly minimal maintenance burden. Otherwise the crate in crates.io must always maintain the exact definition of its traits, but the implementation of json, for example, can continue to evolve in the semver-sense. The major goal for this stabilization effort is to pave the road for a new official serialization crate which can replace the current one, solving many of its downsides in the process. We are not assuming that this will exist for 1.0, hence the above measures. Some possibilities for replacing libserialize include: * If plugins have a stable API, then any crate can provide a custom `deriving` mode (will require some compiler work). This means that any new serialization crate can provide its own `deriving` with its own backing implementation, entirely obsoleting the current libserialize and fully replacing it. * Erick is exploring the possibility of code generation via preprocessing Rust source files in the near term until plugins are stable. This strategy would provide the same ergonomic benefit that `deriving` does today in theory. So, in summary, the current libserialize crate is being deprecated in favor of the crates.io-based rustc-serialize crate where the `deriving` modes are appropriately renamed. This opens up space for a later implementation of serialization in a more official capacity while allowing alternative implementations to be explored in the meantime. Concretely speaking, this change adds support for the `RustcEncodable` and `RustcDecodable` deriving modes. After a snapshot is made warnings will be turned on for usage of `Encodable` and `Decodable` as well as deprecating the in-tree libserialize crate to encurage users to use rustc-serialize instead.
2014-12-11 20:16:30 +00:00
expand!(decodable::expand_deriving_decodable)
}
"PartialEq" => expand!(eq::expand_deriving_eq),
"Eq" => expand!(totaleq::expand_deriving_totaleq),
"PartialOrd" => expand!(ord::expand_deriving_ord),
"Ord" => expand!(totalord::expand_deriving_totalord),
"Rand" => expand!(rand::expand_deriving_rand),
"Show" => {
cx.span_warn(titem.span,
"derive(Show) is deprecated \
in favor of derive(Debug)");
expand!(show::expand_deriving_show)
},
std: Rename Show/String to Debug/Display This commit is an implementation of [RFC 565][rfc] which is a stabilization of the `std::fmt` module and the implementations of various formatting traits. Specifically, the following changes were performed: [rfc]: https://github.com/rust-lang/rfcs/blob/master/text/0565-show-string-guidelines.md * The `Show` trait is now deprecated, it was renamed to `Debug` * The `String` trait is now deprecated, it was renamed to `Display` * Many `Debug` and `Display` implementations were audited in accordance with the RFC and audited implementations now have the `#[stable]` attribute * Integers and floats no longer print a suffix * Smart pointers no longer print details that they are a smart pointer * Paths with `Debug` are now quoted and escape characters * The `unwrap` methods on `Result` now require `Display` instead of `Debug` * The `Error` trait no longer has a `detail` method and now requires that `Display` must be implemented. With the loss of `String`, this has moved into libcore. * `impl<E: Error> FromError<E> for Box<Error>` now exists * `derive(Show)` has been renamed to `derive(Debug)`. This is not currently warned about due to warnings being emitted on stage1+ While backwards compatibility is attempted to be maintained with a blanket implementation of `Display` for the old `String` trait (and the same for `Show`/`Debug`) this is still a breaking change due to primitives no longer implementing `String` as well as modifications such as `unwrap` and the `Error` trait. Most code is fairly straightforward to update with a rename or tweaks of method calls. [breaking-change] Closes #21436
2015-01-20 23:45:07 +00:00
"Debug" => expand!(show::expand_deriving_show),
"Default" => expand!(default::expand_deriving_default),
"FromPrimitive" => expand!(primitive::expand_deriving_from_primitive),
"Send" => expand!(bounds::expand_deriving_bound),
"Sync" => expand!(bounds::expand_deriving_bound),
"Copy" => expand!(bounds::expand_deriving_bound),
ref tname => {
cx.span_err(titem.span,
2015-01-07 16:58:31 +00:00
&format!("unknown `derive` \
trait: `{}`",
2015-01-07 16:58:31 +00:00
*tname)[]);
}
};
}
}
}
}
}
}