Auto merge of #23985 - erickt:derive-cleanup, r=erickt
This extracts some of the minor cleanup patches from #23905.
This commit is contained in:
@@ -15,22 +15,20 @@ use ext::deriving::generic::*;
|
|||||||
use ext::deriving::generic::ty::*;
|
use ext::deriving::generic::ty::*;
|
||||||
use ptr::P;
|
use ptr::P;
|
||||||
|
|
||||||
pub fn expand_deriving_unsafe_bound<F>(cx: &mut ExtCtxt,
|
pub fn expand_deriving_unsafe_bound(cx: &mut ExtCtxt,
|
||||||
span: Span,
|
span: Span,
|
||||||
_: &MetaItem,
|
_: &MetaItem,
|
||||||
_: &Item,
|
_: &Item,
|
||||||
_: F) where
|
_: &mut FnMut(P<Item>))
|
||||||
F: FnOnce(P<Item>),
|
|
||||||
{
|
{
|
||||||
cx.span_err(span, "this unsafe trait should be implemented explicitly");
|
cx.span_err(span, "this unsafe trait should be implemented explicitly");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn expand_deriving_copy<F>(cx: &mut ExtCtxt,
|
pub fn expand_deriving_copy(cx: &mut ExtCtxt,
|
||||||
span: Span,
|
span: Span,
|
||||||
mitem: &MetaItem,
|
mitem: &MetaItem,
|
||||||
item: &Item,
|
item: &Item,
|
||||||
push: F) where
|
push: &mut FnMut(P<Item>))
|
||||||
F: FnOnce(P<Item>),
|
|
||||||
{
|
{
|
||||||
let path = Path::new(vec![
|
let path = Path::new(vec![
|
||||||
if cx.use_std { "std" } else { "core" },
|
if cx.use_std { "std" } else { "core" },
|
||||||
@@ -48,5 +46,5 @@ pub fn expand_deriving_copy<F>(cx: &mut ExtCtxt,
|
|||||||
associated_types: Vec::new(),
|
associated_types: Vec::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
trait_def.expand(cx, mitem, item, push)
|
trait_def.expand(cx, mitem, item, push);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,12 +17,11 @@ use ext::deriving::generic::ty::*;
|
|||||||
use parse::token::InternedString;
|
use parse::token::InternedString;
|
||||||
use ptr::P;
|
use ptr::P;
|
||||||
|
|
||||||
pub fn expand_deriving_clone<F>(cx: &mut ExtCtxt,
|
pub fn expand_deriving_clone(cx: &mut ExtCtxt,
|
||||||
span: Span,
|
span: Span,
|
||||||
mitem: &MetaItem,
|
mitem: &MetaItem,
|
||||||
item: &Item,
|
item: &Item,
|
||||||
push: F) where
|
push: &mut FnMut(P<Item>))
|
||||||
F: FnOnce(P<Item>),
|
|
||||||
{
|
{
|
||||||
let inline = cx.meta_word(span, InternedString::new("inline"));
|
let inline = cx.meta_word(span, InternedString::new("inline"));
|
||||||
let attrs = vec!(cx.attribute(span, inline));
|
let attrs = vec!(cx.attribute(span, inline));
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use ast::{MetaItem, Item, Expr, self};
|
use ast::{MetaItem, Item, Expr};
|
||||||
use codemap::Span;
|
use codemap::Span;
|
||||||
use ext::base::ExtCtxt;
|
use ext::base::ExtCtxt;
|
||||||
use ext::build::AstBuilder;
|
use ext::build::AstBuilder;
|
||||||
@@ -17,77 +17,52 @@ use ext::deriving::generic::ty::*;
|
|||||||
use parse::token::InternedString;
|
use parse::token::InternedString;
|
||||||
use ptr::P;
|
use ptr::P;
|
||||||
|
|
||||||
pub fn expand_deriving_eq<F>(cx: &mut ExtCtxt,
|
pub fn expand_deriving_eq(cx: &mut ExtCtxt,
|
||||||
span: Span,
|
span: Span,
|
||||||
mitem: &MetaItem,
|
mitem: &MetaItem,
|
||||||
item: &Item,
|
item: &Item,
|
||||||
push: F) where
|
push: &mut FnMut(P<Item>))
|
||||||
F: FnOnce(P<Item>),
|
|
||||||
{
|
{
|
||||||
// structures are equal if all fields are equal, and non equal, if
|
fn cs_total_eq_assert(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> {
|
||||||
// any fields are not equal or if the enum variants are different
|
cs_same_method(
|
||||||
fn cs_eq(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> {
|
|cx, span, exprs| {
|
||||||
cs_fold(
|
// create `a.<method>(); b.<method>(); c.<method>(); ...`
|
||||||
true, // use foldl
|
// (where method is `assert_receiver_is_total_eq`)
|
||||||
|cx, span, subexpr, self_f, other_fs| {
|
let stmts = exprs.into_iter().map(|e| cx.stmt_expr(e)).collect();
|
||||||
let other_f = match other_fs {
|
let block = cx.block(span, stmts, None);
|
||||||
[ref o_f] => o_f,
|
cx.expr_block(block)
|
||||||
_ => 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, sp, _, _| {
|
||||||
Box::new(|cx, span, _, _| cx.expr_bool(span, false)),
|
cx.span_bug(sp, "non matching enums in derive(Eq)?") }),
|
||||||
cx, span, substr)
|
cx,
|
||||||
}
|
span,
|
||||||
fn cs_ne(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> {
|
substr
|
||||||
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 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 {
|
let trait_def = TraitDef {
|
||||||
span: span,
|
span: span,
|
||||||
attributes: Vec::new(),
|
attributes: Vec::new(),
|
||||||
path: path_std!(cx, core::cmp::PartialEq),
|
path: path_std!(cx, core::cmp::Eq),
|
||||||
additional_bounds: Vec::new(),
|
additional_bounds: Vec::new(),
|
||||||
generics: LifetimeBounds::empty(),
|
generics: LifetimeBounds::empty(),
|
||||||
methods: vec!(
|
methods: vec!(
|
||||||
md!("eq", cs_eq),
|
MethodDef {
|
||||||
md!("ne", cs_ne)
|
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(),
|
associated_types: Vec::new(),
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -8,8 +8,6 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
pub use self::OrderingOp::*;
|
|
||||||
|
|
||||||
use ast;
|
use ast;
|
||||||
use ast::{MetaItem, Item, Expr};
|
use ast::{MetaItem, Item, Expr};
|
||||||
use codemap::Span;
|
use codemap::Span;
|
||||||
@@ -20,114 +18,71 @@ use ext::deriving::generic::ty::*;
|
|||||||
use parse::token::InternedString;
|
use parse::token::InternedString;
|
||||||
use ptr::P;
|
use ptr::P;
|
||||||
|
|
||||||
pub fn expand_deriving_ord<F>(cx: &mut ExtCtxt,
|
pub fn expand_deriving_ord(cx: &mut ExtCtxt,
|
||||||
span: Span,
|
span: Span,
|
||||||
mitem: &MetaItem,
|
mitem: &MetaItem,
|
||||||
item: &Item,
|
item: &Item,
|
||||||
push: F) where
|
push: &mut FnMut(P<Item>))
|
||||||
F: FnOnce(P<Item>),
|
|
||||||
{
|
{
|
||||||
macro_rules! md {
|
let inline = cx.meta_word(span, InternedString::new("inline"));
|
||||||
($name:expr, $op:expr, $equal:expr) => { {
|
let attrs = vec!(cx.attribute(span, inline));
|
||||||
let inline = cx.meta_word(span, InternedString::new("inline"));
|
let trait_def = TraitDef {
|
||||||
let attrs = vec!(cx.attribute(span, inline));
|
span: span,
|
||||||
|
attributes: Vec::new(),
|
||||||
|
path: path_std!(cx, core::cmp::Ord),
|
||||||
|
additional_bounds: Vec::new(),
|
||||||
|
generics: LifetimeBounds::empty(),
|
||||||
|
methods: vec!(
|
||||||
MethodDef {
|
MethodDef {
|
||||||
name: $name,
|
name: "cmp",
|
||||||
generics: LifetimeBounds::empty(),
|
generics: LifetimeBounds::empty(),
|
||||||
explicit_self: borrowed_explicit_self(),
|
explicit_self: borrowed_explicit_self(),
|
||||||
args: vec!(borrowed_self()),
|
args: vec!(borrowed_self()),
|
||||||
ret_ty: Literal(path_local!(bool)),
|
ret_ty: Literal(path_std!(cx, core::cmp::Ordering)),
|
||||||
attributes: attrs,
|
attributes: attrs,
|
||||||
combine_substructure: combine_substructure(Box::new(|cx, span, substr| {
|
combine_substructure: combine_substructure(Box::new(|a, b, c| {
|
||||||
cs_op($op, $equal, cx, span, substr)
|
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(),
|
associated_types: Vec::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
trait_def.expand(cx, mitem, item, push)
|
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,
|
pub fn ordering_collapsed(cx: &mut ExtCtxt,
|
||||||
span: Span,
|
span: Span,
|
||||||
op: OrderingOp,
|
self_arg_tags: &[ast::Ident]) -> P<ast::Expr> {
|
||||||
self_arg_tags: &[ast::Ident]) -> P<ast::Expr> {
|
|
||||||
let lft = cx.expr_ident(span, self_arg_tags[0]);
|
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 rgt = cx.expr_addr_of(span, cx.expr_ident(span, self_arg_tags[1]));
|
||||||
let op_str = match op {
|
cx.expr_method_call(span, lft, cx.ident_of("cmp"), vec![rgt])
|
||||||
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,
|
pub fn cs_cmp(cx: &mut ExtCtxt, span: Span,
|
||||||
substr: &Substructure) -> P<Expr> {
|
substr: &Substructure) -> P<Expr> {
|
||||||
let test_id = cx.ident_of("__test");
|
let test_id = cx.ident_of("__test");
|
||||||
let ordering = cx.path_global(span,
|
let equals_path = cx.path_global(span,
|
||||||
vec!(cx.ident_of_std("core"),
|
vec!(cx.ident_of_std("core"),
|
||||||
cx.ident_of("cmp"),
|
cx.ident_of("cmp"),
|
||||||
cx.ident_of("Ordering"),
|
cx.ident_of("Ordering"),
|
||||||
cx.ident_of("Equal")));
|
cx.ident_of("Equal")));
|
||||||
let ordering = cx.expr_path(ordering);
|
|
||||||
let equals_expr = cx.expr_some(span, ordering);
|
|
||||||
|
|
||||||
let partial_cmp_path = vec![
|
let cmp_path = vec![
|
||||||
cx.ident_of_std("core"),
|
cx.ident_of_std("core"),
|
||||||
cx.ident_of("cmp"),
|
cx.ident_of("cmp"),
|
||||||
cx.ident_of("PartialOrd"),
|
cx.ident_of("Ord"),
|
||||||
cx.ident_of("partial_cmp"),
|
cx.ident_of("cmp"),
|
||||||
];
|
];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Builds:
|
Builds:
|
||||||
|
|
||||||
let __test = ::std::cmp::PartialOrd::partial_cmp(&self_field1, &other_field1);
|
let __test = ::std::cmp::Ord::cmp(&self_field1, &other_field1);
|
||||||
if __test == ::std::option::Option::Some(::std::cmp::Ordering::Equal) {
|
if other == ::std::cmp::Ordering::Equal {
|
||||||
let __test = ::std::cmp::PartialOrd::partial_cmp(&self_field2, &other_field2);
|
let __test = ::std::cmp::Ord::cmp(&self_field2, &other_field2);
|
||||||
if __test == ::std::option::Option::Some(::std::cmp::Ordering::Equal) {
|
if __test == ::std::cmp::Ordering::Equal {
|
||||||
...
|
...
|
||||||
} else {
|
} else {
|
||||||
__test
|
__test
|
||||||
@@ -144,7 +99,7 @@ pub fn cs_partial_cmp(cx: &mut ExtCtxt, span: Span,
|
|||||||
false,
|
false,
|
||||||
|cx, span, old, self_f, other_fs| {
|
|cx, span, old, self_f, other_fs| {
|
||||||
// let __test = new;
|
// let __test = new;
|
||||||
// if __test == Some(::std::cmp::Ordering::Equal) {
|
// if __test == ::std::cmp::Ordering::Equal {
|
||||||
// old
|
// old
|
||||||
// } else {
|
// } else {
|
||||||
// __test
|
// __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_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 assign = cx.stmt_let(span, false, test_id, new);
|
||||||
|
|
||||||
let cond = cx.expr_binary(span, ast::BiEq,
|
let cond = cx.expr_binary(span, ast::BiEq,
|
||||||
cx.expr_ident(span, test_id),
|
cx.expr_ident(span, test_id),
|
||||||
equals_expr.clone());
|
cx.expr_path(equals_path.clone()));
|
||||||
let if_ = cx.expr_if(span,
|
let if_ = cx.expr_if(span,
|
||||||
cond,
|
cond,
|
||||||
old, Some(cx.expr_ident(span, test_id)));
|
old, Some(cx.expr_ident(span, test_id)));
|
||||||
cx.expr_block(cx.block(span, vec!(assign), Some(if_)))
|
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| {
|
Box::new(|cx, span, (self_args, tag_tuple), _non_self_args| {
|
||||||
if self_args.len() != 2 {
|
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 {
|
} else {
|
||||||
some_ordering_collapsed(cx, span, PartialCmpOp, tag_tuple)
|
ordering_collapsed(cx, span, 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)
|
cx, span, substr)
|
||||||
|
|||||||
94
src/libsyntax/ext/deriving/cmp/partial_eq.rs
Normal file
94
src/libsyntax/ext/deriving/cmp/partial_eq.rs
Normal file
@@ -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)
|
||||||
|
}
|
||||||
237
src/libsyntax/ext/deriving/cmp/partial_ord.rs
Normal file
237
src/libsyntax/ext/deriving/cmp/partial_ord.rs
Normal file
@@ -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)
|
||||||
|
}
|
||||||
@@ -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)
|
|
||||||
}
|
|
||||||
@@ -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)
|
|
||||||
}
|
|
||||||
@@ -21,33 +21,30 @@ use parse::token::InternedString;
|
|||||||
use parse::token;
|
use parse::token;
|
||||||
use ptr::P;
|
use ptr::P;
|
||||||
|
|
||||||
pub fn expand_deriving_rustc_decodable<F>(cx: &mut ExtCtxt,
|
pub fn expand_deriving_rustc_decodable(cx: &mut ExtCtxt,
|
||||||
span: Span,
|
span: Span,
|
||||||
mitem: &MetaItem,
|
mitem: &MetaItem,
|
||||||
item: &Item,
|
item: &Item,
|
||||||
push: F) where
|
push: &mut FnMut(P<Item>))
|
||||||
F: FnOnce(P<Item>),
|
|
||||||
{
|
{
|
||||||
expand_deriving_decodable_imp(cx, span, mitem, item, push, "rustc_serialize")
|
expand_deriving_decodable_imp(cx, span, mitem, item, push, "rustc_serialize")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn expand_deriving_decodable<F>(cx: &mut ExtCtxt,
|
pub fn expand_deriving_decodable(cx: &mut ExtCtxt,
|
||||||
span: Span,
|
span: Span,
|
||||||
mitem: &MetaItem,
|
mitem: &MetaItem,
|
||||||
item: &Item,
|
item: &Item,
|
||||||
push: F) where
|
push: &mut FnMut(P<Item>))
|
||||||
F: FnOnce(P<Item>),
|
|
||||||
{
|
{
|
||||||
expand_deriving_decodable_imp(cx, span, mitem, item, push, "serialize")
|
expand_deriving_decodable_imp(cx, span, mitem, item, push, "serialize")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expand_deriving_decodable_imp<F>(cx: &mut ExtCtxt,
|
fn expand_deriving_decodable_imp(cx: &mut ExtCtxt,
|
||||||
span: Span,
|
span: Span,
|
||||||
mitem: &MetaItem,
|
mitem: &MetaItem,
|
||||||
item: &Item,
|
item: &Item,
|
||||||
push: F,
|
push: &mut FnMut(P<Item>),
|
||||||
krate: &'static str) where
|
krate: &'static str)
|
||||||
F: FnOnce(P<Item>),
|
|
||||||
{
|
{
|
||||||
if !cx.use_std {
|
if !cx.use_std {
|
||||||
// FIXME(#21880): lift this requirement.
|
// FIXME(#21880): lift this requirement.
|
||||||
|
|||||||
@@ -17,12 +17,11 @@ use ext::deriving::generic::ty::*;
|
|||||||
use parse::token::InternedString;
|
use parse::token::InternedString;
|
||||||
use ptr::P;
|
use ptr::P;
|
||||||
|
|
||||||
pub fn expand_deriving_default<F>(cx: &mut ExtCtxt,
|
pub fn expand_deriving_default(cx: &mut ExtCtxt,
|
||||||
span: Span,
|
span: Span,
|
||||||
mitem: &MetaItem,
|
mitem: &MetaItem,
|
||||||
item: &Item,
|
item: &Item,
|
||||||
push: F) where
|
push: &mut FnMut(P<Item>))
|
||||||
F: FnOnce(P<Item>),
|
|
||||||
{
|
{
|
||||||
let inline = cx.meta_word(span, InternedString::new("inline"));
|
let inline = cx.meta_word(span, InternedString::new("inline"));
|
||||||
let attrs = vec!(cx.attribute(span, inline));
|
let attrs = vec!(cx.attribute(span, inline));
|
||||||
|
|||||||
@@ -97,33 +97,30 @@ use ext::deriving::generic::ty::*;
|
|||||||
use parse::token;
|
use parse::token;
|
||||||
use ptr::P;
|
use ptr::P;
|
||||||
|
|
||||||
pub fn expand_deriving_rustc_encodable<F>(cx: &mut ExtCtxt,
|
pub fn expand_deriving_rustc_encodable(cx: &mut ExtCtxt,
|
||||||
span: Span,
|
span: Span,
|
||||||
mitem: &MetaItem,
|
mitem: &MetaItem,
|
||||||
item: &Item,
|
item: &Item,
|
||||||
push: F) where
|
push: &mut FnMut(P<Item>))
|
||||||
F: FnOnce(P<Item>),
|
|
||||||
{
|
{
|
||||||
expand_deriving_encodable_imp(cx, span, mitem, item, push, "rustc_serialize")
|
expand_deriving_encodable_imp(cx, span, mitem, item, push, "rustc_serialize")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn expand_deriving_encodable<F>(cx: &mut ExtCtxt,
|
pub fn expand_deriving_encodable(cx: &mut ExtCtxt,
|
||||||
span: Span,
|
span: Span,
|
||||||
mitem: &MetaItem,
|
mitem: &MetaItem,
|
||||||
item: &Item,
|
item: &Item,
|
||||||
push: F) where
|
push: &mut FnMut(P<Item>))
|
||||||
F: FnOnce(P<Item>),
|
|
||||||
{
|
{
|
||||||
expand_deriving_encodable_imp(cx, span, mitem, item, push, "serialize")
|
expand_deriving_encodable_imp(cx, span, mitem, item, push, "serialize")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expand_deriving_encodable_imp<F>(cx: &mut ExtCtxt,
|
fn expand_deriving_encodable_imp(cx: &mut ExtCtxt,
|
||||||
span: Span,
|
span: Span,
|
||||||
mitem: &MetaItem,
|
mitem: &MetaItem,
|
||||||
item: &Item,
|
item: &Item,
|
||||||
push: F,
|
push: &mut FnMut(P<Item>),
|
||||||
krate: &'static str) where
|
krate: &'static str)
|
||||||
F: FnOnce(P<Item>),
|
|
||||||
{
|
{
|
||||||
if !cx.use_std {
|
if !cx.use_std {
|
||||||
// FIXME(#21880): lift this requirement.
|
// FIXME(#21880): lift this requirement.
|
||||||
|
|||||||
@@ -375,12 +375,11 @@ fn find_type_parameters(ty: &ast::Ty, ty_param_names: &[ast::Name]) -> Vec<P<ast
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> TraitDef<'a> {
|
impl<'a> TraitDef<'a> {
|
||||||
pub fn expand<F>(&self,
|
pub fn expand(&self,
|
||||||
cx: &mut ExtCtxt,
|
cx: &mut ExtCtxt,
|
||||||
mitem: &ast::MetaItem,
|
mitem: &ast::MetaItem,
|
||||||
item: &ast::Item,
|
item: &ast::Item,
|
||||||
push: F) where
|
push: &mut FnMut(P<ast::Item>))
|
||||||
F: FnOnce(P<ast::Item>),
|
|
||||||
{
|
{
|
||||||
let newitem = match item.node {
|
let newitem = match item.node {
|
||||||
ast::ItemStruct(ref struct_def, ref generics) => {
|
ast::ItemStruct(ref struct_def, ref generics) => {
|
||||||
|
|||||||
@@ -16,12 +16,11 @@ use ext::deriving::generic::*;
|
|||||||
use ext::deriving::generic::ty::*;
|
use ext::deriving::generic::ty::*;
|
||||||
use ptr::P;
|
use ptr::P;
|
||||||
|
|
||||||
pub fn expand_deriving_hash<F>(cx: &mut ExtCtxt,
|
pub fn expand_deriving_hash(cx: &mut ExtCtxt,
|
||||||
span: Span,
|
span: Span,
|
||||||
mitem: &MetaItem,
|
mitem: &MetaItem,
|
||||||
item: &Item,
|
item: &Item,
|
||||||
push: F) where
|
push: &mut FnMut(P<Item>))
|
||||||
F: FnOnce(P<Item>),
|
|
||||||
{
|
{
|
||||||
|
|
||||||
let path = Path::new_(pathvec_std!(cx, core::hash::Hash), None,
|
let path = Path::new_(pathvec_std!(cx, core::hash::Hash), None,
|
||||||
|
|||||||
@@ -65,14 +65,14 @@ pub mod show;
|
|||||||
pub mod default;
|
pub mod default;
|
||||||
pub mod primitive;
|
pub mod primitive;
|
||||||
|
|
||||||
|
#[path="cmp/partial_eq.rs"]
|
||||||
|
pub mod partial_eq;
|
||||||
#[path="cmp/eq.rs"]
|
#[path="cmp/eq.rs"]
|
||||||
pub mod eq;
|
pub mod eq;
|
||||||
#[path="cmp/totaleq.rs"]
|
#[path="cmp/partial_ord.rs"]
|
||||||
pub mod totaleq;
|
pub mod partial_ord;
|
||||||
#[path="cmp/ord.rs"]
|
#[path="cmp/ord.rs"]
|
||||||
pub mod ord;
|
pub mod ord;
|
||||||
#[path="cmp/totalord.rs"]
|
|
||||||
pub mod totalord;
|
|
||||||
|
|
||||||
|
|
||||||
pub mod generic;
|
pub mod generic;
|
||||||
@@ -118,7 +118,7 @@ fn expand_derive(cx: &mut ExtCtxt,
|
|||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! derive_traits {
|
macro_rules! derive_traits {
|
||||||
($( $name:expr => $func:path, )*) => {
|
($( $name:expr => $func:path, )+) => {
|
||||||
pub fn register_all(env: &mut SyntaxEnv) {
|
pub fn register_all(env: &mut SyntaxEnv) {
|
||||||
// Define the #[derive_*] extensions.
|
// Define the #[derive_*] extensions.
|
||||||
$({
|
$({
|
||||||
@@ -132,13 +132,13 @@ macro_rules! derive_traits {
|
|||||||
item: &Item,
|
item: &Item,
|
||||||
push: &mut FnMut(P<Item>)) {
|
push: &mut FnMut(P<Item>)) {
|
||||||
warn_if_deprecated(ecx, sp, $name);
|
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)),
|
env.insert(intern(concat!("derive_", $name)),
|
||||||
Decorator(Box::new(DeriveExtension)));
|
Decorator(Box::new(DeriveExtension)));
|
||||||
})*
|
})+
|
||||||
|
|
||||||
env.insert(intern("derive"),
|
env.insert(intern("derive"),
|
||||||
Modifier(Box::new(expand_derive)));
|
Modifier(Box::new(expand_derive)));
|
||||||
@@ -146,7 +146,7 @@ macro_rules! derive_traits {
|
|||||||
|
|
||||||
fn is_builtin_trait(name: &str) -> bool {
|
fn is_builtin_trait(name: &str) -> bool {
|
||||||
match name {
|
match name {
|
||||||
$( $name )|* => true,
|
$( $name )|+ => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -162,10 +162,10 @@ derive_traits! {
|
|||||||
|
|
||||||
"RustcDecodable" => decodable::expand_deriving_rustc_decodable,
|
"RustcDecodable" => decodable::expand_deriving_rustc_decodable,
|
||||||
|
|
||||||
"PartialEq" => eq::expand_deriving_eq,
|
"PartialEq" => partial_eq::expand_deriving_partial_eq,
|
||||||
"Eq" => totaleq::expand_deriving_totaleq,
|
"Eq" => eq::expand_deriving_eq,
|
||||||
"PartialOrd" => ord::expand_deriving_ord,
|
"PartialOrd" => partial_ord::expand_deriving_partial_ord,
|
||||||
"Ord" => totalord::expand_deriving_totalord,
|
"Ord" => ord::expand_deriving_ord,
|
||||||
|
|
||||||
"Debug" => show::expand_deriving_show,
|
"Debug" => show::expand_deriving_show,
|
||||||
|
|
||||||
|
|||||||
@@ -18,12 +18,11 @@ use ext::deriving::generic::ty::*;
|
|||||||
use parse::token::InternedString;
|
use parse::token::InternedString;
|
||||||
use ptr::P;
|
use ptr::P;
|
||||||
|
|
||||||
pub fn expand_deriving_from_primitive<F>(cx: &mut ExtCtxt,
|
pub fn expand_deriving_from_primitive(cx: &mut ExtCtxt,
|
||||||
span: Span,
|
span: Span,
|
||||||
mitem: &MetaItem,
|
mitem: &MetaItem,
|
||||||
item: &Item,
|
item: &Item,
|
||||||
push: F) where
|
push: &mut FnMut(P<Item>))
|
||||||
F: FnOnce(P<Item>),
|
|
||||||
{
|
{
|
||||||
let inline = cx.meta_word(span, InternedString::new("inline"));
|
let inline = cx.meta_word(span, InternedString::new("inline"));
|
||||||
let attrs = vec!(cx.attribute(span, inline));
|
let attrs = vec!(cx.attribute(span, inline));
|
||||||
|
|||||||
@@ -18,12 +18,11 @@ use ext::deriving::generic::ty::*;
|
|||||||
use parse::token;
|
use parse::token;
|
||||||
use ptr::P;
|
use ptr::P;
|
||||||
|
|
||||||
pub fn expand_deriving_show<F>(cx: &mut ExtCtxt,
|
pub fn expand_deriving_show(cx: &mut ExtCtxt,
|
||||||
span: Span,
|
span: Span,
|
||||||
mitem: &MetaItem,
|
mitem: &MetaItem,
|
||||||
item: &Item,
|
item: &Item,
|
||||||
push: F) where
|
push: &mut FnMut(P<Item>))
|
||||||
F: FnOnce(P<Item>),
|
|
||||||
{
|
{
|
||||||
// &mut ::std::fmt::Formatter
|
// &mut ::std::fmt::Formatter
|
||||||
let fmtr = Ptr(box Literal(path_std!(cx, core::fmt::Formatter)),
|
let fmtr = Ptr(box Literal(path_std!(cx, core::fmt::Formatter)),
|
||||||
|
|||||||
@@ -122,7 +122,6 @@ impl fmt::Display for TestName {
|
|||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
enum NamePadding {
|
enum NamePadding {
|
||||||
PadNone,
|
PadNone,
|
||||||
PadOnLeft,
|
|
||||||
PadOnRight,
|
PadOnRight,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,13 +129,9 @@ impl TestDesc {
|
|||||||
fn padded_name(&self, column_count: usize, align: NamePadding) -> String {
|
fn padded_name(&self, column_count: usize, align: NamePadding) -> String {
|
||||||
let mut name = String::from_str(self.name.as_slice());
|
let mut name = String::from_str(self.name.as_slice());
|
||||||
let fill = column_count.saturating_sub(name.len());
|
let fill = column_count.saturating_sub(name.len());
|
||||||
let mut pad = repeat(" ").take(fill).collect::<String>();
|
let pad = repeat(" ").take(fill).collect::<String>();
|
||||||
match align {
|
match align {
|
||||||
PadNone => name,
|
PadNone => name,
|
||||||
PadOnLeft => {
|
|
||||||
pad.push_str(&name);
|
|
||||||
pad
|
|
||||||
}
|
|
||||||
PadOnRight => {
|
PadOnRight => {
|
||||||
name.push_str(&pad);
|
name.push_str(&pad);
|
||||||
name
|
name
|
||||||
@@ -690,7 +685,7 @@ pub fn run_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn> ) -> io::Res
|
|||||||
fn len_if_padded(t: &TestDescAndFn) -> usize {
|
fn len_if_padded(t: &TestDescAndFn) -> usize {
|
||||||
match t.testfn.padding() {
|
match t.testfn.padding() {
|
||||||
PadNone => 0,
|
PadNone => 0,
|
||||||
PadOnLeft | PadOnRight => t.desc.name.as_slice().len(),
|
PadOnRight => t.desc.name.as_slice().len(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
match tests.iter().max_by(|t|len_if_padded(*t)) {
|
match tests.iter().max_by(|t|len_if_padded(*t)) {
|
||||||
|
|||||||
@@ -70,5 +70,5 @@ fn expand(cx: &mut ExtCtxt,
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
trait_def.expand(cx, mitem, item, |i| push(i))
|
trait_def.expand(cx, mitem, item, push)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user