diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 09f5d2a350769..99246b68e176d 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -506,6 +506,7 @@ pub fn compare_scalar_types<'a>( match ty::get(t).sty { ty::ty_nil => f(nil_type), + ty::ty_bare_fn(_) | ty::ty_bool | ty::ty_ptr(_) | ty::ty_uint(_) | ty::ty_char => f(unsigned_int), ty::ty_int(_) => f(signed_int), diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 6275abdc8ab20..bb636c9dec6d3 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -3986,59 +3986,64 @@ pub fn struct_fields(cx: &ctxt, did: ast::DefId, substs: &Substs) } pub fn is_binopable(cx: &ctxt, ty: t, op: ast::BinOp) -> bool { - static tycat_other: int = 0; - static tycat_bool: int = 1; - static tycat_char: int = 2; - static tycat_int: int = 3; - static tycat_float: int = 4; - static tycat_bot: int = 5; - static tycat_raw_ptr: int = 6; - - static opcat_add: int = 0; - static opcat_sub: int = 1; - static opcat_mult: int = 2; - static opcat_shift: int = 3; - static opcat_rel: int = 4; - static opcat_eq: int = 5; - static opcat_bit: int = 6; - static opcat_logic: int = 7; - static opcat_mod: int = 8; - - fn opcat(op: ast::BinOp) -> int { + enum TyCat { + Other = 0, + Bool, + Char, + Int, + Float, + Bot, + RawPtr, + Fn, + } + enum OpCat { + Add = 0, + Sub, + Mult, + Shift, + Rel, + Eq, + Bit, + Logic, + Mod, + } + + fn opcat(op: ast::BinOp) -> OpCat { match op { - ast::BiAdd => opcat_add, - ast::BiSub => opcat_sub, - ast::BiMul => opcat_mult, - ast::BiDiv => opcat_mult, - ast::BiRem => opcat_mod, - ast::BiAnd => opcat_logic, - ast::BiOr => opcat_logic, - ast::BiBitXor => opcat_bit, - ast::BiBitAnd => opcat_bit, - ast::BiBitOr => opcat_bit, - ast::BiShl => opcat_shift, - ast::BiShr => opcat_shift, - ast::BiEq => opcat_eq, - ast::BiNe => opcat_eq, - ast::BiLt => opcat_rel, - ast::BiLe => opcat_rel, - ast::BiGe => opcat_rel, - ast::BiGt => opcat_rel - } - } - - fn tycat(cx: &ctxt, ty: t) -> int { + ast::BiAdd => Add, + ast::BiSub => Sub, + ast::BiMul => Mult, + ast::BiDiv => Mult, + ast::BiRem => Mod, + ast::BiAnd => Logic, + ast::BiOr => Logic, + ast::BiBitXor => Bit, + ast::BiBitAnd => Bit, + ast::BiBitOr => Bit, + ast::BiShl => Shift, + ast::BiShr => Shift, + ast::BiEq => Eq, + ast::BiNe => Eq, + ast::BiLt => Rel, + ast::BiLe => Rel, + ast::BiGe => Rel, + ast::BiGt => Rel + } + } + + fn tycat(cx: &ctxt, ty: t) -> TyCat { if type_is_simd(cx, ty) { return tycat(cx, simd_type(cx, ty)) } match get(ty).sty { - ty_char => tycat_char, - ty_bool => tycat_bool, - ty_int(_) | ty_uint(_) | ty_infer(IntVar(_)) => tycat_int, - ty_float(_) | ty_infer(FloatVar(_)) => tycat_float, - ty_bot => tycat_bot, - ty_ptr(_) => tycat_raw_ptr, - _ => tycat_other + ty_char => Char, + ty_bool => Bool, + ty_int(_) | ty_uint(_) | ty_infer(IntVar(_)) => Int, + ty_float(_) | ty_infer(FloatVar(_)) => Float, + ty_bot => Bot, + ty_ptr(_) => RawPtr, + ty_bare_fn(_) => Fn, + _ => Other } } @@ -4053,7 +4058,9 @@ pub fn is_binopable(cx: &ctxt, ty: t, op: ast::BinOp) -> bool { /*int*/ [t, t, t, t, t, t, t, f, t], /*float*/ [t, t, t, f, t, t, f, f, f], /*bot*/ [t, t, t, t, t, t, t, t, t], - /*raw ptr*/ [f, f, f, f, t, t, f, f, f]]; + /*raw ptr*/ [f, f, f, f, t, t, f, f, f], + /*fn*/ [f, f, f, f, f, t, f, f, f], + ]; return tbl[tycat(cx, ty) as uint ][opcat(op) as uint]; } diff --git a/src/test/compile-fail/fn-compare-mismatch.rs b/src/test/compile-fail/fn-compare-mismatch.rs deleted file mode 100644 index 6178d37a5bd6c..0000000000000 --- a/src/test/compile-fail/fn-compare-mismatch.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn main() { - fn f() { } - fn g() { } - let x = f == g; - //~^ ERROR binary operation `==` cannot be applied -} diff --git a/src/test/run-pass/fn-eq.rs b/src/test/run-pass/fn-eq.rs new file mode 100644 index 0000000000000..098e89fe77014 --- /dev/null +++ b/src/test/run-pass/fn-eq.rs @@ -0,0 +1,44 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + +fn one(x: int) -> int { x + 1 } +fn two(x: int) -> int { x + 2 } + +fn generic(x: T) -> T { x } + +extern fn foo(_x: i32) {} +extern { + fn exit(n: i32); +} + +fn main() { + assert!(one == one); + assert!(one != two); + assert!(one != generic::); + + assert!(two != one); + assert!(two == two); + assert!(two != generic::); + + assert!(generic:: != one); + assert!(generic:: != two); + assert!(generic:: == generic::); + + assert!(foo == foo); + assert!(foo != exit); + assert!(exit != foo); + assert!(exit == exit); + + let bar: unsafe extern "C" fn(i32) = foo; + assert!(bar == foo); + assert!(bar != exit); + assert!(exit != bar); +}