diff options
| author | bors <bors@rust-lang.org> | 2014-06-30 05:36:25 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2014-06-30 05:36:25 +0000 |
| commit | e1683f50c00297e9908ae028fa1d41b9a52a6f6f (patch) | |
| tree | e1f34ea8fa1e5c887ed724e41a029cab323ad455 /src/libsyntax | |
| parent | e25eb6b223d86047dc807a167f3dd4bf492bbf41 (diff) | |
| parent | 55cae0a094bbdcd0e9d5e697ce4f38cbd783bbc7 (diff) | |
| download | rust-e1683f50c00297e9908ae028fa1d41b9a52a6f6f.tar.gz rust-e1683f50c00297e9908ae028fa1d41b9a52a6f6f.zip | |
auto merge of #15030 : sfackler/rust/partial-cmp, r=huonw
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`. # Note This isn't ready to merge yet since libcore tests are broken as you end up with 2 versions of `Option`. The rest should be reviewable though. RFC: 0028-partial-cmp
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ext/deriving/cmp/ord.rs | 104 |
1 files changed, 99 insertions, 5 deletions
diff --git a/src/libsyntax/ext/deriving/cmp/ord.rs b/src/libsyntax/ext/deriving/cmp/ord.rs index 88ebe8a60fa..59cdec1ea88 100644 --- a/src/libsyntax/ext/deriving/cmp/ord.rs +++ b/src/libsyntax/ext/deriving/cmp/ord.rs @@ -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> { |
