Make #[derive(Anything)] into sugar for #[derive_Anything]
This is a hack, but I don't think we can do much better as long as `derive` is running at the syntax expansion phase. If the custom_derive feature gate is enabled, this works with user-defined traits and syntax extensions. Without the gate, you can't use e.g. #[derive_Clone] directly, so this does not change the stable language. This commit also cleans up the deriving code somewhat, and forbids some previously-meaningless attribute syntax. For this reason it's technically a [breaking-change]
This commit is contained in:
parent
e60e6f0693
commit
491054f08e
src
doc
libsyntax
test
@ -2429,6 +2429,10 @@ The currently implemented features of the reference compiler are:
|
||||
so that new attributes can be added in a bacwards compatible
|
||||
manner (RFC 572).
|
||||
|
||||
* `custom_derive` - Allows the use of `#[derive(Foo,Bar)]` as sugar for
|
||||
`#[derive_Foo] #[derive_Bar]`, which can be user-defined syntax
|
||||
extensions.
|
||||
|
||||
* `intrinsics` - Allows use of the "rust-intrinsics" ABI. Compiler intrinsics
|
||||
are inherently unstable and no promise about them is made.
|
||||
|
||||
|
@ -491,10 +491,8 @@ fn initial_syntax_expander_table<'feat>(ecfg: &expand::ExpansionConfig<'feat>)
|
||||
syntax_expanders.insert(intern("log_syntax"),
|
||||
builtin_normal_expander(
|
||||
ext::log_syntax::expand_syntax_ext));
|
||||
syntax_expanders.insert(intern("derive"),
|
||||
Decorator(Box::new(ext::deriving::expand_meta_derive)));
|
||||
syntax_expanders.insert(intern("deriving"),
|
||||
Decorator(Box::new(ext::deriving::expand_deprecated_deriving)));
|
||||
|
||||
ext::deriving::register_all(&mut syntax_expanders);
|
||||
|
||||
if ecfg.enable_quotes() {
|
||||
// Quasi-quoting expanders
|
||||
|
@ -8,47 +8,34 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use ast::{MetaItem, MetaWord, Item};
|
||||
use ast::{MetaItem, Item};
|
||||
use codemap::Span;
|
||||
use ext::base::ExtCtxt;
|
||||
use ext::deriving::generic::*;
|
||||
use ext::deriving::generic::ty::*;
|
||||
use ptr::P;
|
||||
|
||||
pub fn expand_deriving_bound<F>(cx: &mut ExtCtxt,
|
||||
span: Span,
|
||||
mitem: &MetaItem,
|
||||
item: &Item,
|
||||
push: F) where
|
||||
pub fn expand_deriving_unsafe_bound<F>(cx: &mut ExtCtxt,
|
||||
span: Span,
|
||||
_: &MetaItem,
|
||||
_: &Item,
|
||||
_: F) where
|
||||
F: FnOnce(P<Item>),
|
||||
{
|
||||
let name = match mitem.node {
|
||||
MetaWord(ref tname) => {
|
||||
match &tname[..] {
|
||||
"Copy" => "Copy",
|
||||
"Send" | "Sync" => {
|
||||
return cx.span_err(span,
|
||||
&format!("{} is an unsafe trait and it \
|
||||
should be implemented explicitly",
|
||||
*tname))
|
||||
}
|
||||
ref tname => {
|
||||
cx.span_bug(span,
|
||||
&format!("expected built-in trait name but \
|
||||
found {}", *tname))
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
return cx.span_err(span, "unexpected value in deriving, expected \
|
||||
a trait")
|
||||
}
|
||||
};
|
||||
cx.span_err(span, "this unsafe trait should be implemented explicitly");
|
||||
}
|
||||
|
||||
pub fn expand_deriving_copy<F>(cx: &mut ExtCtxt,
|
||||
span: Span,
|
||||
mitem: &MetaItem,
|
||||
item: &Item,
|
||||
push: F) where
|
||||
F: FnOnce(P<Item>),
|
||||
{
|
||||
let path = Path::new(vec![
|
||||
if cx.use_std { "std" } else { "core" },
|
||||
"marker",
|
||||
name
|
||||
"Copy",
|
||||
]);
|
||||
|
||||
let trait_def = TraitDef {
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
|
||||
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
@ -13,9 +13,13 @@
|
||||
//! 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 ext::base::ExtCtxt;
|
||||
use ast::{Item, MetaItem, MetaWord};
|
||||
use attr::AttrMetaMethods;
|
||||
use ext::base::{ExtCtxt, SyntaxEnv, Decorator, ItemDecorator, Modifier};
|
||||
use ext::build::AstBuilder;
|
||||
use feature_gate;
|
||||
use codemap::Span;
|
||||
use parse::token::{intern, intern_and_get_ident};
|
||||
use ptr::P;
|
||||
|
||||
macro_rules! pathvec {
|
||||
@ -74,101 +78,133 @@ pub mod totalord;
|
||||
|
||||
pub mod generic;
|
||||
|
||||
pub fn expand_deprecated_deriving(cx: &mut ExtCtxt,
|
||||
span: Span,
|
||||
_: &MetaItem,
|
||||
_: &Item,
|
||||
_: &mut FnMut(P<Item>)) {
|
||||
fn expand_deprecated_deriving(cx: &mut ExtCtxt,
|
||||
span: Span,
|
||||
_: &MetaItem,
|
||||
_: &Item,
|
||||
_: &mut 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,
|
||||
push: &mut FnMut(P<Item>)) {
|
||||
match mitem.node {
|
||||
MetaNameValue(_, ref l) => {
|
||||
cx.span_err(l.span, "unexpected value in `derive`");
|
||||
fn expand_derive(cx: &mut ExtCtxt,
|
||||
_: Span,
|
||||
mitem: &MetaItem,
|
||||
item: P<Item>) -> P<Item> {
|
||||
item.map(|mut item| {
|
||||
if mitem.value_str().is_some() {
|
||||
cx.span_err(mitem.span, "unexpected value in `derive`");
|
||||
}
|
||||
MetaWord(_) => {
|
||||
|
||||
let traits = mitem.meta_item_list().unwrap_or(&[]);
|
||||
if traits.is_empty() {
|
||||
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`");
|
||||
|
||||
for titem in traits.iter().rev() {
|
||||
let tname = match titem.node {
|
||||
MetaWord(ref tname) => tname,
|
||||
_ => {
|
||||
cx.span_err(titem.span, "malformed `derive` entry");
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
if !(is_builtin_trait(tname) || cx.ecfg.enable_custom_derive()) {
|
||||
feature_gate::emit_feature_err(&cx.parse_sess.span_diagnostic,
|
||||
"custom_derive",
|
||||
titem.span,
|
||||
feature_gate::EXPLAIN_CUSTOM_DERIVE);
|
||||
continue;
|
||||
}
|
||||
|
||||
// #[derive(Foo, Bar)] expands to #[derive_Foo] #[derive_Bar]
|
||||
item.attrs.push(cx.attribute(titem.span, cx.meta_word(titem.span,
|
||||
intern_and_get_ident(&format!("derive_{}", tname)))));
|
||||
}
|
||||
MetaList(_, ref titems) => {
|
||||
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)))
|
||||
}
|
||||
|
||||
match &tname[..] {
|
||||
"Clone" => expand!(clone::expand_deriving_clone),
|
||||
item
|
||||
})
|
||||
}
|
||||
|
||||
"Hash" => expand!(hash::expand_deriving_hash),
|
||||
macro_rules! derive_traits {
|
||||
($( $name:expr => $func:path, )*) => {
|
||||
pub fn register_all(env: &mut SyntaxEnv) {
|
||||
// Define the #[derive_*] extensions.
|
||||
$({
|
||||
struct DeriveExtension;
|
||||
|
||||
"RustcEncodable" => {
|
||||
expand!(encodable::expand_deriving_rustc_encodable)
|
||||
}
|
||||
"RustcDecodable" => {
|
||||
expand!(decodable::expand_deriving_rustc_decodable)
|
||||
}
|
||||
"Encodable" => {
|
||||
cx.span_warn(titem.span,
|
||||
"derive(Encodable) is deprecated \
|
||||
in favor of derive(RustcEncodable)");
|
||||
|
||||
expand!(encodable::expand_deriving_encodable)
|
||||
}
|
||||
"Decodable" => {
|
||||
cx.span_warn(titem.span,
|
||||
"derive(Decodable) is deprecated \
|
||||
in favor of derive(RustcDecodable)");
|
||||
|
||||
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)
|
||||
},
|
||||
|
||||
"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,
|
||||
&format!("unknown `derive` \
|
||||
trait: `{}`",
|
||||
*tname));
|
||||
}
|
||||
};
|
||||
impl ItemDecorator for DeriveExtension {
|
||||
fn expand(&self,
|
||||
ecx: &mut ExtCtxt,
|
||||
sp: Span,
|
||||
mitem: &MetaItem,
|
||||
item: &Item,
|
||||
push: &mut FnMut(P<Item>)) {
|
||||
warn_if_deprecated(ecx, sp, $name);
|
||||
$func(ecx, sp, mitem, item, |i| push(i));
|
||||
}
|
||||
}
|
||||
|
||||
env.insert(intern(concat!("derive_", $name)),
|
||||
Decorator(Box::new(DeriveExtension)));
|
||||
})*
|
||||
|
||||
env.insert(intern("derive"),
|
||||
Modifier(Box::new(expand_derive)));
|
||||
env.insert(intern("deriving"),
|
||||
Decorator(Box::new(expand_deprecated_deriving)));
|
||||
}
|
||||
|
||||
fn is_builtin_trait(name: &str) -> bool {
|
||||
match name {
|
||||
$( $name )|* => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
derive_traits! {
|
||||
"Clone" => clone::expand_deriving_clone,
|
||||
|
||||
"Hash" => hash::expand_deriving_hash,
|
||||
|
||||
"RustcEncodable" => encodable::expand_deriving_rustc_encodable,
|
||||
|
||||
"RustcDecodable" => decodable::expand_deriving_rustc_decodable,
|
||||
|
||||
"PartialEq" => eq::expand_deriving_eq,
|
||||
"Eq" => totaleq::expand_deriving_totaleq,
|
||||
"PartialOrd" => ord::expand_deriving_ord,
|
||||
"Ord" => totalord::expand_deriving_totalord,
|
||||
|
||||
"Rand" => rand::expand_deriving_rand,
|
||||
|
||||
"Debug" => show::expand_deriving_show,
|
||||
|
||||
"Default" => default::expand_deriving_default,
|
||||
|
||||
"FromPrimitive" => primitive::expand_deriving_from_primitive,
|
||||
|
||||
"Send" => bounds::expand_deriving_unsafe_bound,
|
||||
"Sync" => bounds::expand_deriving_unsafe_bound,
|
||||
"Copy" => bounds::expand_deriving_copy,
|
||||
|
||||
// deprecated
|
||||
"Show" => show::expand_deriving_show,
|
||||
"Encodable" => encodable::expand_deriving_encodable,
|
||||
"Decodable" => decodable::expand_deriving_decodable,
|
||||
}
|
||||
|
||||
#[inline] // because `name` is a compile-time constant
|
||||
fn warn_if_deprecated(ecx: &mut ExtCtxt, sp: Span, name: &str) {
|
||||
if let Some(replacement) = match name {
|
||||
"Show" => Some("Debug"),
|
||||
"Encodable" => Some("RustcEncodable"),
|
||||
"Decodable" => Some("RustcDecodable"),
|
||||
_ => None,
|
||||
} {
|
||||
ecx.span_warn(sp, &format!("derive({}) is deprecated in favor of derive({})",
|
||||
name, replacement));
|
||||
}
|
||||
}
|
||||
|
@ -1476,6 +1476,7 @@ impl<'feat> ExpansionConfig<'feat> {
|
||||
fn enable_concat_idents = allow_concat_idents,
|
||||
fn enable_trace_macros = allow_trace_macros,
|
||||
fn enable_allow_internal_unstable = allow_internal_unstable,
|
||||
fn enable_custom_derive = allow_custom_derive,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -137,6 +137,10 @@ const KNOWN_FEATURES: &'static [(&'static str, &'static str, Status)] = &[
|
||||
// Allows the use of custom attributes; RFC 572
|
||||
("custom_attribute", "1.0.0", Active),
|
||||
|
||||
// Allows the use of #[derive(Anything)] as sugar for
|
||||
// #[derive_Anything].
|
||||
("custom_derive", "1.0.0", Active),
|
||||
|
||||
// Allows the use of rustc_* attributes; RFC 572
|
||||
("rustc_attrs", "1.0.0", Active),
|
||||
|
||||
@ -319,6 +323,7 @@ pub struct Features {
|
||||
pub allow_concat_idents: bool,
|
||||
pub allow_trace_macros: bool,
|
||||
pub allow_internal_unstable: bool,
|
||||
pub allow_custom_derive: bool,
|
||||
pub old_orphan_check: bool,
|
||||
pub simd_ffi: bool,
|
||||
pub unmarked_api: bool,
|
||||
@ -340,6 +345,7 @@ impl Features {
|
||||
allow_concat_idents: false,
|
||||
allow_trace_macros: false,
|
||||
allow_internal_unstable: false,
|
||||
allow_custom_derive: false,
|
||||
old_orphan_check: false,
|
||||
simd_ffi: false,
|
||||
unmarked_api: false,
|
||||
@ -391,6 +397,10 @@ impl<'a> Context<'a> {
|
||||
"unless otherwise specified, attributes \
|
||||
with the prefix `rustc_` \
|
||||
are reserved for internal compiler diagnostics");
|
||||
} else if name.starts_with("derive_") {
|
||||
self.gate_feature("custom_derive", attr.span,
|
||||
"attributes of the form `#[derive_*]` are reserved
|
||||
for the compiler");
|
||||
} else {
|
||||
self.gate_feature("custom_attribute", attr.span,
|
||||
format!("The attribute `{}` is currently \
|
||||
@ -432,6 +442,9 @@ pub const EXPLAIN_TRACE_MACROS: &'static str =
|
||||
pub const EXPLAIN_ALLOW_INTERNAL_UNSTABLE: &'static str =
|
||||
"allow_internal_unstable side-steps feature gating and stability checks";
|
||||
|
||||
pub const EXPLAIN_CUSTOM_DERIVE: &'static str =
|
||||
"`#[derive]` for custom traits is not stable enough for use and is subject to change";
|
||||
|
||||
struct MacroVisitor<'a> {
|
||||
context: &'a Context<'a>
|
||||
}
|
||||
@ -780,6 +793,7 @@ fn check_crate_inner<F>(cm: &CodeMap, span_handler: &SpanHandler, krate: &ast::C
|
||||
allow_concat_idents: cx.has_feature("concat_idents"),
|
||||
allow_trace_macros: cx.has_feature("trace_macros"),
|
||||
allow_internal_unstable: cx.has_feature("allow_internal_unstable"),
|
||||
allow_custom_derive: cx.has_feature("custom_derive"),
|
||||
old_orphan_check: cx.has_feature("old_orphan_check"),
|
||||
simd_ffi: cx.has_feature("simd_ffi"),
|
||||
unmarked_api: cx.has_feature("unmarked_api"),
|
||||
|
74
src/test/auxiliary/custom_derive_plugin.rs
Normal file
74
src/test/auxiliary/custom_derive_plugin.rs
Normal file
@ -0,0 +1,74 @@
|
||||
// Copyright 2015 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.
|
||||
|
||||
// force-host
|
||||
|
||||
#![feature(plugin_registrar)]
|
||||
#![feature(box_syntax)]
|
||||
#![feature(rustc_private)]
|
||||
|
||||
extern crate syntax;
|
||||
extern crate rustc;
|
||||
|
||||
use syntax::ast;
|
||||
use syntax::codemap::Span;
|
||||
use syntax::ext::base::{Decorator, ExtCtxt};
|
||||
use syntax::ext::build::AstBuilder;
|
||||
use syntax::ext::deriving::generic::{cs_fold, TraitDef, MethodDef, combine_substructure};
|
||||
use syntax::ext::deriving::generic::ty::{Literal, LifetimeBounds, Path, borrowed_explicit_self};
|
||||
use syntax::parse::token;
|
||||
use syntax::ptr::P;
|
||||
use rustc::plugin::Registry;
|
||||
|
||||
#[plugin_registrar]
|
||||
pub fn plugin_registrar(reg: &mut Registry) {
|
||||
reg.register_syntax_extension(
|
||||
token::intern("derive_TotalSum"),
|
||||
Decorator(box expand));
|
||||
}
|
||||
|
||||
fn expand(cx: &mut ExtCtxt,
|
||||
span: Span,
|
||||
mitem: &ast::MetaItem,
|
||||
item: &ast::Item,
|
||||
push: &mut FnMut(P<ast::Item>)) {
|
||||
let trait_def = TraitDef {
|
||||
span: span,
|
||||
attributes: vec![],
|
||||
path: Path::new(vec!["TotalSum"]),
|
||||
additional_bounds: vec![],
|
||||
generics: LifetimeBounds::empty(),
|
||||
associated_types: vec![],
|
||||
methods: vec![
|
||||
MethodDef {
|
||||
name: "total_sum",
|
||||
generics: LifetimeBounds::empty(),
|
||||
explicit_self: borrowed_explicit_self(),
|
||||
args: vec![],
|
||||
ret_ty: Literal(Path::new_local("isize")),
|
||||
attributes: vec![],
|
||||
combine_substructure: combine_substructure(box |cx, span, substr| {
|
||||
let zero = cx.expr_int(span, 0);
|
||||
cs_fold(false,
|
||||
|cx, span, subexpr, field, _| {
|
||||
cx.expr_binary(span, ast::BiAdd, subexpr,
|
||||
cx.expr_method_call(span, field,
|
||||
token::str_to_ident("total_sum"), vec![]))
|
||||
},
|
||||
zero,
|
||||
box |cx, span, _, _| { cx.span_bug(span, "wtf??"); },
|
||||
cx, span, substr)
|
||||
}),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
trait_def.expand(cx, mitem, item, |i| push(i))
|
||||
}
|
@ -8,12 +8,12 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#[derive(Copy(Bad))]
|
||||
//~^ ERROR unexpected value in deriving, expected a trait
|
||||
#[derive(Send)]
|
||||
//~^ ERROR this unsafe trait should be implemented explicitly
|
||||
struct Test;
|
||||
|
||||
#[derive(Sync)]
|
||||
//~^ ERROR Sync is an unsafe trait and it should be implemented explicitly
|
||||
//~^ ERROR this unsafe trait should be implemented explicitly
|
||||
struct Test1;
|
||||
|
||||
pub fn main() {}
|
||||
|
@ -8,7 +8,8 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#[derive(Eqr)] //~ ERROR unknown `derive` trait: `Eqr`
|
||||
#[derive(Eqr)]
|
||||
//~^ ERROR `#[derive]` for custom traits is not stable enough for use and is subject to change
|
||||
struct Foo;
|
||||
|
||||
pub fn main() {}
|
||||
|
25
src/test/compile-fail/malformed-derive-entry.rs
Normal file
25
src/test/compile-fail/malformed-derive-entry.rs
Normal file
@ -0,0 +1,25 @@
|
||||
// Copyright 2015 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.
|
||||
|
||||
#[derive(Copy(Bad))]
|
||||
//~^ ERROR malformed `derive` entry
|
||||
struct Test1;
|
||||
|
||||
#[derive(Copy="bad")]
|
||||
//~^ ERROR malformed `derive` entry
|
||||
struct Test2;
|
||||
|
||||
#[derive()]
|
||||
//~^ WARNING empty trait list
|
||||
struct Test3;
|
||||
|
||||
#[derive]
|
||||
//~^ WARNING empty trait list
|
||||
struct Test4;
|
15
src/test/compile-fail/single-derive-attr.rs
Normal file
15
src/test/compile-fail/single-derive-attr.rs
Normal file
@ -0,0 +1,15 @@
|
||||
// Copyright 2015 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.
|
||||
|
||||
#[derive_Clone]
|
||||
//~^ ERROR attributes of the form `#[derive_*]` are reserved
|
||||
struct Test;
|
||||
|
||||
pub fn main() {}
|
59
src/test/run-pass-fulldeps/derive-totalsum.rs
Normal file
59
src/test/run-pass-fulldeps/derive-totalsum.rs
Normal file
@ -0,0 +1,59 @@
|
||||
// Copyright 2015 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.
|
||||
|
||||
// aux-build:custom_derive_plugin.rs
|
||||
// ignore-stage1
|
||||
|
||||
#![feature(plugin, custom_derive)]
|
||||
#![plugin(custom_derive_plugin)]
|
||||
|
||||
trait TotalSum {
|
||||
fn total_sum(&self) -> isize;
|
||||
}
|
||||
|
||||
impl TotalSum for isize {
|
||||
fn total_sum(&self) -> isize {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
struct Seven;
|
||||
|
||||
impl TotalSum for Seven {
|
||||
fn total_sum(&self) -> isize {
|
||||
7
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(TotalSum)]
|
||||
struct Foo {
|
||||
seven: Seven,
|
||||
bar: Bar,
|
||||
baz: isize,
|
||||
}
|
||||
|
||||
#[derive(TotalSum)]
|
||||
struct Bar {
|
||||
quux: isize,
|
||||
bleh: isize,
|
||||
}
|
||||
|
||||
|
||||
pub fn main() {
|
||||
let v = Foo {
|
||||
seven: Seven,
|
||||
bar: Bar {
|
||||
quux: 9,
|
||||
bleh: 3,
|
||||
},
|
||||
baz: 80,
|
||||
};
|
||||
assert_eq!(v.total_sum(), 99);
|
||||
}
|
15
src/test/run-pass/deprecated-derive.rs
Normal file
15
src/test/run-pass/deprecated-derive.rs
Normal file
@ -0,0 +1,15 @@
|
||||
// Copyright 2015 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.
|
||||
|
||||
#[derive(Show)]
|
||||
//~^ WARNING derive(Show) is deprecated
|
||||
struct Test1;
|
||||
|
||||
fn main() { }
|
18
src/test/run-pass/single-derive-attr-with-gate.rs
Normal file
18
src/test/run-pass/single-derive-attr-with-gate.rs
Normal file
@ -0,0 +1,18 @@
|
||||
// Copyright 2015 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.
|
||||
|
||||
#![feature(custom_derive)]
|
||||
|
||||
#[derive_Clone]
|
||||
struct Test;
|
||||
|
||||
pub fn main() {
|
||||
Test.clone();
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user