Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 491054f

Browse files
committedMar 7, 2015
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]
1 parent e60e6f0 commit 491054f

File tree

14 files changed

+372
-125
lines changed

14 files changed

+372
-125
lines changed
 

‎src/doc/reference.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2429,6 +2429,10 @@ The currently implemented features of the reference compiler are:
24292429
so that new attributes can be added in a bacwards compatible
24302430
manner (RFC 572).
24312431

2432+
* `custom_derive` - Allows the use of `#[derive(Foo,Bar)]` as sugar for
2433+
`#[derive_Foo] #[derive_Bar]`, which can be user-defined syntax
2434+
extensions.
2435+
24322436
* `intrinsics` - Allows use of the "rust-intrinsics" ABI. Compiler intrinsics
24332437
are inherently unstable and no promise about them is made.
24342438

‎src/libsyntax/ext/base.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -491,10 +491,8 @@ fn initial_syntax_expander_table<'feat>(ecfg: &expand::ExpansionConfig<'feat>)
491491
syntax_expanders.insert(intern("log_syntax"),
492492
builtin_normal_expander(
493493
ext::log_syntax::expand_syntax_ext));
494-
syntax_expanders.insert(intern("derive"),
495-
Decorator(Box::new(ext::deriving::expand_meta_derive)));
496-
syntax_expanders.insert(intern("deriving"),
497-
Decorator(Box::new(ext::deriving::expand_deprecated_deriving)));
494+
495+
ext::deriving::register_all(&mut syntax_expanders);
498496

