Skip to content

Commit 8f94ac6

Browse files
committed
auto merge of #6267 : huonw/rust/syntax-deriving-generaliseder, r=nikomatsakis
This "finishes" the generic deriving code (which I started in #5640), in the sense it supports everything that I can think of being useful. (Including lifetimes and type parameters on methods and traits, arguments and return values of (almost) any type, static methods.) It closes #6149, but met with #6257, so the following doesn't work: ```rust #[deriving(TotalEq)] struct Foo<'self>(&'self int); ``` (It only fails for `TotalOrd`, `TotalEq` and `Clone`, since they are the only ones that call a method directly on sub-elements of the type, which means that the auto-deref interferes with the pointer.) It also makes `Rand` (chooses a random variant, fills the fields with random values, including recursively for recursive types) and `ToStr` (`x.to_str()` is the same as `fmt!("%?", x)`) derivable, as well as converting IterBytes to the generic code (which made the code 2.5x shorter, more robust and added support for tuple structs). ({En,De}codable are trickier, so I'll convert them over later.)
2 parents 37becd8 + 08c8054 commit 8f94ac6

18 files changed

+1342
-777
lines changed

src/libsyntax/ext/build.rs

+59-25
Original file line numberDiff line numberDiff line change
@@ -54,43 +54,52 @@ pub fn mk_binary(cx: @ext_ctxt, sp: span, op: ast::binop,
5454
cx.next_id(); // see ast_util::op_expr_callee_id
5555
mk_expr(cx, sp, ast::expr_binary(op, lhs, rhs))
5656
}
57+
58+
pub fn mk_deref(cx: @ext_ctxt, sp: span, e: @ast::expr) -> @ast::expr {
59+
mk_unary(cx, sp, ast::deref, e)
60+
}
5761
pub fn mk_unary(cx: @ext_ctxt, sp: span, op: ast::unop, e: @ast::expr)
5862
-> @ast::expr {
5963
cx.next_id(); // see ast_util::op_expr_callee_id
6064
mk_expr(cx, sp, ast::expr_unary(op, e))
6165
}
6266
pub fn mk_raw_path(sp: span, idents: ~[ast::ident]) -> @ast::Path {
63-
mk_raw_path_(sp, idents, ~[])
67+
mk_raw_path_(sp, idents, None, ~[])
6468
}
6569
pub fn mk_raw_path_(sp: span,
6670
idents: ~[ast::ident],
71+
rp: Option<@ast::Lifetime>,
6772
types: ~[@ast::Ty])
6873
-> @ast::Path {
6974
@ast::Path { span: sp,
7075
global: false,
7176
idents: idents,
72-
rp: None,
77+
rp: rp,
7378
types: types }
7479
}
7580
pub fn mk_raw_path_global(sp: span, idents: ~[ast::ident]) -> @ast::Path {
76-
mk_raw_path_global_(sp, idents, ~[])
81+
mk_raw_path_global_(sp, idents, None, ~[])
7782
}
7883
pub fn mk_raw_path_global_(sp: span,
7984
idents: ~[ast::ident],
85+
rp: Option<@ast::Lifetime>,
8086
types: ~[@ast::Ty]) -> @ast::Path {
8187
@ast::Path { span: sp,
8288
global: true,
8389
idents: idents,
84-
rp: None,
90+
rp: rp,
8591
types: types }
8692
}
93+
pub fn mk_path_raw(cx: @ext_ctxt, sp: span, path: @ast::Path)-> @ast::expr {
94+
mk_expr(cx, sp, ast::expr_path(path))
95+
}
8796
pub fn mk_path(cx: @ext_ctxt, sp: span, idents: ~[ast::ident])
8897
-> @ast::expr {
89-
mk_expr(cx, sp, ast::expr_path(mk_raw_path(sp, idents)))
98+
mk_path_raw(cx, sp, mk_raw_path(sp, idents))
9099
}
91100
pub fn mk_path_global(cx: @ext_ctxt, sp: span, idents: ~[ast::ident])
92101
-> @ast::expr {
93-
mk_expr(cx, sp, ast::expr_path(mk_raw_path_global(sp, idents)))
102+
mk_path_raw(cx, sp, mk_raw_path_global(sp, idents))
94103
}
95104
pub fn mk_access_(cx: @ext_ctxt, sp: span, p: @ast::expr, m: ast::ident)
96105
-> @ast::expr {
@@ -354,44 +363,69 @@ pub fn mk_stmt(cx: @ext_ctxt, span: span, expr: @ast::expr) -> @ast::stmt {
354363
let stmt_ = ast::stmt_semi(expr, cx.next_id());
355364
@codemap::spanned { node: stmt_, span: span }
356365
}
366+
367+
pub fn mk_ty_mt(ty: @ast::Ty, mutbl: ast::mutability) -> ast::mt {
368+
ast::mt {
369+
ty: ty,
370+
mutbl: mutbl
371+
}
372+
}
373+
374+
pub fn mk_ty(cx: @ext_ctxt,
375+
span: span,
376+
ty: ast::ty_) -> @ast::Ty {
377+
@ast::Ty {
378+
id: cx.next_id(),
379+
span: span,
380+
node: ty
381+
}
382+
}
383+
357384
pub fn mk_ty_path(cx: @ext_ctxt,
358385
span: span,
359386
idents: ~[ ast::ident ])
360387
-> @ast::Ty {
361388
let ty = build::mk_raw_path(span, idents);
362-
let ty = ast::ty_path(ty, cx.next_id());
363-
let ty = @ast::Ty { id: cx.next_id(), node: ty, span: span };
364-
ty
389+
mk_ty_path_path(cx, span, ty)
365390
}
391+
366392
pub fn mk_ty_path_global(cx: @ext_ctxt,
367393
span: span,
368394
idents: ~[ ast::ident ])
369395
-> @ast::Ty {
370396
let ty = build::mk_raw_path_global(span, idents);
371-
let ty = ast::ty_path(ty, cx.next_id());
372-
let ty = @ast::Ty { id: cx.next_id(), node: ty, span: span };
373-
ty
397+
mk_ty_path_path(cx, span, ty)
374398
}
399+
400+
pub fn mk_ty_path_path(cx: @ext_ctxt,
401+
span: span,
402+
path: @ast::Path)
403+
-> @ast::Ty {
404+
let ty = ast::ty_path(path, cx.next_id());
405+
mk_ty(cx, span, ty)
406+
}
407+
375408
pub fn mk_ty_rptr(cx: @ext_ctxt,
376409
span: span,
377410
ty: @ast::Ty,
411+
lifetime: Option<@ast::Lifetime>,
378412
mutbl: ast::mutability)
379413
-> @ast::Ty {
380-
@ast::Ty {
381-
id: cx.next_id(),
382-
span: span,
383-
node: ast::ty_rptr(
384-
None,
385-
ast::mt { ty: ty, mutbl: mutbl }
386-
),
387-
}
414+
mk_ty(cx, span,
415+
ast::ty_rptr(lifetime, mk_ty_mt(ty, mutbl)))
416+
}
417+
pub fn mk_ty_uniq(cx: @ext_ctxt, span: span, ty: @ast::Ty) -> @ast::Ty {
418+
mk_ty(cx, span, ast::ty_uniq(mk_ty_mt(ty, ast::m_imm)))
388419
}
420+
pub fn mk_ty_box(cx: @ext_ctxt, span: span,
421+
ty: @ast::Ty, mutbl: ast::mutability) -> @ast::Ty {
422+
mk_ty(cx, span, ast::ty_box(mk_ty_mt(ty, mutbl)))
423+
}
424+
425+
426+
389427
pub fn mk_ty_infer(cx: @ext_ctxt, span: span) -> @ast::Ty {
390-
@ast::Ty {
391-
id: cx.next_id(),
392-
node: ast::ty_infer,
393-
span: span,
394-
}
428+
mk_ty(cx, span, ast::ty_infer)
395429
}
396430
pub fn mk_trait_ref_global(cx: @ext_ctxt,
397431
span: span,

src/libsyntax/ext/deriving/clone.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ use codemap::span;
1313
use ext::base::ext_ctxt;
1414
use ext::build;
1515
use ext::deriving::generic::*;
16-
use core::option::{None,Some};
1716

1817

1918
pub fn expand_deriving_clone(cx: @ext_ctxt,
@@ -22,13 +21,16 @@ pub fn expand_deriving_clone(cx: @ext_ctxt,
2221
in_items: ~[@item])
2322
-> ~[@item] {
2423
let trait_def = TraitDef {
25-
path: ~[~"core", ~"clone", ~"Clone"],
24+
path: Path::new(~[~"core", ~"clone", ~"Clone"]),
2625
additional_bounds: ~[],
26+
generics: LifetimeBounds::empty(),
2727
methods: ~[
2828
MethodDef {
2929
name: ~"clone",
30-
nargs: 0,
31-
output_type: None, // return Self
30+
generics: LifetimeBounds::empty(),
31+
self_ty: borrowed_explicit_self(),
32+
args: ~[],
33+
ret_ty: Self,
3234
const_nonmatching: false,
3335
combine_substructure: cs_clone
3436
}
@@ -66,7 +68,8 @@ fn cs_clone(cx: @ext_ctxt, span: span,
6668
ctor_ident = ~[ variant.node.name ];
6769
all_fields = af;
6870
},
69-
EnumNonMatching(*) => cx.bug("Non-matching enum variants in `deriving(Clone)`")
71+
EnumNonMatching(*) => cx.span_bug(span, "Non-matching enum variants in `deriving(Clone)`"),
72+
StaticEnum(*) | StaticStruct(*) => cx.span_bug(span, "Static method in `deriving(Clone)`")
7073
}
7174

7275
match all_fields {

src/libsyntax/ext/deriving/cmp/eq.rs

+10-9
Original file line numberDiff line numberDiff line change
@@ -8,44 +8,45 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
1211
use ast::{meta_item, item, expr};
1312
use codemap::span;
1413
use ext::base::ext_ctxt;
1514
use ext::build;
1615
use ext::deriving::generic::*;
1716

18-
use core::option::Some;
19-
2017
pub fn expand_deriving_eq(cx: @ext_ctxt,
2118
span: span,
2219
mitem: @meta_item,
2320
in_items: ~[@item]) -> ~[@item] {
2421
// structures are equal if all fields are equal, and non equal, if
2522
// any fields are not equal or if the enum variants are different
2623
fn cs_eq(cx: @ext_ctxt, span: span, substr: &Substructure) -> @expr {
27-
cs_and(|cx, span, _| build::mk_bool(cx, span, false),
24+
cs_and(|cx, span, _, _| build::mk_bool(cx, span, false),
2825
cx, span, substr)
2926
}
3027
fn cs_ne(cx: @ext_ctxt, span: span, substr: &Substructure) -> @expr {
31-
cs_or(|cx, span, _| build::mk_bool(cx, span, true),
28+
cs_or(|cx, span, _, _| build::mk_bool(cx, span, true),
3229
cx, span, substr)
3330
}
31+
3432
macro_rules! md (
3533
($name:expr, $f:ident) => {
3634
MethodDef {
3735
name: $name,
38-
output_type: Some(~[~"bool"]),
39-
nargs: 1,
36+
generics: LifetimeBounds::empty(),
37+
self_ty: borrowed_explicit_self(),
38+
args: ~[borrowed_self()],
39+
ret_ty: Literal(Path::new(~[~"bool"])),
4040
const_nonmatching: true,
4141
combine_substructure: $f
4242
},
4343
}
44-
)
44+
);
4545

4646
let trait_def = TraitDef {
47-
path: ~[~"core", ~"cmp", ~"Eq"],
47+
path: Path::new(~[~"core", ~"cmp", ~"Eq"]),
4848
additional_bounds: ~[],
49+
generics: LifetimeBounds::empty(),
4950
methods: ~[
5051
md!(~"eq", cs_eq),
5152
md!(~"ne", cs_ne)

src/libsyntax/ext/deriving/cmp/ord.rs

+23-19
Original file line numberDiff line numberDiff line change
@@ -14,29 +14,33 @@ use codemap::span;
1414
use ext::base::ext_ctxt;
1515
use ext::build;
1616
use ext::deriving::generic::*;
17-
use core::option::Some;
18-
19-
macro_rules! md {
20-
($name:expr, $less:expr, $equal:expr) => {
21-
MethodDef {
22-
name: $name,
23-
output_type: Some(~[~"bool"]),
24-
nargs: 1,
25-
const_nonmatching: false,
26-
combine_substructure: |cx, span, substr|
27-
cs_ord($less, $equal, cx, span, substr)
28-
}
29-
}
30-
}
3117

3218
pub fn expand_deriving_ord(cx: @ext_ctxt,
3319
span: span,
3420
mitem: @meta_item,
3521
in_items: ~[@item]) -> ~[@item] {
22+
macro_rules! md (
23+
($name:expr, $less:expr, $equal:expr) => {
24+
MethodDef {
25+
name: $name,
26+
generics: LifetimeBounds::empty(),
27+
self_ty: borrowed_explicit_self(),
28+
args: ~[borrowed_self()],
29+
ret_ty: Literal(Path::new(~[~"bool"])),
30+
const_nonmatching: false,
31+
combine_substructure: |cx, span, substr|
32+
cs_ord($less, $equal, cx, span, substr)
33+
}
34+
}
35+
);
36+
37+
38+
3639
let trait_def = TraitDef {
37-
path: ~[~"core", ~"cmp", ~"Ord"],
40+
path: Path::new(~[~"core", ~"cmp", ~"Ord"]),
3841
// XXX: Ord doesn't imply Eq yet
39-
additional_bounds: ~[~[~"core", ~"cmp", ~"Eq"]],
42+
additional_bounds: ~[Literal(Path::new(~[~"core", ~"cmp", ~"Eq"]))],
43+
generics: LifetimeBounds::empty(),
4044
methods: ~[
4145
md!(~"lt", true, false),
4246
md!(~"le", true, true),
@@ -97,19 +101,19 @@ fn cs_ord(less: bool, equal: bool,
97101
}
98102

99103
let cmp = build::mk_method_call(cx, span,
100-
self_f, cx.ident_of(~"eq"), other_fs);
104+
self_f, cx.ident_of(~"eq"), other_fs.to_owned());
101105
let subexpr = build::mk_simple_block(cx, span, subexpr);
102106
let elseif = expr_if(cmp, subexpr, Some(false_blk_expr));
103107
let elseif = build::mk_expr(cx, span, elseif);
104108
105109
let cmp = build::mk_method_call(cx, span,
106-
self_f, binop, other_fs);
110+
self_f, binop, other_fs.to_owned());
107111
let if_ = expr_if(cmp, true_blk, Some(elseif));
108112
109113
build::mk_expr(cx, span, if_)
110114
},
111115
base,
112-
|cx, span, args| {
116+
|cx, span, args, _| {
113117
// nonmatching enums, order by the order the variants are
114118
// written
115119
match args {

src/libsyntax/ext/deriving/cmp/totaleq.rs

+7-6
Original file line numberDiff line numberDiff line change
@@ -15,26 +15,27 @@ use ext::base::ext_ctxt;
1515
use ext::build;
1616
use ext::deriving::generic::*;
1717

18-
use core::option::Some;
19-
2018
pub fn expand_deriving_totaleq(cx: @ext_ctxt,
2119
span: span,
2220
mitem: @meta_item,
2321
in_items: ~[@item]) -> ~[@item] {
2422

2523
fn cs_equals(cx: @ext_ctxt, span: span, substr: &Substructure) -> @expr {
26-
cs_and(|cx, span, _| build::mk_bool(cx, span, false),
24+
cs_and(|cx, span, _, _| build::mk_bool(cx, span, false),
2725
cx, span, substr)
2826
}
2927

3028
let trait_def = TraitDef {
31-
path: ~[~"core", ~"cmp", ~"TotalEq"],
29+
path: Path::new(~[~"core", ~"cmp", ~"TotalEq"]),
3230
additional_bounds: ~[],
31+
generics: LifetimeBounds::empty(),
3332
methods: ~[
3433
MethodDef {
3534
name: ~"equals",
36-
output_type: Some(~[~"bool"]),
37-
nargs: 1,
35+
generics: LifetimeBounds::empty(),
36+
self_ty: borrowed_explicit_self(),
37+
args: ~[borrowed_self()],
38+
ret_ty: Literal(Path::new(~[~"bool"])),
3839
const_nonmatching: true,
3940
combine_substructure: cs_equals
4041
}

src/libsyntax/ext/deriving/cmp/totalord.rs

+7-5
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,22 @@ use ext::base::ext_ctxt;
1414
use ext::build;
1515
use ext::deriving::generic::*;
1616
use core::cmp::{Ordering, Equal, Less, Greater};
17-
use core::option::Some;
1817

1918
pub fn expand_deriving_totalord(cx: @ext_ctxt,
2019
span: span,
2120
mitem: @meta_item,
2221
in_items: ~[@item]) -> ~[@item] {
2322
let trait_def = TraitDef {
24-
path: ~[~"core", ~"cmp", ~"TotalOrd"],
23+
path: Path::new(~[~"core", ~"cmp", ~"TotalOrd"]),
2524
additional_bounds: ~[],
25+
generics: LifetimeBounds::empty(),
2626
methods: ~[
2727
MethodDef {
2828
name: ~"cmp",
29-
output_type: Some(~[~"core", ~"cmp", ~"Ordering"]),
30-
nargs: 1,
29+
generics: LifetimeBounds::empty(),
30+
self_ty: borrowed_explicit_self(),
31+
args: ~[borrowed_self()],
32+
ret_ty: Literal(Path::new(~[~"core", ~"cmp", ~"Ordering"])),
3133
const_nonmatching: false,
3234
combine_substructure: cs_cmp
3335
}
@@ -64,7 +66,7 @@ pub fn cs_cmp(cx: @ext_ctxt, span: span,
6466
build::mk_call_global(cx, span, lexical_ord, ~[old, new])
6567
},
6668
ordering_const(cx, span, Equal),
67-
|cx, span, list| {
69+
|cx, span, list, _| {
6870
match list {
6971
// an earlier nonmatching variant is Less than a
7072
// later one

0 commit comments

Comments
 (0)