Skip to content

Fix comparisons of the nil type to do something sensible. #663

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

Closed
wants to merge 1 commit into from
Closed
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
40 changes: 19 additions & 21 deletions src/comp/middle/trans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2362,9 +2362,8 @@ fn make_cmp_glue(&@block_ctxt cx, ValueRef lhs0, ValueRef rhs0, &ty::t t,
rhs_fill = vec_fill(scx, rhs);
bcx = scx;
}
r =
compare_numerical_values(bcx, lhs_fill, rhs_fill,
unsigned_int, llop);
r = compare_scalar_values(bcx, lhs_fill, rhs_fill,
unsigned_int, llop);
r.bcx.build.Store(r.val, flag);
} else {
// == and <= default to true if they find == all the way. <
Expand Down Expand Up @@ -2441,18 +2440,18 @@ fn make_cmp_glue(&@block_ctxt cx, ValueRef lhs0, ValueRef rhs0, &ty::t t,


// Used only for creating scalar comparsion glue.
tag numerical_type { signed_int; unsigned_int; floating_point; }
tag scalar_type { nil_type; signed_int; unsigned_int; floating_point; }


fn compare_scalar_types(@block_ctxt cx, ValueRef lhs, ValueRef rhs, &ty::t t,
ValueRef llop) -> result {
// FIXME: this could be a lot shorter if we could combine multiple cases
// of alt expressions (issue #449).

auto f = bind compare_numerical_values(cx, lhs, rhs, _, llop);
auto f = bind compare_scalar_values(cx, lhs, rhs, _, llop);

alt (ty::struct(cx.fcx.lcx.ccx.tcx, t)) {
case (ty::ty_nil) { ret rslt(cx, C_bool(true)); }
case (ty::ty_nil) { ret f(nil_type); }
case (ty::ty_bool) { ret f(unsigned_int); }
case (ty::ty_int) { ret f(signed_int); }
case (ty::ty_float) { ret f(floating_point); }
Expand Down Expand Up @@ -2514,13 +2513,20 @@ fn make_scalar_cmp_glue(&@block_ctxt cx, ValueRef lhs, ValueRef rhs, &ty::t t,
}


// A helper function to compare numerical values.
fn compare_numerical_values(&@block_ctxt cx, ValueRef lhs, ValueRef rhs,
numerical_type nt, ValueRef llop) -> result {
// A helper function to do the actual comparison of scalar values.
fn compare_scalar_values(&@block_ctxt cx, ValueRef lhs, ValueRef rhs,
scalar_type nt, ValueRef llop) -> result {
auto eq_cmp;
auto lt_cmp;
auto le_cmp;
alt (nt) {
case (nil_type) {
// We don't need to do actual comparisons for nil.
// () == () holds but () < () does not.
eq_cmp = 1u;
lt_cmp = 0u;
le_cmp = 1u;
}
case (floating_point) {
eq_cmp = lib::llvm::LLVMRealUEQ;
lt_cmp = lib::llvm::LLVMRealULT;
Expand All @@ -2543,10 +2549,12 @@ fn compare_numerical_values(&@block_ctxt cx, ValueRef lhs, ValueRef rhs,
// the above, and "auto eq_result = cmp_fn(eq_cmp, lhs, rhs);" in the
// below.

fn generic_cmp(&@block_ctxt cx, numerical_type nt, uint op, ValueRef lhs,
fn generic_cmp(&@block_ctxt cx, scalar_type nt, uint op, ValueRef lhs,
ValueRef rhs) -> ValueRef {
let ValueRef r;
if (nt == floating_point) {
if (nt == nil_type) {
r = C_bool(op != 0u);
} else if (nt == floating_point) {
r = cx.build.FCmp(op, lhs, rhs);
} else { r = cx.build.ICmp(op, lhs, rhs); }
ret r;
Expand All @@ -2573,16 +2581,6 @@ fn compare_numerical_values(&@block_ctxt cx, ValueRef lhs, ValueRef rhs,
ret rslt(last_cx, last_result);
}


// A helper function to create numerical comparison glue.
fn make_numerical_cmp_glue(&@block_ctxt cx, ValueRef lhs, ValueRef rhs,
numerical_type nt, ValueRef llop) {
auto r = compare_numerical_values(cx, lhs, rhs, nt, llop);
r.bcx.build.Store(r.val, r.bcx.fcx.llretptr);
r.bcx.build.RetVoid();
}


type val_pair_fn = fn(&@block_ctxt, ValueRef, ValueRef) -> result ;

type val_and_ty_fn = fn(&@block_ctxt, ValueRef, ty::t) -> result ;
Expand Down
8 changes: 3 additions & 5 deletions src/test/run-pass/binops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,10 @@
fn test_nil() {
assert () == ();
assert !(() != ());
// FIXME (#576): The current implementation of relational ops on nil
// is nonsensical
assert () < ();
assert !(() < ());
assert () <= ();
assert !(() > ());
assert !(() >= ());
assert () >= ();
}

fn test_bool() {
Expand Down Expand Up @@ -159,4 +157,4 @@ fn main() {
test_fn();
test_native_fn();
test_obj();
}
}