499497
if ecfg.enable_quotes() {
500498
// Quasi-quoting expanders

‎src/libsyntax/ext/deriving/bounds.rs

Lines changed: 16 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -8,47 +8,34 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use ast::{MetaItem, MetaWord, Item};
11+
use ast::{MetaItem, Item};
1212
use codemap::Span;
1313
use ext::base::ExtCtxt;
1414
use ext::deriving::generic::*;
1515
use ext::deriving::generic::ty::*;
1616
use ptr::P;
1717

18-
pub fn expand_deriving_bound<F>(cx: &mut ExtCtxt,
19-
span: Span,
20-
mitem: &MetaItem,
21-
item: &Item,
22-
push: F) where
18+
pub fn expand_deriving_unsafe_bound<F>(cx: &mut ExtCtxt,
19+
span: Span,
20+
_: &MetaItem,
21+
_: &Item,
22+
_: F) where
2323
F: FnOnce(P<Item>),
2424
{
25-
let name = match mitem.node {
26-
MetaWord(ref tname) => {
27-
match &tname[..] {
28-
"Copy" => "Copy",
29-
"Send" | "Sync" => {
30-
return cx.span_err(span,
31-
&format!("{} is an unsafe trait and it \
32-
should be implemented explicitly",
33-
*tname))
34-
}
35-
ref tname => {
36-
cx.span_bug(span,
37-
&format!("expected built-in trait name but \
38-
found {}", *tname))
39-
}
40-
}
41-
},
42-
_ => {
43-
return cx.span_err(span, "unexpected value in deriving, expected \
44-
a trait")
45-
}
46-
};
25+
cx.span_err(span, "this unsafe trait should be implemented explicitly");
26+
}
4727

28+
pub fn expand_deriving_copy<F>(cx: &mut ExtCtxt,
29+
span: Span,
30+
mitem: &MetaItem,
31+
item: &Item,
32+
push: F) where
33+
F: FnOnce(P<Item>),
34+
{
4835
let path = Path::new(vec![
4936
if cx.use_std { "std" } else { "core" },
5037
"marker",
51-
name
38+
"Copy",
5239
]);
5340

5441
let trait_def = TraitDef {

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

Lines changed: 124 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
1+
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
22
// file at the top-level directory of this distribution and at
33
// http://rust-lang.org/COPYRIGHT.
44
//
@@ -13,9 +13,13 @@
1313
//! FIXME (#2810): hygiene. Search for "__" strings (in other files too). We also assume "extra" is
1414
//! the standard library, and "std" is the core library.
1515
16-
use ast::{Item, MetaItem, MetaList, MetaNameValue, MetaWord};
17-
use ext::base::ExtCtxt;
16+
use ast::{Item, MetaItem, MetaWord};
17+
use attr::AttrMetaMethods;
18+
use ext::base::{ExtCtxt, SyntaxEnv, Decorator, ItemDecorator, Modifier};
19+
use ext::build::AstBuilder;
20+
use feature_gate;
1821
use codemap::Span;
22+
use parse::token::{intern, intern_and_get_ident};
1923
use ptr::P;
2024

2125
macro_rules! pathvec {
@@ -74,101 +78,133 @@ pub mod totalord;
7478

7579
pub mod generic;
7680

77-
pub fn expand_deprecated_deriving(cx: &mut ExtCtxt,
78-
span: Span,
79-
_: &MetaItem,
80-
_: &Item,
81-
_: &mut FnMut(P<Item>)) {
81+
fn expand_deprecated_deriving(cx: &mut ExtCtxt,
82+
span: Span,
83+
_: &MetaItem,
84+
_: &Item,
85+
_: &mut FnMut(P<Item>)) {
8286
cx.span_err(span, "`deriving` has been renamed to `derive`");
8387
}
8488

85-
pub fn expand_meta_derive(cx: &mut ExtCtxt,
86-
_span: Span,
87-
mitem: &MetaItem,
88-
item: &Item,
89-
push: &mut FnMut(P<Item>)) {
90-
match mitem.node {
91-
MetaNameValue(_, ref l) => {
92-
cx.span_err(l.span, "unexpected value in `derive`");
89+
fn expand_derive(cx: &mut ExtCtxt,
90+
_: Span,
91+
mitem: &MetaItem,
92+
item: P<Item>) -> P<Item> {
93+
item.map(|mut item| {
94+
if mitem.value_str().is_some() {
95+
cx.span_err(mitem.span, "unexpected value in `derive`");
9396
}
94-
MetaWord(_) => {
97+
98+
let traits = mitem.meta_item_list().unwrap_or(&[]);
99+
if traits.is_empty() {
95100
cx.span_warn(mitem.span, "empty trait list in `derive`");
96101
}
97-
MetaList(_, ref titems) if titems.len() == 0 => {
98-
cx.span_warn(mitem.span, "empty trait list in `derive`");
102+
103+
for titem in traits.iter().rev() {
104+
let tname = match titem.node {
105+
MetaWord(ref tname) => tname,
106+
_ => {
107+
cx.span_err(titem.span, "malformed `derive` entry");
108+
continue;
109+
}
110+
};
111+
112+
if !(is_builtin_trait(tname) || cx.ecfg.enable_custom_derive()) {
113+
feature_gate::emit_feature_err(&cx.parse_sess.span_diagnostic,
114+
"custom_derive",
115+
titem.span,
116+
feature_gate::EXPLAIN_CUSTOM_DERIVE);
117+
continue;
118+
}
119+
120+
// #[derive(Foo, Bar)] expands to #[derive_Foo] #[derive_Bar]
121+
item.attrs.push(cx.attribute(titem.span, cx.meta_word(titem.span,
122+
intern_and_get_ident(&format!("derive_{}", tname)))));
99123
}
100-
MetaList(_, ref titems) => {
101-
for titem in titems.iter().rev() {
102-
match titem.node {
103-
MetaNameValue(ref tname, _) |
104-
MetaList(ref tname, _) |
105-
MetaWord(ref tname) => {
106-
macro_rules! expand {
107-
($func:path) => ($func(cx, titem.span, &**titem, item,
108-
|i| push(i)))
109-
}
110-
111-
match &tname[..] {
112-
"Clone" => expand!(clone::expand_deriving_clone),
113-
114-
"Hash" => expand!(hash::expand_deriving_hash),
115-
116-
"RustcEncodable" => {
117-
expand!(encodable::expand_deriving_rustc_encodable)
118-
}
119-
"RustcDecodable" => {
120-
expand!(decodable::expand_deriving_rustc_decodable)
121-
}
122-
"Encodable" => {
123-
cx.span_warn(titem.span,
124-
"derive(Encodable) is deprecated \
125-
in favor of derive(RustcEncodable)");
126-
127-
expand!(encodable::expand_deriving_encodable)
128-
}
129-
"Decodable" => {
130-
cx.span_warn(titem.span,
131-
"derive(Decodable) is deprecated \
132-
in favor of derive(RustcDecodable)");
133-
134-
expand!(decodable::expand_deriving_decodable)
135-
}
136-
137-
"PartialEq" => expand!(eq::expand_deriving_eq),
138-
"Eq" => expand!(totaleq::expand_deriving_totaleq),
139-
"PartialOrd" => expand!(ord::expand_deriving_ord),
140-
"Ord" => expand!(totalord::expand_deriving_totalord),
141-
142-
"Rand" => expand!(rand::expand_deriving_rand),
143-
144-
"Show" => {
145-
cx.span_warn(titem.span,
146-
"derive(Show) is deprecated \
147-
in favor of derive(Debug)");
148-
149-
expand!(show::expand_deriving_show)
150-
},
151-
152-
"Debug" => expand!(show::expand_deriving_show),
153-
154-
"Default" => expand!(default::expand_deriving_default),
155-
156-
"FromPrimitive" => expand!(primitive::expand_deriving_from_primitive),
157-
158-
"Send" => expand!(bounds::expand_deriving_bound),
159-
"Sync" => expand!(bounds::expand_deriving_bound),
160-
"Copy" => expand!(bounds::expand_deriving_bound),
161-
162-
ref tname => {
163-
cx.span_err(titem.span,
164-
&format!("unknown `derive` \
165-
trait: `{}`",
166-
*tname));
167-
}
168-
};
124+
125+
item
126+
})
127+
}
128+
129+
macro_rules! derive_traits {
130+
($( $name:expr => $func:path, )*) => {
131+
pub fn register_all(env: &mut SyntaxEnv) {
132+
// Define the #[derive_*] extensions.
133+
$({
134+
struct DeriveExtension;
135+
136+
impl ItemDecorator for DeriveExtension {
137+
fn expand(&self,
138+
ecx: &mut ExtCtxt,
139+
sp: Span,
140+
mitem: &MetaItem,
141+
item: &Item,
142+
push: &mut FnMut(P<Item>)) {
143+
warn_if_deprecated(ecx, sp, $name);
144+
$func(ecx, sp, mitem, item, |i| push(i));
169145
}
170146
}
147+
148+
env.insert(intern(concat!("derive_", $name)),
149+
Decorator(Box::new(DeriveExtension)));
150+
})*
151+
152+
env.insert(intern("derive"),
153+
Modifier(Box::new(expand_derive)));
154+
env.insert(intern("deriving"),
155+
Decorator(Box::new(expand_deprecated_deriving)));
156+
}
157+
158+
fn is_builtin_trait(name: &str) -> bool {
159+
match name {
160+
$( $name )|* => true,
161+
_ => false,
171162
}
172163
}
173164
}
174165
}
166+
167+
derive_traits! {
168+
"Clone" => clone::expand_deriving_clone,
169+
170+
"Hash" => hash::expand_deriving_hash,
171+
172+
"RustcEncodable" => encodable::expand_deriving_rustc_encodable,
173+
174+
"RustcDecodable" => decodable::expand_deriving_rustc_decodable,
175+
176+
"PartialEq" => eq::expand_deriving_eq,
177+
"Eq" => totaleq::expand_deriving_totaleq,
178+
"PartialOrd" => ord::expand_deriving_ord,
179+
"Ord" => totalord::expand_deriving_totalord,
180+
181+
"Rand" => rand::expand_deriving_rand,
182+
183+
"Debug" => show::expand_deriving_show,
184+
185+
"Default" => default::expand_deriving_default,
186+
187+
"FromPrimitive" => primitive::expand_deriving_from_primitive,
188+
189+
"Send" => bounds::expand_deriving_unsafe_bound,
190+
"Sync" => bounds::expand_deriving_unsafe_bound,
191+
"Copy" => bounds::expand_deriving_copy,
192+
193+
// deprecated
194+
"Show" => show::expand_deriving_show,
195+
"Encodable" => encodable::expand_deriving_encodable,
196+
"Decodable" => decodable::expand_deriving_decodable,
197+
}
198+
199+
#[inline] // because `name` is a compile-time constant
200+
fn warn_if_deprecated(ecx: &mut ExtCtxt, sp: Span, name: &str) {
201+
if let Some(replacement) = match name {
202+
"Show" => Some("Debug"),
203+
"Encodable" => Some("RustcEncodable"),
204+
"Decodable" => Some("RustcDecodable"),
205+
_ => None,
206+
} {
207+
ecx.span_warn(sp, &format!("derive({}) is deprecated in favor of derive({})",
208+
name, replacement));
209+
}
210+
}

‎src/libsyntax/ext/expand.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1476,6 +1476,7 @@ impl<'feat> ExpansionConfig<'feat> {
14761476
fn enable_concat_idents = allow_concat_idents,
14771477
fn enable_trace_macros = allow_trace_macros,
14781478
fn enable_allow_internal_unstable = allow_internal_unstable,
1479+
fn enable_custom_derive = allow_custom_derive,
14791480
}
14801481
}
14811482

‎src/libsyntax/feature_gate.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,10 @@ const KNOWN_FEATURES: &'static [(&'static str, &'static str, Status)] = &[
137137
// Allows the use of custom attributes; RFC 572
138138
("custom_attribute", "1.0.0", Active),
139139

140+
// Allows the use of #[derive(Anything)] as sugar for
141+
// #[derive_Anything].
142+
("custom_derive", "1.0.0", Active),
143+
140144
// Allows the use of rustc_* attributes; RFC 572
141145
("rustc_attrs", "1.0.0", Active),
142146

@@ -319,6 +323,7 @@ pub struct Features {
319323
pub allow_concat_idents: bool,
320324
pub allow_trace_macros: bool,
321325
pub allow_internal_unstable: bool,
326+
pub allow_custom_derive: bool,
322327
pub old_orphan_check: bool,
323328
pub simd_ffi: bool,
324329
pub unmarked_api: bool,
@@ -340,6 +345,7 @@ impl Features {
340345
allow_concat_idents: false,
341346
allow_trace_macros: false,
342347
allow_internal_unstable: false,
348+
allow_custom_derive: false,
343349
old_orphan_check: false,
344350
simd_ffi: false,
345351
unmarked_api: false,
@@ -391,6 +397,10 @@ impl<'a> Context<'a> {
391397
"unless otherwise specified, attributes \
392398
with the prefix `rustc_` \
393399
are reserved for internal compiler diagnostics");
400+
} else if name.starts_with("derive_") {
401+
self.gate_feature("custom_derive", attr.span,
402+
"attributes of the form `#[derive_*]` are reserved
403+
for the compiler");
394404
} else {
395405
self.gate_feature("custom_attribute", attr.span,
396406
format!("The attribute `{}` is currently \
@@ -432,6 +442,9 @@ pub const EXPLAIN_TRACE_MACROS: &'static str =
432442
pub const EXPLAIN_ALLOW_INTERNAL_UNSTABLE: &'static str =
433443
"allow_internal_unstable side-steps feature gating and stability checks";
434444

445+
pub const EXPLAIN_CUSTOM_DERIVE: &'static str =
446+
"`#[derive]` for custom traits is not stable enough for use and is subject to change";
447+
435448
struct MacroVisitor<'a> {
436449
context: &'a Context<'a>
437450
}
@@ -780,6 +793,7 @@ fn check_crate_inner<F>(cm: &CodeMap, span_handler: &SpanHandler, krate: &ast::C
780793
allow_concat_idents: cx.has_feature("concat_idents"),
781794
allow_trace_macros: cx.has_feature("trace_macros"),
782795
allow_internal_unstable: cx.has_feature("allow_internal_unstable"),
796+
allow_custom_derive: cx.has_feature("custom_derive"),
783797
old_orphan_check: cx.has_feature("old_orphan_check"),
784798
simd_ffi: cx.has_feature("simd_ffi"),
785799
unmarked_api: cx.has_feature("unmarked_api"),
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// force-host
12+
13+
#![feature(plugin_registrar)]
14+
#![feature(box_syntax)]
15+
#![feature(rustc_private)]
16+
17+
extern crate syntax;
18+
extern crate rustc;
19+
20+
use syntax::ast;
21+
use syntax::codemap::Span;
22+
use syntax::ext::base::{Decorator, ExtCtxt};
23+
use syntax::ext::build::AstBuilder;
24+
use syntax::ext::deriving::generic::{cs_fold, TraitDef, MethodDef, combine_substructure};
25+
use syntax::ext::deriving::generic::ty::{Literal, LifetimeBounds, Path, borrowed_explicit_self};
26+
use syntax::parse::token;
27+
use syntax::ptr::P;
28+
use rustc::plugin::Registry;
29+
30+
#[plugin_registrar]
31+
pub fn plugin_registrar(reg: &mut Registry) {
32+
reg.register_syntax_extension(
33+
token::intern("derive_TotalSum"),
34+
Decorator(box expand));
35+
}
36+
37+
fn expand(cx: &mut ExtCtxt,
38+
span: Span,
39+
mitem: &ast::MetaItem,
40+
item: &ast::Item,
41+
push: &mut FnMut(P<ast::Item>)) {
42+
let trait_def = TraitDef {
43+
span: span,
44+
attributes: vec![],
45+
path: Path::new(vec!["TotalSum"]),
46+
additional_bounds: vec![],
47+
generics: LifetimeBounds::empty(),
48+
associated_types: vec![],
49+
methods: vec![
50+
MethodDef {
51+
name: "total_sum",
52+
generics: LifetimeBounds::empty(),
53+
explicit_self: borrowed_explicit_self(),
54+
args: vec![],
55+
ret_ty: Literal(Path::new_local("isize")),
56+
attributes: vec![],
57+
combine_substructure: combine_substructure(box |cx, span, substr| {
58+
let zero = cx.expr_int(span, 0);
59+
cs_fold(false,
60+
|cx, span, subexpr, field, _| {
61+
cx.expr_binary(span, ast::BiAdd, subexpr,
62+
cx.expr_method_call(span, field,
63+
token::str_to_ident("total_sum"), vec![]))
64+
},
65+
zero,
66+
box |cx, span, _, _| { cx.span_bug(span, "wtf??"); },
67+
cx, span, substr)
68+
}),
69+
},
70+
],
71+
};
72+
73+
trait_def.expand(cx, mitem, item, |i| push(i))
74+
}

‎src/test/compile-fail/deriving-bounds.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
#[derive(Copy(Bad))]
12-
//~^ ERROR unexpected value in deriving, expected a trait
11+
#[derive(Send)]
12+
//~^ ERROR this unsafe trait should be implemented explicitly
1313
struct Test;
1414

1515
#[derive(Sync)]
16-
//~^ ERROR Sync is an unsafe trait and it should be implemented explicitly
16+
//~^ ERROR this unsafe trait should be implemented explicitly
1717
struct Test1;
1818

1919
pub fn main() {}

‎src/test/compile-fail/deriving-meta-unknown-trait.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
#[derive(Eqr)] //~ ERROR unknown `derive` trait: `Eqr`
11+
#[derive(Eqr)]
12+
//~^ ERROR `#[derive]` for custom traits is not stable enough for use and is subject to change
1213
struct Foo;
1314

1415
pub fn main() {}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#[derive(Copy(Bad))]
12+
//~^ ERROR malformed `derive` entry
13+
struct Test1;
14+
15+
#[derive(Copy="bad")]
16+
//~^ ERROR malformed `derive` entry
17+
struct Test2;
18+
19+
#[derive()]
20+
//~^ WARNING empty trait list
21+
struct Test3;
22+
23+
#[derive]
24+
//~^ WARNING empty trait list
25+
struct Test4;
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#[derive_Clone]
12+
//~^ ERROR attributes of the form `#[derive_*]` are reserved
13+
struct Test;
14+
15+
pub fn main() {}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// aux-build:custom_derive_plugin.rs
12+
// ignore-stage1
13+
14+
#![feature(plugin, custom_derive)]
15+
#![plugin(custom_derive_plugin)]
16+
17+
trait TotalSum {
18+
fn total_sum(&self) -> isize;
19+
}
20+
21+
impl TotalSum for isize {
22+
fn total_sum(&self) -> isize {
23+
*self
24+
}
25+
}
26+
27+
struct Seven;
28+
29+
impl TotalSum for Seven {
30+
fn total_sum(&self) -> isize {
31+
7
32+
}
33+
}
34+
35+
#[derive(TotalSum)]
36+
struct Foo {
37+
seven: Seven,
38+
bar: Bar,
39+
baz: isize,
40+
}
41+
42+
#[derive(TotalSum)]
43+
struct Bar {
44+
quux: isize,
45+
bleh: isize,
46+
}
47+
48+
49+
pub fn main() {
50+
let v = Foo {
51+
seven: Seven,
52+
bar: Bar {
53+
quux: 9,
54+
bleh: 3,
55+
},
56+
baz: 80,
57+
};
58+
assert_eq!(v.total_sum(), 99);
59+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#[derive(Show)]
12+
//~^ WARNING derive(Show) is deprecated
13+
struct Test1;
14+
15+
fn main() { }
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(custom_derive)]
12+
13+
#[derive_Clone]
14+
struct Test;
15+
16+
pub fn main() {
17+
Test.clone();
18+
}

0 commit comments

Comments
 (0)
Please sign in to comment.