rustc: Make shape-based compare glue never called for comparison operators.

Only called for string patterns.
This commit is contained in:
Patrick Walton 2012-09-07 18:53:14 -07:00
parent 9a15c50f6c
commit 22b8757705
22 changed files with 322 additions and 82 deletions

View File

@ -179,7 +179,7 @@ pure fn min<A:Copy Ord,IA:BaseIter<A>>(self: IA) -> A {
}
}
pure fn max<A:Copy,IA:BaseIter<A>>(self: IA) -> A {
pure fn max<A:Copy Ord,IA:BaseIter<A>>(self: IA) -> A {
match do foldl::<A,Option<A>,IA>(self, None) |a, b| {
match a {
Some(a_) if a_ > b => {

View File

@ -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 {

View File

@ -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
*

View File

@ -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 {

View File

@ -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

View File

@ -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)]

View File

@ -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 {

View File

@ -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);

View File

@ -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 {

View File

@ -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<ast::proto>, 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);
}

View File

@ -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

View File

@ -210,6 +210,15 @@ enum ResolveResult<T> {
Success(T) // Successfully resolved the import.
}
impl<T> ResolveResult<T> {
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;

View File

@ -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");
}
};

View File

@ -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;
}

View File

@ -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<T:Copy>(tbl: hashmap<ast::node_id, ast::inferable<T>>,
+m0: ast::inferable<T>) -> ast::inferable<T> {
fn canon<T:Copy cmp::Eq>(tbl: hashmap<ast::node_id, ast::inferable<T>>,
+m0: ast::inferable<T>) -> ast::inferable<T> {
match m0 {
ast::infer(id) => match tbl.find(id) {
None => m0,

View File

@ -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|

View File

@ -20,7 +20,7 @@ struct node<V:Copy, T:Copy> {
}
impl infer_ctxt {
fn get<V:Copy vid, T:Copy>(
fn get<V:Copy vid Eq, T:Copy>(
vb: &vals_and_bindings<V, T>, vid: V) -> node<V, T> {
let vid_u = vid.to_uint();
@ -377,4 +377,4 @@ impl infer_ctxt {
}
}
}

View File

@ -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<TT: Copy, UU: Copy>(kv0: &(TT,UU),
kv1: &(TT,UU)) -> bool {
pure fn le_by_val<TT: Copy Ord, UU: Copy Ord>(kv0: &(TT,UU),
kv1: &(TT,UU)) -> bool {
let (_, v0) = *kv0;
let (_, v1) = *kv1;
return v0 >= v1;
}
pure fn le_by_key<TT: Copy, UU: Copy>(kv0: &(TT,UU),
kv1: &(TT,UU)) -> bool {
pure fn le_by_key<TT: Copy Ord, UU: Copy Ord>(kv0: &(TT,UU),
kv1: &(TT,UU)) -> bool {
let (k0, _) = *kv0;
let (k1, _) = *kv1;
return k0 <= k1;
}
// sort by key, then by value
fn sortKV<TT: Copy, UU: Copy>(orig: ~[(TT,UU)]) -> ~[(TT,UU)] {
fn sortKV<TT: Copy Ord, UU: Copy Ord>(orig: ~[(TT,UU)]) -> ~[(TT,UU)] {
return sort::merge_sort(le_by_val, sort::merge_sort(le_by_key, orig));
}

View File

@ -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;
}
});

View File

@ -1,5 +0,0 @@
enum taggy { foo(@taggy), bar, }
fn main() { assert (bar <= bar); }

View File

@ -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(); }

View File

@ -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";