Implement RFC#28: Add PartialOrd::partial_cmp
I ended up altering the semantics of Json's PartialOrd implementation. It used to be the case that Null < Null, but I can't think of any reason for an ordering other than the default one so I just switched it over to using the derived implementation. This also fixes broken `PartialOrd` implementations for `Vec` and `TreeMap`. RFC: 0028-partial-cmp
This commit is contained in:
parent
bb5695b95c
commit
55cae0a094
28 changed files with 343 additions and 161 deletions
|
|
@ -43,22 +43,116 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt,
|
|||
} }
|
||||
);
|
||||
|
||||
let ordering_ty = Literal(Path::new(vec!["std", "cmp", "Ordering"]));
|
||||
let ret_ty = Literal(Path::new_(vec!["std", "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,
|
||||
const_nonmatching: false,
|
||||
combine_substructure: combine_substructure(|cx, span, substr| {
|
||||
cs_partial_cmp(cx, span, substr)
|
||||
})
|
||||
};
|
||||
|
||||
let trait_def = TraitDef {
|
||||
span: span,
|
||||
attributes: Vec::new(),
|
||||
path: Path::new(vec!("std", "cmp", "PartialOrd")),
|
||||
additional_bounds: Vec::new(),
|
||||
attributes: vec![],
|
||||
path: Path::new(vec!["std", "cmp", "PartialOrd"]),
|
||||
additional_bounds: vec![],
|
||||
generics: LifetimeBounds::empty(),
|
||||
methods: vec!(
|
||||
methods: vec![
|
||||
partial_cmp_def,
|
||||
md!("lt", true, false),
|
||||
md!("le", true, true),
|
||||
md!("gt", false, false),
|
||||
md!("ge", false, true)
|
||||
)
|
||||
]
|
||||
};
|
||||
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"
|
||||
};
|
||||
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)
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
/*
|
||||
Builds:
|
||||
|
||||
let __test = self_field1.partial_cmp(&other_field2);
|
||||
if __test == ::std::option::Some(::std::cmp::Equal) {
|
||||
let __test = self_field2.partial_cmp(&other_field2);
|
||||
if __test == ::std::option::Some(::std::cmp::Equal) {
|
||||
...
|
||||
} else {
|
||||
__test
|
||||
}
|
||||
} else {
|
||||
__test
|
||||
}
|
||||
|
||||
FIXME #6449: These `if`s could/should be `match`es.
|
||||
*/
|
||||
cs_same_method_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, new| {
|
||||
// let __test = new;
|
||||
// if __test == Some(::std::cmp::Equal) {
|
||||
// old
|
||||
// } else {
|
||||
// __test
|
||||
// }
|
||||
|
||||
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(),
|
||||
|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, substr)
|
||||
}
|
||||
|
||||
/// Strict inequality.
|
||||
fn cs_op(less: bool, equal: bool, cx: &mut ExtCtxt, span: Span,
|
||||
substr: &Substructure) -> Gc<Expr> {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue