diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index e9d6784136f..1e05965925c 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -179,7 +179,7 @@ pure fn min>(self: IA) -> A { } } -pure fn max>(self: IA) -> A { +pure fn max>(self: IA) -> A { match do foldl::,IA>(self, None) |a, b| { match a { Some(a_) if a_ > b => { diff --git a/src/libcore/str.rs b/src/libcore/str.rs index ca96090ebd4..66ef6e001b7 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -769,28 +769,17 @@ pure fn lt(a: &str, b: &str) -> bool { /// Bytewise less than or equal pure fn le(a: &str, b: &str) -> bool { - let (a_len, b_len) = (a.len(), b.len()); - let mut end = uint::min(a_len, b_len); - - let mut i = 0; - while i < end { - let (c_a, c_b) = (a[i], b[i]); - if c_a < c_b { return true; } - if c_a > c_b { return false; } - i += 1; - } - - return a_len <= b_len; + !lt(b, a) } /// Bytewise greater than or equal pure fn ge(a: &str, b: &str) -> bool { - !lt(b, a) + !lt(a, b) } /// Bytewise greater than pure fn gt(a: &str, b: &str) -> bool { - !le(b, a) + !le(a, b) } impl &str: Eq { diff --git a/src/libcore/task.rs b/src/libcore/task.rs index bee810fceba..ced39ef067b 100644 --- a/src/libcore/task.rs +++ b/src/libcore/task.rs @@ -158,6 +158,46 @@ enum SchedMode { PlatformThread } +impl SchedMode : cmp::Eq { + pure fn eq(&&other: SchedMode) -> bool { + match self { + SingleThreaded => { + match other { + SingleThreaded => true, + _ => false + } + } + ThreadPerCore => { + match other { + ThreadPerCore => true, + _ => false + } + } + ThreadPerTask => { + match other { + ThreadPerTask => true, + _ => false + } + } + ManualThreads(e0a) => { + match other { + ManualThreads(e0b) => e0a == e0b, + _ => false + } + } + PlatformThread => { + match other { + PlatformThread => true, + _ => false + } + } + } + } + pure fn ne(&&other: SchedMode) -> bool { + !self.eq(other) + } +} + /** * Scheduler configuration options * diff --git a/src/libstd/json.rs b/src/libstd/json.rs index 1adb41e8d10..de6f2ea3e90 100644 --- a/src/libstd/json.rs +++ b/src/libstd/json.rs @@ -3,11 +3,12 @@ //! json serialization -use core::cmp::Eq; +use core::cmp::{Eq, Ord}; use result::{Result, Ok, Err}; use io::WriterUtil; use map::hashmap; use map::map; +use sort::Sort; export Json; export Error; @@ -603,6 +604,75 @@ pure fn eq(value0: Json, value1: Json) -> bool { } } +/// Test if two json values are less than one another +pure fn lt(value0: Json, value1: Json) -> bool { + match value0 { + Num(f0) => { + match value1 { + Num(f1) => f0 < f1, + String(_) | Boolean(_) | List(_) | Dict(_) | Null => true + } + } + + String(s0) => { + match value1 { + Num(_) => false, + String(s1) => s0 < s1, + Boolean(_) | List(_) | Dict(_) | Null => true + } + } + + Boolean(b0) => { + match value1 { + Num(_) | String(_) => false, + Boolean(b1) => b0 < b1, + List(_) | Dict(_) | Null => true + } + } + + List(l0) => { + match value1 { + Num(_) | String(_) | Boolean(_) => false, + List(l1) => l0 < l1, + Dict(_) | Null => true + } + } + + Dict(d0) => { + match value1 { + Num(_) | String(_) | Boolean(_) | List(_) => false, + Dict(d1) => { + unchecked { + let (d0_flat, d1_flat) = { + let d0_flat = dvec::DVec(); + for d0.each |k, v| { d0_flat.push((k, v)); } + let d0_flat = dvec::unwrap(d0_flat); + d0_flat.qsort(); + + let mut d1_flat = dvec::DVec(); + for d1.each |k, v| { d1_flat.push((k, v)); } + let d1_flat = dvec::unwrap(d1_flat); + d1_flat.qsort(); + + (d0_flat, d1_flat) + }; + + d0_flat < d1_flat + } + } + Null => true + } + } + + Null => { + match value1 { + Num(_) | String(_) | Boolean(_) | List(_) | Dict(_) => false, + Null => true + } + } + } +} + impl Error : Eq { pure fn eq(&&other: Error) -> bool { self.line == other.line && @@ -617,6 +687,13 @@ impl Json : Eq { pure fn ne(&&other: Json) -> bool { !self.eq(other) } } +impl Json : Ord { + pure fn lt(&&other: Json) -> bool { lt(self, other) } + pure fn le(&&other: Json) -> bool { !other.lt(self) } + pure fn ge(&&other: Json) -> bool { !self.lt(other) } + pure fn gt(&&other: Json) -> bool { other.lt(self) } +} + trait ToJson { fn to_json() -> Json; } impl Json: ToJson { diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index e2cfdd119b6..364576aae33 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -405,6 +405,13 @@ enum proto { proto_block, // fn& } +impl proto : cmp::Eq { + pure fn eq(&&other: proto) -> bool { + (self as uint) == (other as uint) + } + pure fn ne(&&other: proto) -> bool { !self.eq(other) } +} + #[auto_serialize] enum vstore { // FIXME (#2112): Change uint to @expr (actually only constant exprs) @@ -454,7 +461,49 @@ impl binop : cmp::Eq { enum unop { box(mutability), uniq(mutability), - deref, not, neg + deref, + not, + neg +} + +impl unop : cmp::Eq { + pure fn eq(&&other: unop) -> bool { + match self { + box(e0a) => { + match other { + box(e0b) => e0a == e0b, + _ => false + } + } + uniq(e0a) => { + match other { + uniq(e0b) => e0a == e0b, + _ => false + } + } + deref => { + match other { + deref => true, + _ => false + } + } + not => { + match other { + not => true, + _ => false + } + } + neg => { + match other { + neg => true, + _ => false + } + } + } + } + pure fn ne(&&other: unop) -> bool { + !self.eq(other) + } } // Generally, after typeck you can get the inferred value diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index 9dc610e2fb6..a12233765ca 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -337,6 +337,13 @@ enum inline_attr { ia_never, } +impl inline_attr : cmp::Eq { + pure fn eq(&&other: inline_attr) -> bool { + (self as uint) == (other as uint) + } + pure fn ne(&&other: inline_attr) -> bool { !self.eq(other) } +} + /// True if something like #[inline] is found in the list of attrs. fn find_inline_attr(attrs: ~[ast::attribute]) -> inline_attr { // FIXME (#2809)---validate the usage of #[inline] and #[inline(always)] diff --git a/src/libsyntax/ext/pipes/proto.rs b/src/libsyntax/ext/pipes/proto.rs index 4065c8cf2ba..cb470aee7f3 100644 --- a/src/libsyntax/ext/pipes/proto.rs +++ b/src/libsyntax/ext/pipes/proto.rs @@ -143,7 +143,7 @@ struct protocol_ { fn get_state_by_id(id: uint) -> state { self.states[id] } fn has_state(name: ~str) -> bool { - self.states.find(|i| i.name == name) != None + self.states.find(|i| i.name == name).is_some() } fn filename() -> ~str { diff --git a/src/libsyntax/ext/simplext.rs b/src/libsyntax/ext/simplext.rs index bb5af8402df..c6ddc449b20 100644 --- a/src/libsyntax/ext/simplext.rs +++ b/src/libsyntax/ext/simplext.rs @@ -68,7 +68,7 @@ fn elts_to_ell(cx: ext_ctxt, elts: ~[@expr]) -> match elt.node { expr_mac(m) => match m.node { ast::mac_ellipsis => { - if res != None { + if res.is_some() { cx.span_fatal(m.span, ~"only one ellipsis allowed"); } res = @@ -449,7 +449,7 @@ fn p_t_s_rec(cx: ext_ctxt, m: matchable, s: selector, b: binders) { } } {pre: pre, rep: None, post: post} => { - if post != ~[] { + if post.len() > 0 { cx.bug(~"elts_to_ell provided an invalid result"); } p_t_s_r_length(cx, vec::len(pre), false, s, b); diff --git a/src/libsyntax/parse/comments.rs b/src/libsyntax/parse/comments.rs index b85262cb79d..7fcf7a032dc 100644 --- a/src/libsyntax/parse/comments.rs +++ b/src/libsyntax/parse/comments.rs @@ -17,6 +17,15 @@ enum cmnt_style { blank_line, // Just a manual blank line "\n\n", for layout } +impl cmnt_style : cmp::Eq { + pure fn eq(&&other: cmnt_style) -> bool { + (self as uint) == (other as uint) + } + pure fn ne(&&other: cmnt_style) -> bool { + (self as uint) != (other as uint) + } +} + type cmnt = {style: cmnt_style, lines: ~[~str], pos: uint}; fn is_doc_comment(s: ~str) -> bool { diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 942963797cb..46faa67114e 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1616,10 +1616,13 @@ fn print_fn_args_and_ret(s: ps, decl: ast::fn_decl, pclose(s); maybe_print_comment(s, decl.output.span.lo); - if decl.output.node != ast::ty_nil { - space_if_not_bol(s); - word_space(s, ~"->"); - print_type(s, decl.output); + match decl.output.node { + ast::ty_nil => {} + _ => { + space_if_not_bol(s); + word_space(s, ~"->"); + print_type(s, decl.output); + } } } @@ -1628,11 +1631,16 @@ fn print_fn_block_args(s: ps, decl: ast::fn_decl, word(s.s, ~"|"); print_fn_args(s, decl, cap_items, None); word(s.s, ~"|"); - if decl.output.node != ast::ty_infer { - space_if_not_bol(s); - word_space(s, ~"->"); - print_type(s, decl.output); + + match decl.output.node { + ast::ty_infer => {} + _ => { + space_if_not_bol(s); + word_space(s, ~"->"); + print_type(s, decl.output); + } } + maybe_print_comment(s, decl.output.span.lo); } @@ -1829,14 +1837,19 @@ fn print_ty_fn(s: ps, opt_proto: Option, purity: ast::purity, pclose(s); maybe_print_comment(s, decl.output.span.lo); - if decl.output.node != ast::ty_nil { - space_if_not_bol(s); - ibox(s, indent_unit); - word_space(s, ~"->"); - if decl.cf == ast::noreturn { word_nbsp(s, ~"!"); } - else { print_type(s, decl.output); } - end(s); + + match decl.output.node { + ast::ty_nil => {} + _ => { + space_if_not_bol(s); + ibox(s, indent_unit); + word_space(s, ~"->"); + if decl.cf == ast::noreturn { word_nbsp(s, ~"!"); } + else { print_type(s, decl.output); } + end(s); + } } + end(s); } diff --git a/src/rustc/middle/borrowck/check_loans.rs b/src/rustc/middle/borrowck/check_loans.rs index c45e6d03546..2d4f988c007 100644 --- a/src/rustc/middle/borrowck/check_loans.rs +++ b/src/rustc/middle/borrowck/check_loans.rs @@ -79,6 +79,13 @@ enum assignment_type { at_mutbl_ref, } +impl assignment_type : cmp::Eq { + pure fn eq(&&other: assignment_type) -> bool { + (self as uint) == (other as uint) + } + pure fn ne(&&other: assignment_type) -> bool { !self.eq(other) } +} + impl assignment_type { fn checked_by_liveness() -> bool { // the liveness pass guarantees that immutable local variables diff --git a/src/rustc/middle/resolve.rs b/src/rustc/middle/resolve.rs index 94786aa8a89..b85b10e50e8 100644 --- a/src/rustc/middle/resolve.rs +++ b/src/rustc/middle/resolve.rs @@ -210,6 +210,15 @@ enum ResolveResult { Success(T) // Successfully resolved the import. } +impl ResolveResult { + fn failed() -> bool { + match self { Failed => true, _ => false } + } + fn indeterminate() -> bool { + match self { Indeterminate => true, _ => false } + } +} + enum TypeParameters/& { NoTypeParameters, //< No type parameters. HasTypeParameters(&~[ty_param], //< Type parameters. @@ -558,9 +567,14 @@ struct NameBindings { fn defined_in_namespace(namespace: Namespace) -> bool { match namespace { - ModuleNS => return self.module_def != NoModuleDef, - TypeNS => return self.type_def != None, - ValueNS => return self.value_def != None + ModuleNS => { + match self.module_def { + NoModuleDef => false, + _ => true + } + } + TypeNS => return self.type_def.is_some(), + ValueNS => return self.value_def.is_some() } } @@ -1788,7 +1802,7 @@ struct Resolver { // processing imports here. (See the loop in // resolve_imports_for_module.) - if resolution_result != Indeterminate { + if !resolution_result.indeterminate() { match *import_directive.subclass { GlobImport => { assert module_.glob_count >= 1u; diff --git a/src/rustc/middle/trans/expr.rs b/src/rustc/middle/trans/expr.rs index b1ee870dbb5..0fe4f3cd917 100644 --- a/src/rustc/middle/trans/expr.rs +++ b/src/rustc/middle/trans/expr.rs @@ -1117,12 +1117,21 @@ fn trans_eager_binop(bcx: block, AShr(bcx, lhs, rhs) } else { LShr(bcx, lhs, rhs) } } + ast::eq | ast::ne | ast::lt | ast::ge | ast::le | ast::gt => { + if ty::type_is_bot(rhs_t) { + C_bool(false) + } else { + if !ty::type_is_scalar(rhs_t) { + bcx.tcx().sess.span_bug(binop_expr.span, + ~"non-scalar comparison"); + } + let cmpr = base::compare_scalar_types(bcx, lhs, rhs, rhs_t, op); + bcx = cmpr.bcx; + cmpr.val + } + } _ => { - let cmpr = base::trans_compare(bcx, op, - lhs, lhs_t, - rhs, rhs_t); - bcx = cmpr.bcx; - cmpr.val + bcx.tcx().sess.span_bug(binop_expr.span, ~"unexpected binop"); } }; diff --git a/src/rustc/middle/trans/shape.rs b/src/rustc/middle/trans/shape.rs index d65b0e1978c..cdbaf6e5ee2 100644 --- a/src/rustc/middle/trans/shape.rs +++ b/src/rustc/middle/trans/shape.rs @@ -516,12 +516,14 @@ fn gen_enum_shapes(ccx: @crate_ctxt) -> ValueRef { ranges[i].align.bounded && ranges[j].size.bounded && ranges[j].align.bounded { - if ranges[i].size >= ranges[j].size && - ranges[i].align >= ranges[j].align { + if ranges[i].size.min >= ranges[j].size.min && + ranges[i].align.min >= ranges[j].align.min { // Throw out j. candidates[j] = false; - } else if ranges[j].size >= ranges[i].size && - ranges[j].align >= ranges[j].align { + } else if ranges[j].size.min >= + ranges[i].size.min && + ranges[j].align.min >= + ranges[j].align.min { // Throw out i. candidates[i] = false; } diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs index e6476b57e70..b8d610e7a15 100644 --- a/src/rustc/middle/ty.rs +++ b/src/rustc/middle/ty.rs @@ -3081,8 +3081,8 @@ fn occurs_check(tcx: ctxt, sp: span, vid: TyVid, rt: t) { // Maintains a little union-set tree for inferred modes. `canon()` returns // the current head value for `m0`. -fn canon(tbl: hashmap>, - +m0: ast::inferable) -> ast::inferable { +fn canon(tbl: hashmap>, + +m0: ast::inferable) -> ast::inferable { match m0 { ast::infer(id) => match tbl.find(id) { None => m0, diff --git a/src/rustc/middle/typeck/check.rs b/src/rustc/middle/typeck/check.rs index f63f6f2e125..677a7a444f0 100644 --- a/src/rustc/middle/typeck/check.rs +++ b/src/rustc/middle/typeck/check.rs @@ -1132,7 +1132,13 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, let rhs_bot = check_expr_with(fcx, rhs, tvar); let result_t = match op { ast::eq | ast::lt | ast::le | ast::ne | ast::ge | - ast::gt => ty::mk_bool(fcx.ccx.tcx), + ast::gt => { + if !ty::type_is_scalar(lhs_t) { + fcx.ccx.tcx.sess.span_bug(expr.span, + ~"non-scalar compare"); + } + ty::mk_bool(fcx.ccx.tcx) + } _ => lhs_t }; fcx.write_ty(expr.id, result_t); @@ -1410,23 +1416,6 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, let typ = check_lit(fcx, lit); fcx.write_ty(id, typ); } - - // Something of a hack: special rules for comparison operators that - // simply unify LHS and RHS. This helps with inference as LHS and RHS - // do not need to be "resolvable". Some tests, particularly those with - // complicated trait requirements, fail without this---I think this code - // can be removed if we improve trait resolution to be more eager when - // possible. - ast::expr_binary(ast::ne, lhs, rhs) | - ast::expr_binary(ast::le, lhs, rhs) | - ast::expr_binary(ast::gt, lhs, rhs) | - ast::expr_binary(ast::ge, lhs, rhs) => { - let tcx = fcx.ccx.tcx; - let tvar = fcx.infcx().next_ty_var(); - bot |= check_expr_with(fcx, lhs, tvar); - bot |= check_expr_with(fcx, rhs, tvar); - fcx.write_ty(id, ty::mk_bool(tcx)); - } ast::expr_binary(op, lhs, rhs) => { bot |= check_binop(fcx, expr, op, lhs, rhs); } @@ -1806,7 +1795,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, } ast::expr_rec(fields, base) => { option::iter(base, |b| { check_expr(fcx, b, expected); }); - let expected = if expected == None && base != None { + let expected = if expected.is_none() && base.is_some() { Some(fcx.expr_ty(base.get())) } else { expected }; let flds = unpack_expected(fcx, expected, |sty| diff --git a/src/rustc/middle/typeck/infer/unify.rs b/src/rustc/middle/typeck/infer/unify.rs index 2793d0e4f5a..500a4d5b419 100644 --- a/src/rustc/middle/typeck/infer/unify.rs +++ b/src/rustc/middle/typeck/infer/unify.rs @@ -20,7 +20,7 @@ struct node { } impl infer_ctxt { - fn get( + fn get( vb: &vals_and_bindings, vid: V) -> node { let vid_u = vid.to_uint(); @@ -377,4 +377,4 @@ impl infer_ctxt { } -} \ No newline at end of file +} diff --git a/src/test/bench/shootout-k-nucleotide.rs b/src/test/bench/shootout-k-nucleotide.rs index 5f907e55a1f..c1d9a10a106 100644 --- a/src/test/bench/shootout-k-nucleotide.rs +++ b/src/test/bench/shootout-k-nucleotide.rs @@ -14,22 +14,22 @@ fn sort_and_fmt(mm: hashmap<~[u8], uint>, total: uint) -> ~str { return (xx as float) * 100f / (yy as float); } - pure fn le_by_val(kv0: &(TT,UU), - kv1: &(TT,UU)) -> bool { + pure fn le_by_val(kv0: &(TT,UU), + kv1: &(TT,UU)) -> bool { let (_, v0) = *kv0; let (_, v1) = *kv1; return v0 >= v1; } - pure fn le_by_key(kv0: &(TT,UU), - kv1: &(TT,UU)) -> bool { + pure fn le_by_key(kv0: &(TT,UU), + kv1: &(TT,UU)) -> bool { let (k0, _) = *kv0; let (k1, _) = *kv1; return k0 <= k1; } // sort by key, then by value - fn sortKV(orig: ~[(TT,UU)]) -> ~[(TT,UU)] { + fn sortKV(orig: ~[(TT,UU)]) -> ~[(TT,UU)] { return sort::merge_sort(le_by_val, sort::merge_sort(le_by_key, orig)); } diff --git a/src/test/run-pass/pipe-select.rs b/src/test/run-pass/pipe-select.rs index 783febf942c..29504d477a1 100644 --- a/src/test/run-pass/pipe-select.rs +++ b/src/test/run-pass/pipe-select.rs @@ -46,7 +46,7 @@ fn main() { error!("selecting"); let (i, m, _) = select(~[left, right]); error!("selected %?", i); - if m != None { + if m.is_some() { assert i == 1; } }); diff --git a/src/test/run-pass/structured-compare-recursive.rs b/src/test/run-pass/structured-compare-recursive.rs deleted file mode 100644 index 269cbf0363b..00000000000 --- a/src/test/run-pass/structured-compare-recursive.rs +++ /dev/null @@ -1,5 +0,0 @@ - - -enum taggy { foo(@taggy), bar, } - -fn main() { assert (bar <= bar); } diff --git a/src/test/run-pass/tag.rs b/src/test/run-pass/tag.rs index 1793f5f22a2..6d6e2ad09d0 100644 --- a/src/test/run-pass/tag.rs +++ b/src/test/run-pass/tag.rs @@ -4,6 +4,26 @@ // -*- rust -*- enum colour { red(int, int), green, } +impl colour : cmp::Eq { + pure fn eq(&&other: colour) -> bool { + match self { + red(a0, b0) => { + match other { + red(a1, b1) => a0 == a1 && b0 == b1, + green => false, + } + } + green => { + match other { + red(*) => false, + green => true + } + } + } + } + pure fn ne(&&other: colour) -> bool { !self.eq(other) } +} + fn f() { let x = red(1, 2); let y = green; assert (x != y); } fn main() { f(); } diff --git a/src/test/run-pass/while-prelude-drop.rs b/src/test/run-pass/while-prelude-drop.rs index 6315a92ca2d..9400840dd8e 100644 --- a/src/test/run-pass/while-prelude-drop.rs +++ b/src/test/run-pass/while-prelude-drop.rs @@ -1,6 +1,26 @@ enum t { a, b(~str), } +impl t : cmp::Eq { + pure fn eq(&&other: t) -> bool { + match self { + a => { + match other { + a => true, + b(_) => false + } + } + b(s0) => { + match other { + a => false, + b(s1) => s0 == s1 + } + } + } + } + pure fn ne(&&other: t) -> bool { !self.eq(other) } +} + fn make(i: int) -> t { if i > 10 { return a; } let mut s = ~"hello";