Merge pull request #450 from Manishearth/mir_float_cmp

use rustc's eval_const, bail on (negative) infinity
This commit is contained in:
Manish Goregaokar 2015-11-10 21:19:47 +05:30
commit d57fa7bc5b
2 changed files with 14 additions and 6 deletions

View File

@ -6,10 +6,12 @@ use rustc_front::util::{is_comparison_binop, binop_to_string};
use syntax::codemap::{Span, Spanned}; use syntax::codemap::{Span, Spanned};
use rustc_front::visit::FnKind; use rustc_front::visit::FnKind;
use rustc::middle::ty; use rustc::middle::ty;
use rustc::middle::const_eval::ConstVal::Float;
use rustc::middle::const_eval::eval_const_expr_partial;
use rustc::middle::const_eval::EvalHint::ExprTypeChecked;
use utils::{get_item_name, match_path, snippet, span_lint, walk_ptrs_ty, is_integer_literal}; use utils::{get_item_name, match_path, snippet, span_lint, walk_ptrs_ty, is_integer_literal};
use utils::span_help_and_lint; use utils::span_help_and_lint;
use consts::constant;
declare_lint!(pub TOPLEVEL_REF_ARG, Warn, declare_lint!(pub TOPLEVEL_REF_ARG, Warn,
"An entire binding was declared as `ref`, in a function argument (`fn foo(ref x: Bar)`), \ "An entire binding was declared as `ref`, in a function argument (`fn foo(ref x: Bar)`), \
@ -119,10 +121,7 @@ impl LateLintPass for FloatCmp {
if let ExprBinary(ref cmp, ref left, ref right) = expr.node { if let ExprBinary(ref cmp, ref left, ref right) = expr.node {
let op = cmp.node; let op = cmp.node;
if (op == BiEq || op == BiNe) && (is_float(cx, left) || is_float(cx, right)) { if (op == BiEq || op == BiNe) && (is_float(cx, left) || is_float(cx, right)) {
if constant(cx, left).or_else(|| constant(cx, right)).map_or( if is_allowed(cx, left) || is_allowed(cx, right) { return; }
false, |c| c.0.as_float().map_or(false, |f| f == 0.0)) {
return;
}
if let Some(name) = get_item_name(cx, expr) { if let Some(name) = get_item_name(cx, expr) {
let name = name.as_str(); let name = name.as_str();
if name == "eq" || name == "ne" || name == "is_nan" || if name == "eq" || name == "ne" || name == "is_nan" ||
@ -141,6 +140,13 @@ impl LateLintPass for FloatCmp {
} }
} }
fn is_allowed(cx: &LateContext, expr: &Expr) -> bool {
let res = eval_const_expr_partial(cx.tcx, expr, ExprTypeChecked, None);
if let Ok(Float(val)) = res {
val == 0.0 || val == ::std::f64::INFINITY || val == ::std::f64::NEG_INFINITY
} else { false }
}
fn is_float(cx: &LateContext, expr: &Expr) -> bool { fn is_float(cx: &LateContext, expr: &Expr) -> bool {
if let ty::TyFloat(_) = walk_ptrs_ty(cx.tcx.expr_ty(expr)).sty { if let ty::TyFloat(_) = walk_ptrs_ty(cx.tcx.expr_ty(expr)).sty {
true true

View File

@ -35,8 +35,10 @@ impl PartialEq for X {
fn main() { fn main() {
ZERO == 0f32; //no error, comparison with zero is ok ZERO == 0f32; //no error, comparison with zero is ok
1.0f32 != ::std::f32::INFINITY; // also comparison with infinity
1.0f32 != ::std::f32::NEG_INFINITY; // and negative infinity
ZERO == 0.0; //no error, comparison with zero is ok ZERO == 0.0; //no error, comparison with zero is ok
ZERO + ZERO != 1.0; //~ERROR !=-comparison of f32 or f64 ZERO + ZERO != 1.0; //no error, comparison with zero is ok
ONE == 1f32; //~ERROR ==-comparison of f32 or f64 ONE == 1f32; //~ERROR ==-comparison of f32 or f64
ONE == (1.0 + 0.0); //~ERROR ==-comparison of f32 or f64 ONE == (1.0 + 0.0); //~ERROR ==-comparison of f32 or f64