diff options
| author | bors <bors@rust-lang.org> | 2015-04-18 00:48:34 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2015-04-18 00:48:34 +0000 |
| commit | 1284be4044420bc4c41767284ae26be61a38d331 (patch) | |
| tree | e363960cdf71027e69a8a6c35b5c9150c2eefd22 /src/libsyntax | |
| parent | b08d6cf529a83caec2f408cd8b1287e493ec57ca (diff) | |
| parent | ed437cd8fcbb9ee89849a7eafff94ea97252189e (diff) | |
| download | rust-1284be4044420bc4c41767284ae26be61a38d331.tar.gz rust-1284be4044420bc4c41767284ae26be61a38d331.zip | |
Auto merge of #23985 - erickt:derive-cleanup, r=erickt
This extracts some of the minor cleanup patches from #23905.
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ext/deriving/bounds.rs | 24 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/clone.rs | 11 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/cmp/eq.rs | 97 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/cmp/ord.rs | 185 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/cmp/partial_eq.rs | 94 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/cmp/partial_ord.rs | 237 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/cmp/totaleq.rs | 69 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/cmp/totalord.rs | 142 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/decodable.rs | 35 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/default.rs | 11 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/encodable.rs | 35 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/generic/mod.rs | 11 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/hash.rs | 11 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/mod.rs | 24 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/primitive.rs | 11 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/show.rs | 11 |
16 files changed, 496 insertions, 512 deletions
diff --git a/src/libsyntax/ext/deriving/bounds.rs b/src/libsyntax/ext/deriving/bounds.rs index e408c99935d..eb3debeac99 100644 --- a/src/libsyntax/ext/deriving/bounds.rs +++ b/src/libsyntax/ext/deriving/bounds.rs @@ -15,22 +15,20 @@ use ext::deriving::generic::*; use ext::deriving::generic::ty::*; use ptr::P; -pub fn expand_deriving_unsafe_bound<F>(cx: &mut ExtCtxt, - span: Span, - _: &MetaItem, - _: &Item, - _: F) where - F: FnOnce(P<Item>), +pub fn expand_deriving_unsafe_bound(cx: &mut ExtCtxt, + span: Span, + _: &MetaItem, + _: &Item, + _: &mut FnMut(P<Item>)) { 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>), +pub fn expand_deriving_copy(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: &mut FnMut(P<Item>)) { let path = Path::new(vec![ if cx.use_std { "std" } else { "core" }, @@ -48,5 +46,5 @@ pub fn expand_deriving_copy<F>(cx: &mut ExtCtxt, associated_types: Vec::new(), }; - trait_def.expand(cx, mitem, item, push) + trait_def.expand(cx, mitem, item, push); } diff --git a/src/libsyntax/ext/deriving/clone.rs b/src/libsyntax/ext/deriving/clone.rs index 95eb68ca0d3..97fc3f0bf56 100644 --- a/src/libsyntax/ext/deriving/clone.rs +++ b/src/libsyntax/ext/deriving/clone.rs @@ -17,12 +17,11 @@ use ext::deriving::generic::ty::*; use parse::token::InternedString; use ptr::P; -pub fn expand_deriving_clone<F>(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: F) where - F: FnOnce(P<Item>), +pub fn expand_deriving_clone(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: &mut FnMut(P<Item>)) { let inline = cx.meta_word(span, InternedString::new("inline")); let attrs = vec!(cx.attribute(span, inline)); diff --git a/src/libsyntax/ext/deriving/cmp/eq.rs b/src/libsyntax/ext/deriving/cmp/eq.rs index c02af437b1c..ce8f0a7b32b 100644 --- a/src/libsyntax/ext/deriving/cmp/eq.rs +++ b/src/libsyntax/ext/deriving/cmp/eq.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use ast::{MetaItem, Item, Expr, self}; +use ast::{MetaItem, Item, Expr}; use codemap::Span; use ext::base::ExtCtxt; use ext::build::AstBuilder; @@ -17,77 +17,52 @@ use ext::deriving::generic::ty::*; use parse::token::InternedString; use ptr::P; -pub fn expand_deriving_eq<F>(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: F) where - F: FnOnce(P<Item>), +pub fn expand_deriving_eq(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: &mut FnMut(P<Item>)) { - // structures are equal if all fields are equal, and non equal, if - // any fields are not equal or if the enum variants are different - fn cs_eq(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> { - cs_fold( - true, // use foldl - |cx, span, subexpr, self_f, other_fs| { - let other_f = match other_fs { - [ref o_f] => o_f, - _ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialEq)`") - }; - - let eq = cx.expr_binary(span, ast::BiEq, self_f, other_f.clone()); - - cx.expr_binary(span, ast::BiAnd, subexpr, eq) - }, - cx.expr_bool(span, true), - Box::new(|cx, span, _, _| cx.expr_bool(span, false)), - cx, span, substr) - } - fn cs_ne(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> { - cs_fold( - true, // use foldl - |cx, span, subexpr, self_f, other_fs| { - let other_f = match other_fs { - [ref o_f] => o_f, - _ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialEq)`") - }; - - let eq = cx.expr_binary(span, ast::BiNe, self_f, other_f.clone()); - - cx.expr_binary(span, ast::BiOr, subexpr, eq) + fn cs_total_eq_assert(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> { + cs_same_method( + |cx, span, exprs| { + // create `a.<method>(); b.<method>(); c.<method>(); ...` + // (where method is `assert_receiver_is_total_eq`) + let stmts = exprs.into_iter().map(|e| cx.stmt_expr(e)).collect(); + let block = cx.block(span, stmts, None); + cx.expr_block(block) }, - cx.expr_bool(span, false), - Box::new(|cx, span, _, _| cx.expr_bool(span, true)), - cx, span, substr) + Box::new(|cx, sp, _, _| { + cx.span_bug(sp, "non matching enums in derive(Eq)?") }), + cx, + span, + substr + ) } - macro_rules! md { - ($name:expr, $f:ident) => { { - let inline = cx.meta_word(span, InternedString::new("inline")); - let attrs = vec!(cx.attribute(span, inline)); + let inline = cx.meta_word(span, InternedString::new("inline")); + let hidden = cx.meta_word(span, InternedString::new("hidden")); + let doc = cx.meta_list(span, InternedString::new("doc"), vec!(hidden)); + let attrs = vec!(cx.attribute(span, inline), + cx.attribute(span, doc)); + let trait_def = TraitDef { + span: span, + attributes: Vec::new(), + path: path_std!(cx, core::cmp::Eq), + additional_bounds: Vec::new(), + generics: LifetimeBounds::empty(), + methods: vec!( MethodDef { - name: $name, + name: "assert_receiver_is_total_eq", generics: LifetimeBounds::empty(), explicit_self: borrowed_explicit_self(), - args: vec!(borrowed_self()), - ret_ty: Literal(path_local!(bool)), + args: vec!(), + ret_ty: nil_ty(), attributes: attrs, combine_substructure: combine_substructure(Box::new(|a, b, c| { - $f(a, b, c) + cs_total_eq_assert(a, b, c) })) } - } } - } - - let trait_def = TraitDef { - span: span, - attributes: Vec::new(), - path: path_std!(cx, core::cmp::PartialEq), - additional_bounds: Vec::new(), - generics: LifetimeBounds::empty(), - methods: vec!( - md!("eq", cs_eq), - md!("ne", cs_ne) ), associated_types: Vec::new(), }; diff --git a/src/libsyntax/ext/deriving/cmp/ord.rs b/src/libsyntax/ext/deriving/cmp/ord.rs index 8ecd172b2f0..b2a4ef1dafb 100644 --- a/src/libsyntax/ext/deriving/cmp/ord.rs +++ b/src/libsyntax/ext/deriving/cmp/ord.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub use self::OrderingOp::*; - use ast; use ast::{MetaItem, Item, Expr}; use codemap::Span; @@ -20,114 +18,71 @@ use ext::deriving::generic::ty::*; use parse::token::InternedString; use ptr::P; -pub fn expand_deriving_ord<F>(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: F) where - F: FnOnce(P<Item>), +pub fn expand_deriving_ord(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: &mut FnMut(P<Item>)) { - macro_rules! md { - ($name:expr, $op:expr, $equal:expr) => { { - let inline = cx.meta_word(span, InternedString::new("inline")); - let attrs = vec!(cx.attribute(span, inline)); + let inline = cx.meta_word(span, InternedString::new("inline")); + let attrs = vec!(cx.attribute(span, inline)); + let trait_def = TraitDef { + span: span, + attributes: Vec::new(), + path: path_std!(cx, core::cmp::Ord), + additional_bounds: Vec::new(), + generics: LifetimeBounds::empty(), + methods: vec!( MethodDef { - name: $name, + name: "cmp", generics: LifetimeBounds::empty(), explicit_self: borrowed_explicit_self(), args: vec!(borrowed_self()), - ret_ty: Literal(path_local!(bool)), + ret_ty: Literal(path_std!(cx, core::cmp::Ordering)), attributes: attrs, - combine_substructure: combine_substructure(Box::new(|cx, span, substr| { - cs_op($op, $equal, cx, span, substr) - })) + combine_substructure: combine_substructure(Box::new(|a, b, c| { + cs_cmp(a, b, c) + })), } - } } - } - - let ordering_ty = Literal(path_std!(cx, core::cmp::Ordering)); - let ret_ty = Literal(Path::new_(pathvec_std!(cx, core::option::Option), - None, - vec![box ordering_ty], - true)); - - let inline = cx.meta_word(span, InternedString::new("inline")); - let attrs = vec!(cx.attribute(span, inline)); - - let partial_cmp_def = MethodDef { - name: "partial_cmp", - generics: LifetimeBounds::empty(), - explicit_self: borrowed_explicit_self(), - args: vec![borrowed_self()], - ret_ty: ret_ty, - attributes: attrs, - combine_substructure: combine_substructure(Box::new(|cx, span, substr| { - cs_partial_cmp(cx, span, substr) - })) - }; - - let trait_def = TraitDef { - span: span, - attributes: vec![], - path: path_std!(cx, core::cmp::PartialOrd), - additional_bounds: vec![], - generics: LifetimeBounds::empty(), - methods: vec![ - partial_cmp_def, - md!("lt", true, false), - md!("le", true, true), - md!("gt", false, false), - md!("ge", false, true) - ], + ), associated_types: Vec::new(), }; + trait_def.expand(cx, mitem, item, push) } -#[derive(Copy, Clone)] -pub enum OrderingOp { - PartialCmpOp, LtOp, LeOp, GtOp, GeOp, -} -pub fn some_ordering_collapsed(cx: &mut ExtCtxt, - span: Span, - op: OrderingOp, - self_arg_tags: &[ast::Ident]) -> P<ast::Expr> { +pub fn ordering_collapsed(cx: &mut ExtCtxt, + span: Span, + self_arg_tags: &[ast::Ident]) -> P<ast::Expr> { let lft = cx.expr_ident(span, self_arg_tags[0]); let rgt = cx.expr_addr_of(span, cx.expr_ident(span, self_arg_tags[1])); - let op_str = match op { - PartialCmpOp => "partial_cmp", - LtOp => "lt", LeOp => "le", - GtOp => "gt", GeOp => "ge", - }; - cx.expr_method_call(span, lft, cx.ident_of(op_str), vec![rgt]) + cx.expr_method_call(span, lft, cx.ident_of("cmp"), vec![rgt]) } -pub fn cs_partial_cmp(cx: &mut ExtCtxt, span: Span, +pub fn cs_cmp(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> { let test_id = cx.ident_of("__test"); - let ordering = cx.path_global(span, - vec!(cx.ident_of_std("core"), - cx.ident_of("cmp"), - cx.ident_of("Ordering"), - cx.ident_of("Equal"))); - let ordering = cx.expr_path(ordering); - let equals_expr = cx.expr_some(span, ordering); + let equals_path = cx.path_global(span, + vec!(cx.ident_of_std("core"), + cx.ident_of("cmp"), + cx.ident_of("Ordering"), + cx.ident_of("Equal"))); - let partial_cmp_path = vec![ + let cmp_path = vec![ cx.ident_of_std("core"), cx.ident_of("cmp"), - cx.ident_of("PartialOrd"), - cx.ident_of("partial_cmp"), + cx.ident_of("Ord"), + cx.ident_of("cmp"), ]; /* Builds: - let __test = ::std::cmp::PartialOrd::partial_cmp(&self_field1, &other_field1); - if __test == ::std::option::Option::Some(::std::cmp::Ordering::Equal) { - let __test = ::std::cmp::PartialOrd::partial_cmp(&self_field2, &other_field2); - if __test == ::std::option::Option::Some(::std::cmp::Ordering::Equal) { + let __test = ::std::cmp::Ord::cmp(&self_field1, &other_field1); + if other == ::std::cmp::Ordering::Equal { + let __test = ::std::cmp::Ord::cmp(&self_field2, &other_field2); + if __test == ::std::cmp::Ordering::Equal { ... } else { __test @@ -144,7 +99,7 @@ pub fn cs_partial_cmp(cx: &mut ExtCtxt, span: Span, false, |cx, span, old, self_f, other_fs| { // let __test = new; - // if __test == Some(::std::cmp::Ordering::Equal) { + // if __test == ::std::cmp::Ordering::Equal { // old // } else { // __test @@ -161,77 +116,25 @@ pub fn cs_partial_cmp(cx: &mut ExtCtxt, span: Span, cx.expr_addr_of(span, other_f.clone()), ]; - cx.expr_call_global(span, partial_cmp_path.clone(), args) + cx.expr_call_global(span, cmp_path.clone(), args) }; let assign = cx.stmt_let(span, false, test_id, new); let cond = cx.expr_binary(span, ast::BiEq, cx.expr_ident(span, test_id), - equals_expr.clone()); + cx.expr_path(equals_path.clone())); let if_ = cx.expr_if(span, cond, old, Some(cx.expr_ident(span, test_id))); cx.expr_block(cx.block(span, vec!(assign), Some(if_))) }, - equals_expr.clone(), + cx.expr_path(equals_path.clone()), Box::new(|cx, span, (self_args, tag_tuple), _non_self_args| { if self_args.len() != 2 { - cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`") + cx.span_bug(span, "not exactly 2 arguments in `derives(Ord)`") } else { - some_ordering_collapsed(cx, span, PartialCmpOp, tag_tuple) - } - }), - cx, span, substr) -} - -/// Strict inequality. -fn cs_op(less: bool, equal: bool, cx: &mut ExtCtxt, - span: Span, substr: &Substructure) -> P<Expr> { - let op = if less {ast::BiLt} else {ast::BiGt}; - cs_fold( - false, // need foldr, - |cx, span, subexpr, self_f, other_fs| { - /* - build up a series of chain ||'s and &&'s from the inside - out (hence foldr) to get lexical ordering, i.e. for op == - `ast::lt` - - ``` - self.f1 < other.f1 || (!(other.f1 < self.f1) && - (self.f2 < other.f2 || (!(other.f2 < self.f2) && - (false) - )) - ) - ``` - - The optimiser should remove the redundancy. We explicitly - get use the binops to avoid auto-deref dereferencing too many - layers of pointers, if the type includes pointers. - */ - let other_f = match other_fs { - [ref o_f] => o_f, - _ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`") - }; - - let cmp = cx.expr_binary(span, op, self_f.clone(), other_f.clone()); - - let not_cmp = cx.expr_unary(span, ast::UnNot, - cx.expr_binary(span, op, other_f.clone(), self_f)); - - let and = cx.expr_binary(span, ast::BiAnd, not_cmp, subexpr); - cx.expr_binary(span, ast::BiOr, cmp, and) - }, - cx.expr_bool(span, equal), - Box::new(|cx, span, (self_args, tag_tuple), _non_self_args| { - if self_args.len() != 2 { - cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`") - } else { - let op = match (less, equal) { - (true, true) => LeOp, (true, false) => LtOp, - (false, true) => GeOp, (false, false) => GtOp, - }; - some_ordering_collapsed(cx, span, op, tag_tuple) + ordering_collapsed(cx, span, tag_tuple) } }), cx, span, substr) diff --git a/src/libsyntax/ext/deriving/cmp/partial_eq.rs b/src/libsyntax/ext/deriving/cmp/partial_eq.rs new file mode 100644 index 00000000000..f02e5ee1412 --- /dev/null +++ b/src/libsyntax/ext/deriving/cmp/partial_eq.rs @@ -0,0 +1,94 @@ +// Copyright 2013 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. + +use ast::{MetaItem, Item, Expr, self}; +use codemap::Span; +use ext::base::ExtCtxt; +use ext::build::AstBuilder; +use ext::deriving::generic::*; +use ext::deriving::generic::ty::*; +use parse::token::InternedString; +use ptr::P; + +pub fn expand_deriving_partial_eq(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: &mut FnMut(P<Item>)) +{ + // structures are equal if all fields are equal, and non equal, if + // any fields are not equal or if the enum variants are different + fn cs_eq(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> { + cs_fold( + true, // use foldl + |cx, span, subexpr, self_f, other_fs| { + let other_f = match other_fs { + [ref o_f] => o_f, + _ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialEq)`") + }; + + let eq = cx.expr_binary(span, ast::BiEq, self_f, other_f.clone()); + + cx.expr_binary(span, ast::BiAnd, subexpr, eq) + }, + cx.expr_bool(span, true), + Box::new(|cx, span, _, _| cx.expr_bool(span, false)), + cx, span, substr) + } + fn cs_ne(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> { + cs_fold( + true, // use foldl + |cx, span, subexpr, self_f, other_fs| { + let other_f = match other_fs { + [ref o_f] => o_f, + _ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialEq)`") + }; + + let eq = cx.expr_binary(span, ast::BiNe, self_f, other_f.clone()); + + cx.expr_binary(span, ast::BiOr, subexpr, eq) + }, + cx.expr_bool(span, false), + Box::new(|cx, span, _, _| cx.expr_bool(span, true)), + cx, span, substr) + } + + macro_rules! md { + ($name:expr, $f:ident) => { { + let inline = cx.meta_word(span, InternedString::new("inline")); + let attrs = vec!(cx.attribute(span, inline)); + MethodDef { + name: $name, + generics: LifetimeBounds::empty(), + explicit_self: borrowed_explicit_self(), + args: vec!(borrowed_self()), + ret_ty: Literal(path_local!(bool)), + attributes: attrs, + combine_substructure: combine_substructure(Box::new(|a, b, c| { + $f(a, b, c) + })) + } + } } + } + + let trait_def = TraitDef { + span: span, + attributes: Vec::new(), + path: path_std!(cx, core::cmp::PartialEq), + additional_bounds: Vec::new(), + generics: LifetimeBounds::empty(), + methods: vec!( + md!("eq", cs_eq), + md!("ne", cs_ne) + ), + associated_types: Vec::new(), + }; + trait_def.expand(cx, mitem, item, push) +} diff --git a/src/libsyntax/ext/deriving/cmp/partial_ord.rs b/src/libsyntax/ext/deriving/cmp/partial_ord.rs new file mode 100644 index 00000000000..9da2db25f7e --- /dev/null +++ b/src/libsyntax/ext/deriving/cmp/partial_ord.rs @@ -0,0 +1,237 @@ +// Copyright 2013 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. + +pub use self::OrderingOp::*; + +use ast; +use ast::{MetaItem, Item, Expr}; +use codemap::Span; +use ext::base::ExtCtxt; +use ext::build::AstBuilder; +use ext::deriving::generic::*; +use ext::deriving::generic::ty::*; +use parse::token::InternedString; +use ptr::P; + +pub fn expand_deriving_partial_ord(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: &mut FnMut(P<Item>)) +{ + macro_rules! md { + ($name:expr, $op:expr, $equal:expr) => { { + let inline = cx.meta_word(span, InternedString::new("inline")); + let attrs = vec!(cx.attribute(span, inline)); + MethodDef { + name: $name, + generics: LifetimeBounds::empty(), + explicit_self: borrowed_explicit_self(), + args: vec!(borrowed_self()), + ret_ty: Literal(path_local!(bool)), + attributes: attrs, + combine_substructure: combine_substructure(Box::new(|cx, span, substr| { + cs_op($op, $equal, cx, span, substr) + })) + } + } } + } + + let ordering_ty = Literal(path_std!(cx, core::cmp::Ordering)); + let ret_ty = Literal(Path::new_(pathvec_std!(cx, core::option::Option), + None, + vec![box ordering_ty], + true)); + + let inline = cx.meta_word(span, InternedString::new("inline")); + let attrs = vec!(cx.attribute(span, inline)); + + let partial_cmp_def = MethodDef { + name: "partial_cmp", + generics: LifetimeBounds::empty(), + explicit_self: borrowed_explicit_self(), + args: vec![borrowed_self()], + ret_ty: ret_ty, + attributes: attrs, + combine_substructure: combine_substructure(Box::new(|cx, span, substr| { + cs_partial_cmp(cx, span, substr) + })) + }; + + let trait_def = TraitDef { + span: span, + attributes: vec![], + path: path_std!(cx, core::cmp::PartialOrd), + additional_bounds: vec![], + generics: LifetimeBounds::empty(), + methods: vec![ + partial_cmp_def, + md!("lt", true, false), + md!("le", true, true), + md!("gt", false, false), + md!("ge", false, true) + ], + associated_types: Vec::new(), + }; + trait_def.expand(cx, mitem, item, push) +} + +#[derive(Copy, Clone)] +pub enum OrderingOp { + PartialCmpOp, LtOp, LeOp, GtOp, GeOp, +} + +pub fn some_ordering_collapsed(cx: &mut ExtCtxt, + span: Span, + op: OrderingOp, + self_arg_tags: &[ast::Ident]) -> P<ast::Expr> { + let lft = cx.expr_ident(span, self_arg_tags[0]); + let rgt = cx.expr_addr_of(span, cx.expr_ident(span, self_arg_tags[1])); + let op_str = match op { + PartialCmpOp => "partial_cmp", + LtOp => "lt", LeOp => "le", + GtOp => "gt", GeOp => "ge", + }; + cx.expr_method_call(span, lft, cx.ident_of(op_str), vec![rgt]) +} + +pub fn cs_partial_cmp(cx: &mut ExtCtxt, span: Span, + substr: &Substructure) -> P<Expr> { + let test_id = cx.ident_of("__test"); + let ordering = cx.path_global(span, + vec!(cx.ident_of_std("core"), + cx.ident_of("cmp"), + cx.ident_of("Ordering"), + cx.ident_of("Equal"))); + let ordering = cx.expr_path(ordering); + let equals_expr = cx.expr_some(span, ordering); + + let partial_cmp_path = vec![ + cx.ident_of_std("core"), + cx.ident_of("cmp"), + cx.ident_of("PartialOrd"), + cx.ident_of("partial_cmp"), + ]; + + /* + Builds: + + let __test = ::std::cmp::PartialOrd::partial_cmp(&self_field1, &other_field1); + if __test == ::std::option::Option::Some(::std::cmp::Ordering::Equal) { + let __test = ::std::cmp::PartialOrd::partial_cmp(&self_field2, &other_field2); + if __test == ::std::option::Option::Some(::std::cmp::Ordering::Equal) { + ... + } else { + __test + } + } else { + __test + } + + FIXME #6449: These `if`s could/should be `match`es. + */ + cs_fold( + // foldr nests the if-elses correctly, leaving the first field + // as the outermost one, and the last as the innermost. + false, + |cx, span, old, self_f, other_fs| { + // let __test = new; + // if __test == Some(::std::cmp::Ordering::Equal) { + // old + // } else { + // __test + // } + + let new = { + let other_f = match other_fs { + [ref o_f] => o_f, + _ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`"), + }; + + let args = vec![ + cx.expr_addr_of(span, self_f), + cx.expr_addr_of(span, other_f.clone()), + ]; + + cx.expr_call_global(span, partial_cmp_path.clone(), args) + }; + + let assign = cx.stmt_let(span, false, test_id, new); + + let cond = cx.expr_binary(span, ast::BiEq, + cx.expr_ident(span, test_id), + equals_expr.clone()); + let if_ = cx.expr_if(span, + cond, + old, Some(cx.expr_ident(span, test_id))); + cx.expr_block(cx.block(span, vec!(assign), Some(if_))) + }, + equals_expr.clone(), + Box::new(|cx, span, (self_args, tag_tuple), _non_self_args| { + if self_args.len() != 2 { + cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`") + } else { + some_ordering_collapsed(cx, span, PartialCmpOp, tag_tuple) + } + }), + cx, span, substr) +} + +/// Strict inequality. +fn cs_op(less: bool, equal: bool, cx: &mut ExtCtxt, + span: Span, substr: &Substructure) -> P<Expr> { + let op = if less {ast::BiLt} else {ast::BiGt}; + cs_fold( + false, // need foldr, + |cx, span, subexpr, self_f, other_fs| { + /* + build up a series of chain ||'s and &&'s from the inside + out (hence foldr) to get lexical ordering, i.e. for op == + `ast::lt` + + ``` + self.f1 < other.f1 || (!(other.f1 < self.f1) && + (self.f2 < other.f2 || (!(other.f2 < self.f2) && + (false) + )) + ) + ``` + + The optimiser should remove the redundancy. We explicitly + get use the binops to avoid auto-deref dereferencing too many + layers of pointers, if the type includes pointers. + */ + let other_f = match other_fs { + [ref o_f] => o_f, + _ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`") + }; + + let cmp = cx.expr_binary(span, op, self_f.clone(), other_f.clone()); + + let not_cmp = cx.expr_unary(span, ast::UnNot, + cx.expr_binary(span, op, other_f.clone(), self_f)); + + let and = cx.expr_binary(span, ast::BiAnd, not_cmp, subexpr); + cx.expr_binary(span, ast::BiOr, cmp, and) + }, + cx.expr_bool(span, equal), + Box::new(|cx, span, (self_args, tag_tuple), _non_self_args| { + if self_args.len() != 2 { + cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`") + } else { + let op = match (less, equal) { + (true, true) => LeOp, (true, false) => LtOp, + (false, true) => GeOp, (false, false) => GtOp, + }; + some_ordering_collapsed(cx, span, op, tag_tuple) + } + }), + cx, span, substr) +} diff --git a/src/libsyntax/ext/deriving/cmp/totaleq.rs b/src/libsyntax/ext/deriving/cmp/totaleq.rs deleted file mode 100644 index 83164d242e8..00000000000 --- a/src/libsyntax/ext/deriving/cmp/totaleq.rs +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2013 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. - -use ast::{MetaItem, Item, Expr}; -use codemap::Span; -use ext::base::ExtCtxt; -use ext::build::AstBuilder; -use ext::deriving::generic::*; -use ext::deriving::generic::ty::*; -use parse::token::InternedString; -use ptr::P; - -pub fn expand_deriving_totaleq<F>(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: F) where - F: FnOnce(P<Item>), -{ - fn cs_total_eq_assert(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> { - cs_same_method(|cx, span, exprs| { - // create `a.<method>(); b.<method>(); c.<method>(); ...` - // (where method is `assert_receiver_is_total_eq`) - let stmts = exprs.into_iter().map(|e| cx.stmt_expr(e)).collect(); - let block = cx.block(span, stmts, None); - cx.expr_block(block) - }, - Box::new(|cx, sp, _, _| { - cx.span_bug(sp, "non matching enums in derive(Eq)?") }), - cx, - span, - substr) - } - - let inline = cx.meta_word(span, InternedString::new("inline")); - let hidden = cx.meta_word(span, InternedString::new("hidden")); - let doc = cx.meta_list(span, InternedString::new("doc"), vec!(hidden)); - let attrs = vec!(cx.attribute(span, inline), - cx.attribute(span, doc)); - let trait_def = TraitDef { - span: span, - attributes: Vec::new(), - path: path_std!(cx, core::cmp::Eq), - additional_bounds: Vec::new(), - generics: LifetimeBounds::empty(), - methods: vec!( - MethodDef { - name: "assert_receiver_is_total_eq", - generics: LifetimeBounds::empty(), - explicit_self: borrowed_explicit_self(), - args: vec!(), - ret_ty: nil_ty(), - attributes: attrs, - combine_substructure: combine_substructure(Box::new(|a, b, c| { - cs_total_eq_assert(a, b, c) - })) - } - ), - associated_types: Vec::new(), - }; - trait_def.expand(cx, mitem, item, push) -} diff --git a/src/libsyntax/ext/deriving/cmp/totalord.rs b/src/libsyntax/ext/deriving/cmp/totalord.rs deleted file mode 100644 index 1de955856e7..00000000000 --- a/src/libsyntax/ext/deriving/cmp/totalord.rs +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright 2013 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. - -use ast; -use ast::{MetaItem, Item, Expr}; -use codemap::Span; -use ext::base::ExtCtxt; -use ext::build::AstBuilder; -use ext::deriving::generic::*; -use ext::deriving::generic::ty::*; -use parse::token::InternedString; -use ptr::P; - -pub fn expand_deriving_totalord<F>(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: F) where - F: FnOnce(P<Item>), -{ - let inline = cx.meta_word(span, InternedString::new("inline")); - let attrs = vec!(cx.attribute(span, inline)); - let trait_def = TraitDef { - span: span, - attributes: Vec::new(), - path: path_std!(cx, core::cmp::Ord), - additional_bounds: Vec::new(), - generics: LifetimeBounds::empty(), - methods: vec!( - MethodDef { - name: "cmp", - generics: LifetimeBounds::empty(), - explicit_self: borrowed_explicit_self(), - args: vec!(borrowed_self()), - ret_ty: Literal(path_std!(cx, core::cmp::Ordering)), - attributes: attrs, - combine_substructure: combine_substructure(Box::new(|a, b, c| { - cs_cmp(a, b, c) - })), - } - ), - associated_types: Vec::new(), - }; - - trait_def.expand(cx, mitem, item, push) -} - - -pub fn ordering_collapsed(cx: &mut ExtCtxt, - span: Span, - self_arg_tags: &[ast::Ident]) -> P<ast::Expr> { - let lft = cx.expr_ident(span, self_arg_tags[0]); - let rgt = cx.expr_addr_of(span, cx.expr_ident(span, self_arg_tags[1])); - cx.expr_method_call(span, lft, cx.ident_of("cmp"), vec![rgt]) -} - -pub fn cs_cmp(cx: &mut ExtCtxt, span: Span, - substr: &Substructure) -> P<Expr> { - let test_id = cx.ident_of("__test"); - let equals_path = cx.path_global(span, - vec!(cx.ident_of_std("core"), - cx.ident_of("cmp"), - cx.ident_of("Ordering"), - cx.ident_of("Equal"))); - - let cmp_path = vec![ - cx.ident_of_std("core"), - cx.ident_of("cmp"), - cx.ident_of("Ord"), - cx.ident_of("cmp"), - ]; - - /* - Builds: - - let __test = ::std::cmp::Ord::cmp(&self_field1, &other_field1); - if other == ::std::cmp::Ordering::Equal { - let __test = ::std::cmp::Ord::cmp(&self_field2, &other_field2); - if __test == ::std::cmp::Ordering::Equal { - ... - } else { - __test - } - } else { - __test - } - - FIXME #6449: These `if`s could/should be `match`es. - */ - cs_fold( - // foldr nests the if-elses correctly, leaving the first field - // as the outermost one, and the last as the innermost. - false, - |cx, span, old, self_f, other_fs| { - // let __test = new; - // if __test == ::std::cmp::Ordering::Equal { - // old - // } else { - // __test - // } - - let new = { - let other_f = match other_fs { - [ref o_f] => o_f, - _ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`"), - }; - - let args = vec![ - cx.expr_addr_of(span, self_f), - cx.expr_addr_of(span, other_f.clone()), - ]; - - cx.expr_call_global(span, cmp_path.clone(), args) - }; - - let assign = cx.stmt_let(span, false, test_id, new); - - let cond = cx.expr_binary(span, ast::BiEq, - cx.expr_ident(span, test_id), - cx.expr_path(equals_path.clone())); - let if_ = cx.expr_if(span, - cond, - old, Some(cx.expr_ident(span, test_id))); - cx.expr_block(cx.block(span, vec!(assign), Some(if_))) - }, - cx.expr_path(equals_path.clone()), - Box::new(|cx, span, (self_args, tag_tuple), _non_self_args| { - if self_args.len() != 2 { - cx.span_bug(span, "not exactly 2 arguments in `derives(Ord)`") - } else { - ordering_collapsed(cx, span, tag_tuple) - } - }), - cx, span, substr) -} diff --git a/src/libsyntax/ext/deriving/decodable.rs b/src/libsyntax/ext/deriving/decodable.rs index 6ce68948e4b..14f0004101c 100644 --- a/src/libsyntax/ext/deriving/decodable.rs +++ b/src/libsyntax/ext/deriving/decodable.rs @@ -21,33 +21,30 @@ use parse::token::InternedString; use parse::token; use ptr::P; -pub fn expand_deriving_rustc_decodable<F>(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: F) where - F: FnOnce(P<Item>), +pub fn expand_deriving_rustc_decodable(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: &mut FnMut(P<Item>)) { expand_deriving_decodable_imp(cx, span, mitem, item, push, "rustc_serialize") } -pub fn expand_deriving_decodable<F>(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: F) where - F: FnOnce(P<Item>), +pub fn expand_deriving_decodable(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: &mut FnMut(P<Item>)) { expand_deriving_decodable_imp(cx, span, mitem, item, push, "serialize") } -fn expand_deriving_decodable_imp<F>(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: F, - krate: &'static str) where - F: FnOnce(P<Item>), +fn expand_deriving_decodable_imp(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: &mut FnMut(P<Item>), + krate: &'static str) { if !cx.use_std { // FIXME(#21880): lift this requirement. diff --git a/src/libsyntax/ext/deriving/default.rs b/src/libsyntax/ext/deriving/default.rs index f9991a23354..f04eaa08dea 100644 --- a/src/libsyntax/ext/deriving/default.rs +++ b/src/libsyntax/ext/deriving/default.rs @@ -17,12 +17,11 @@ use ext::deriving::generic::ty::*; use parse::token::InternedString; use ptr::P; -pub fn expand_deriving_default<F>(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: F) where - F: FnOnce(P<Item>), +pub fn expand_deriving_default(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: &mut FnMut(P<Item>)) { let inline = cx.meta_word(span, InternedString::new("inline")); let attrs = vec!(cx.attribute(span, inline)); diff --git a/src/libsyntax/ext/deriving/encodable.rs b/src/libsyntax/ext/deriving/encodable.rs index 6425e6a28ec..175f986f6dd 100644 --- a/src/libsyntax/ext/deriving/encodable.rs +++ b/src/libsyntax/ext/deriving/encodable.rs @@ -97,33 +97,30 @@ use ext::deriving::generic::ty::*; use parse::token; use ptr::P; -pub fn expand_deriving_rustc_encodable<F>(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: F) where - F: FnOnce(P<Item>), +pub fn expand_deriving_rustc_encodable(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: &mut FnMut(P<Item>)) { expand_deriving_encodable_imp(cx, span, mitem, item, push, "rustc_serialize") } -pub fn expand_deriving_encodable<F>(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: F) where - F: FnOnce(P<Item>), +pub fn expand_deriving_encodable(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: &mut FnMut(P<Item>)) { expand_deriving_encodable_imp(cx, span, mitem, item, push, "serialize") } -fn expand_deriving_encodable_imp<F>(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: F, - krate: &'static str) where - F: FnOnce(P<Item>), +fn expand_deriving_encodable_imp(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: &mut FnMut(P<Item>), + krate: &'static str) { if !cx.use_std { // FIXME(#21880): lift this requirement. diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs index 7f6f29df530..4685b4b2954 100644 --- a/src/libsyntax/ext/deriving/generic/mod.rs +++ b/src/libsyntax/ext/deriving/generic/mod.rs @@ -375,12 +375,11 @@ fn find_type_parameters(ty: &ast::Ty, ty_param_names: &[ast::Name]) -> Vec<P<ast } impl<'a> TraitDef<'a> { - pub fn expand<F>(&self, - cx: &mut ExtCtxt, - mitem: &ast::MetaItem, - item: &ast::Item, - push: F) where - F: FnOnce(P<ast::Item>), + pub fn expand(&self, + cx: &mut ExtCtxt, + mitem: &ast::MetaItem, + item: &ast::Item, + push: &mut FnMut(P<ast::Item>)) { let newitem = match item.node { ast::ItemStruct(ref struct_def, ref generics) => { diff --git a/src/libsyntax/ext/deriving/hash.rs b/src/libsyntax/ext/deriving/hash.rs index da80c7a0e6d..2f6734b1a14 100644 --- a/src/libsyntax/ext/deriving/hash.rs +++ b/src/libsyntax/ext/deriving/hash.rs @@ -16,12 +16,11 @@ use ext::deriving::generic::*; use ext::deriving::generic::ty::*; use ptr::P; -pub fn expand_deriving_hash<F>(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: F) where - F: FnOnce(P<Item>), +pub fn expand_deriving_hash(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: &mut FnMut(P<Item>)) { let path = Path::new_(pathvec_std!(cx, core::hash::Hash), None, diff --git a/src/libsyntax/ext/deriving/mod.rs b/src/libsyntax/ext/deriving/mod.rs index 65554efdd68..a3725355840 100644 --- a/src/libsyntax/ext/deriving/mod.rs +++ b/src/libsyntax/ext/deriving/mod.rs @@ -65,14 +65,14 @@ pub mod show; pub mod default; pub mod primitive; +#[path="cmp/partial_eq.rs"] +pub mod partial_eq; #[path="cmp/eq.rs"] pub mod eq; -#[path="cmp/totaleq.rs"] -pub mod totaleq; +#[path="cmp/partial_ord.rs"] +pub mod partial_ord; #[path="cmp/ord.rs"] pub mod ord; -#[path="cmp/totalord.rs"] -pub mod totalord; pub mod generic; @@ -118,7 +118,7 @@ fn expand_derive(cx: &mut ExtCtxt, } macro_rules! derive_traits { - ($( $name:expr => $func:path, )*) => { + ($( $name:expr => $func:path, )+) => { pub fn register_all(env: &mut SyntaxEnv) { // Define the #[derive_*] extensions. $({ @@ -132,13 +132,13 @@ macro_rules! derive_traits { item: &Item, push: &mut FnMut(P<Item>)) { warn_if_deprecated(ecx, sp, $name); - $func(ecx, sp, mitem, item, |i| push(i)); + $func(ecx, sp, mitem, item, push); } } env.insert(intern(concat!("derive_", $name)), Decorator(Box::new(DeriveExtension))); - })* + })+ env.insert(intern("derive"), Modifier(Box::new(expand_derive))); @@ -146,7 +146,7 @@ macro_rules! derive_traits { fn is_builtin_trait(name: &str) -> bool { match name { - $( $name )|* => true, + $( $name )|+ => true, _ => false, } } @@ -162,10 +162,10 @@ derive_traits! { "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, + "PartialEq" => partial_eq::expand_deriving_partial_eq, + "Eq" => eq::expand_deriving_eq, + "PartialOrd" => partial_ord::expand_deriving_partial_ord, + "Ord" => ord::expand_deriving_ord, "Debug" => show::expand_deriving_show, diff --git a/src/libsyntax/ext/deriving/primitive.rs b/src/libsyntax/ext/deriving/primitive.rs index b2d0a9f6b51..625f759fced 100644 --- a/src/libsyntax/ext/deriving/primitive.rs +++ b/src/libsyntax/ext/deriving/primitive.rs @@ -18,12 +18,11 @@ use ext::deriving::generic::ty::*; use parse::token::InternedString; use ptr::P; -pub fn expand_deriving_from_primitive<F>(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: F) where - F: FnOnce(P<Item>), +pub fn expand_deriving_from_primitive(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: &mut FnMut(P<Item>)) { let inline = cx.meta_word(span, InternedString::new("inline")); let attrs = vec!(cx.attribute(span, inline)); diff --git a/src/libsyntax/ext/deriving/show.rs b/src/libsyntax/ext/deriving/show.rs index ae9a4020060..f3b0e8a7681 100644 --- a/src/libsyntax/ext/deriving/show.rs +++ b/src/libsyntax/ext/deriving/show.rs @@ -18,12 +18,11 @@ use ext::deriving::generic::ty::*; use parse::token; use ptr::P; -pub fn expand_deriving_show<F>(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: F) where - F: FnOnce(P<Item>), +pub fn expand_deriving_show(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: &mut FnMut(P<Item>)) { // &mut ::std::fmt::Formatter let fmtr = Ptr(box Literal(path_std!(cx, core::fmt::Formatter)), |
