11
11
use deriving:: generic:: * ;
12
12
use deriving:: generic:: ty:: * ;
13
13
14
- use syntax:: ast:: { Expr , MetaItem } ;
14
+ use syntax:: ast:: { self , Expr , MetaItem } ;
15
15
use syntax:: ext:: base:: { Annotatable , ExtCtxt } ;
16
16
use syntax:: ext:: build:: AstBuilder ;
17
17
use syntax:: parse:: token:: InternedString ;
@@ -23,22 +23,6 @@ pub fn expand_deriving_eq(cx: &mut ExtCtxt,
23
23
mitem : & MetaItem ,
24
24
item : & Annotatable ,
25
25
push : & mut FnMut ( Annotatable ) ) {
26
- fn cs_total_eq_assert ( cx : & mut ExtCtxt , span : Span , substr : & Substructure ) -> P < Expr > {
27
- cs_same_method ( |cx, span, exprs| {
28
- // create `a.<method>(); b.<method>(); c.<method>(); ...`
29
- // (where method is `assert_receiver_is_total_eq`)
30
- let stmts = exprs. into_iter ( ) . map ( |e| cx. stmt_expr ( e) ) . collect ( ) ;
31
- let block = cx. block ( span, stmts) ;
32
- cx. expr_block ( block)
33
- } ,
34
- Box :: new ( |cx, sp, _, _| {
35
- cx. span_bug ( sp, "non matching enums in derive(Eq)?" )
36
- } ) ,
37
- cx,
38
- span,
39
- substr)
40
- }
41
-
42
26
let inline = cx. meta_word ( span, InternedString :: new ( "inline" ) ) ;
43
27
let hidden = cx. meta_list_item_word ( span, InternedString :: new ( "hidden" ) ) ;
44
28
let doc = cx. meta_list ( span, InternedString :: new ( "doc" ) , vec ! [ hidden] ) ;
@@ -50,7 +34,7 @@ pub fn expand_deriving_eq(cx: &mut ExtCtxt,
50
34
additional_bounds : Vec :: new ( ) ,
51
35
generics : LifetimeBounds :: empty ( ) ,
52
36
is_unsafe : false ,
53
- supports_unions : false ,
37
+ supports_unions : true ,
54
38
methods : vec ! [ MethodDef {
55
39
name: "assert_receiver_is_total_eq" ,
56
40
generics: LifetimeBounds :: empty( ) ,
@@ -66,5 +50,38 @@ pub fn expand_deriving_eq(cx: &mut ExtCtxt,
66
50
} ] ,
67
51
associated_types : Vec :: new ( ) ,
68
52
} ;
69
- trait_def. expand ( cx, mitem, item, push)
53
+ trait_def. expand_ext ( cx, mitem, item, push, true )
54
+ }
55
+
56
+ fn cs_total_eq_assert ( cx : & mut ExtCtxt , trait_span : Span , substr : & Substructure ) -> P < Expr > {
57
+ fn assert_ty_bounds ( cx : & mut ExtCtxt , stmts : & mut Vec < ast:: Stmt > ,
58
+ ty : P < ast:: Ty > , span : Span , helper_name : & str ) {
59
+ // Generate statement `let _: helper_name<ty>;`,
60
+ // set the expn ID so we can use the unstable struct.
61
+ let span = super :: allow_unstable ( cx, span, "derive(Eq)" ) ;
62
+ let assert_path = cx. path_all ( span, true ,
63
+ cx. std_path ( & [ "cmp" , helper_name] ) ,
64
+ vec ! [ ] , vec ! [ ty] , vec ! [ ] ) ;
65
+ stmts. push ( cx. stmt_let_type_only ( span, cx. ty_path ( assert_path) ) ) ;
66
+ }
67
+ fn process_variant ( cx : & mut ExtCtxt , stmts : & mut Vec < ast:: Stmt > , variant : & ast:: VariantData ) {
68
+ for field in variant. fields ( ) {
69
+ // let _: AssertParamIsEq<FieldTy>;
70
+ assert_ty_bounds ( cx, stmts, field. ty . clone ( ) , field. span , "AssertParamIsEq" ) ;
71
+ }
72
+ }
73
+
74
+ let mut stmts = Vec :: new ( ) ;
75
+ match * substr. fields {
76
+ StaticStruct ( vdata, ..) => {
77
+ process_variant ( cx, & mut stmts, vdata) ;
78
+ }
79
+ StaticEnum ( enum_def, ..) => {
80
+ for variant in & enum_def. variants {
81
+ process_variant ( cx, & mut stmts, & variant. node . data ) ;
82
+ }
83
+ }
84
+ _ => cx. span_bug ( trait_span, "unexpected substructure in `derive(Eq)`" )
85
+ }
86
+ cx. expr_block ( cx. block ( trait_span, stmts) )
70
87
}
0 commit comments