1111use deriving:: generic:: * ;
1212use deriving:: generic:: ty:: * ;
1313
14- use syntax:: ast:: { Expr , MetaItem } ;
14+ use syntax:: ast:: { self , Expr , MetaItem } ;
1515use syntax:: ext:: base:: { Annotatable , ExtCtxt } ;
1616use syntax:: ext:: build:: AstBuilder ;
1717use syntax:: parse:: token:: InternedString ;
@@ -23,22 +23,6 @@ pub fn expand_deriving_eq(cx: &mut ExtCtxt,
2323 mitem : & MetaItem ,
2424 item : & Annotatable ,
2525 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-
4226 let inline = cx. meta_word ( span, InternedString :: new ( "inline" ) ) ;
4327 let hidden = cx. meta_list_item_word ( span, InternedString :: new ( "hidden" ) ) ;
4428 let doc = cx. meta_list ( span, InternedString :: new ( "doc" ) , vec ! [ hidden] ) ;
@@ -50,7 +34,7 @@ pub fn expand_deriving_eq(cx: &mut ExtCtxt,
5034 additional_bounds : Vec :: new ( ) ,
5135 generics : LifetimeBounds :: empty ( ) ,
5236 is_unsafe : false ,
53- supports_unions : false ,
37+ supports_unions : true ,
5438 methods : vec ! [ MethodDef {
5539 name: "assert_receiver_is_total_eq" ,
5640 generics: LifetimeBounds :: empty( ) ,
@@ -66,5 +50,38 @@ pub fn expand_deriving_eq(cx: &mut ExtCtxt,
6650 } ] ,
6751 associated_types : Vec :: new ( ) ,
6852 } ;
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) )
7087}
0 commit comments