Skip to content

New deriving that generates O(n) code for PartialOrd, Ord, etc. #15503

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jul 11, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions src/libsyntax/ext/deriving/clone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ pub fn expand_deriving_clone(cx: &mut ExtCtxt,
args: Vec::new(),
ret_ty: Self,
attributes: attrs,
const_nonmatching: false,
combine_substructure: combine_substructure(|c, s, sub| {
cs_clone("Clone", c, s, sub)
}),
Expand Down Expand Up @@ -69,7 +68,7 @@ fn cs_clone(
ctor_ident = variant.node.name;
all_fields = af;
},
EnumNonMatching(..) => {
EnumNonMatchingCollapsed (..) => {
cx.span_bug(trait_span,
format!("non-matching enum variants in \
`deriving({})`",
Expand Down
1 change: 0 additions & 1 deletion src/libsyntax/ext/deriving/cmp/eq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ pub fn expand_deriving_eq(cx: &mut ExtCtxt,
args: vec!(borrowed_self()),
ret_ty: Literal(Path::new(vec!("bool"))),
attributes: attrs,
const_nonmatching: true,
combine_substructure: combine_substructure(|a, b, c| {
$f(a, b, c)
})
Expand Down
69 changes: 35 additions & 34 deletions src/libsyntax/ext/deriving/cmp/ord.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt,
args: vec!(borrowed_self()),
ret_ty: Literal(Path::new(vec!("bool"))),
attributes: attrs,
const_nonmatching: false,
combine_substructure: combine_substructure(|cx, span, substr| {
cs_op($op, $equal, cx, span, substr)
})
Expand All @@ -59,7 +58,6 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt,
args: vec![borrowed_self()],
ret_ty: ret_ty,
attributes: attrs,
const_nonmatching: false,
combine_substructure: combine_substructure(|cx, span, substr| {
cs_partial_cmp(cx, span, substr)
})
Expand All @@ -82,24 +80,33 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt,
trait_def.expand(cx, mitem, item, push)
}

pub fn some_ordering_const(cx: &mut ExtCtxt, span: Span, cnst: Ordering) -> Gc<ast::Expr> {
let cnst = match cnst {
Less => "Less",
Equal => "Equal",
Greater => "Greater"
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]) -> Gc<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",
};
let ordering = cx.path_global(span,
vec!(cx.ident_of("std"),
cx.ident_of("cmp"),
cx.ident_of(cnst)));
let ordering = cx.expr_path(ordering);
cx.expr_some(span, ordering)
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) -> Gc<Expr> {
let test_id = cx.ident_of("__test");
let equals_expr = some_ordering_const(cx, span, Equal);
let ordering = cx.path_global(span,
vec!(cx.ident_of("std"),
cx.ident_of("cmp"),
cx.ident_of("Equal")));
let ordering = cx.expr_path(ordering);
let equals_expr = cx.expr_some(span, ordering);

/*
Builds:
Expand Down Expand Up @@ -141,13 +148,11 @@ pub fn cs_partial_cmp(cx: &mut ExtCtxt, span: Span,
cx.expr_block(cx.block(span, vec!(assign), Some(if_)))
},
equals_expr.clone(),
|cx, span, list, _| {
match list {
// an earlier nonmatching variant is Less than a
// later one.
[(self_var, _, _), (other_var, _, _)] =>
some_ordering_const(cx, span, self_var.cmp(&other_var)),
_ => cx.span_bug(span, "not exactly 2 arguments in `deriving(Ord)`")
|cx, span, (self_args, tag_tuple), _non_self_args| {
if self_args.len() != 2 {
cx.span_bug(span, "not exactly 2 arguments in `deriving(Ord)`")
} else {
some_ordering_collapsed(cx, span, PartialCmpOp, tag_tuple)
}
},
cx, span, substr)
Expand Down Expand Up @@ -191,19 +196,15 @@ fn cs_op(less: bool, equal: bool, cx: &mut ExtCtxt, span: Span,
cx.expr_binary(span, ast::BiOr, cmp, and)
},
cx.expr_bool(span, equal),
|cx, span, args, _| {
// nonmatching enums, order by the order the variants are
// written
match args {
[(self_var, _, _),
(other_var, _, _)] =>
cx.expr_bool(span,
if less {
self_var < other_var
} else {
self_var > other_var
}),
_ => cx.span_bug(span, "not exactly 2 arguments in `deriving(Ord)`")
|cx, span, (self_args, tag_tuple), _non_self_args| {
if self_args.len() != 2 {
cx.span_bug(span, "not exactly 2 arguments in `deriving(Ord)`")
} 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)
Expand Down
1 change: 0 additions & 1 deletion src/libsyntax/ext/deriving/cmp/totaleq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ pub fn expand_deriving_totaleq(cx: &mut ExtCtxt,
args: vec!(),
ret_ty: nil_ty(),
attributes: attrs,
const_nonmatching: true,
combine_substructure: combine_substructure(|a, b, c| {
cs_total_eq_assert(a, b, c)
})
Expand Down
38 changes: 15 additions & 23 deletions src/libsyntax/ext/deriving/cmp/totalord.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ use ext::deriving::generic::*;
use ext::deriving::generic::ty::*;
use parse::token::InternedString;

use std::cmp::{Ordering, Equal, Less, Greater};
use std::gc::Gc;

pub fn expand_deriving_totalord(cx: &mut ExtCtxt,
Expand All @@ -41,7 +40,6 @@ pub fn expand_deriving_totalord(cx: &mut ExtCtxt,
args: vec!(borrowed_self()),
ret_ty: Literal(Path::new(vec!("std", "cmp", "Ordering"))),
attributes: attrs,
const_nonmatching: false,
combine_substructure: combine_substructure(|a, b, c| {
cs_cmp(a, b, c)
}),
Expand All @@ -53,22 +51,21 @@ pub fn expand_deriving_totalord(cx: &mut ExtCtxt,
}


pub fn ordering_const(cx: &mut ExtCtxt, span: Span, cnst: Ordering) -> ast::Path {
let cnst = match cnst {
Less => "Less",
Equal => "Equal",
Greater => "Greater"
};
cx.path_global(span,
vec!(cx.ident_of("std"),
cx.ident_of("cmp"),
cx.ident_of(cnst)))
pub fn ordering_collapsed(cx: &mut ExtCtxt,
span: Span,
self_arg_tags: &[ast::Ident]) -> Gc<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) -> Gc<Expr> {
let test_id = cx.ident_of("__test");
let equals_path = ordering_const(cx, span, Equal);
let equals_path = cx.path_global(span,
vec!(cx.ident_of("std"),
cx.ident_of("cmp"),
cx.ident_of("Equal")));

/*
Builds:
Expand Down Expand Up @@ -110,16 +107,11 @@ pub fn cs_cmp(cx: &mut ExtCtxt, span: Span,
cx.expr_block(cx.block(span, vec!(assign), Some(if_)))
},
cx.expr_path(equals_path.clone()),
|cx, span, list, _| {
match list {
// an earlier nonmatching variant is Less than a
// later one.
[(self_var, _, _),
(other_var, _, _)] => {
let order = ordering_const(cx, span, self_var.cmp(&other_var));
cx.expr_path(order)
}
_ => cx.span_bug(span, "not exactly 2 arguments in `deriving(Ord)`")
|cx, span, (self_args, tag_tuple), _non_self_args| {
if self_args.len() != 2 {
cx.span_bug(span, "not exactly 2 arguments in `deriving(TotalOrd)`")
} else {
ordering_collapsed(cx, span, tag_tuple)
}
},
cx, span, substr)
Expand Down
1 change: 0 additions & 1 deletion src/libsyntax/ext/deriving/decodable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ pub fn expand_deriving_decodable(cx: &mut ExtCtxt,
vec!(box Self,
box Literal(Path::new_local("__E"))), true)),
attributes: Vec::new(),
const_nonmatching: true,
combine_substructure: combine_substructure(|a, b, c| {
decodable_substructure(a, b, c)
}),
Expand Down
1 change: 0 additions & 1 deletion src/libsyntax/ext/deriving/default.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ pub fn expand_deriving_default(cx: &mut ExtCtxt,
args: Vec::new(),
ret_ty: Self,
attributes: attrs,
const_nonmatching: false,
combine_substructure: combine_substructure(|a, b, c| {
default_substructure(a, b, c)
})
Expand Down
1 change: 0 additions & 1 deletion src/libsyntax/ext/deriving/encodable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,6 @@ pub fn expand_deriving_encodable(cx: &mut ExtCtxt,
box Literal(Path::new_local("__E"))),
true)),
attributes: Vec::new(),
const_nonmatching: true,
combine_substructure: combine_substructure(|a, b, c| {
encodable_substructure(a, b, c)
}),
Expand Down
Loading