]> git.lizzy.rs Git - rust.git/commitdiff
use rustc's eval_const, bail on (negative) infinity
authorAndre Bogus <bogusandre@gmail.com>
Tue, 10 Nov 2015 10:19:33 +0000 (11:19 +0100)
committerAndre Bogus <bogusandre@gmail.com>
Tue, 10 Nov 2015 10:23:47 +0000 (11:23 +0100)
src/misc.rs
tests/compile-fail/float_cmp.rs

index 01ecb2c2cf80fa34c87c8d3aa001e32b952c6359..85fd03079fe2d919a3d8d2c0eba763fd9728473e 100644 (file)
@@ -6,10 +6,12 @@
 use syntax::codemap::{Span, Spanned};
 use rustc_front::visit::FnKind;
 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::span_help_and_lint;
-use consts::constant;
 
 declare_lint!(pub TOPLEVEL_REF_ARG, Warn,
               "An entire binding was declared as `ref`, in a function argument (`fn foo(ref x: Bar)`), \
@@ -119,10 +121,7 @@ fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
         if let ExprBinary(ref cmp, ref left, ref right) = expr.node {
             let op = cmp.node;
             if (op == BiEq || op == BiNe) && (is_float(cx, left) || is_float(cx, right)) {
-                if constant(cx, left).or_else(|| constant(cx, right)).map_or(
-                        false, |c| c.0.as_float().map_or(false, |f| f == 0.0)) {
-                    return;
-                }
+                if is_allowed(cx, left) || is_allowed(cx, right) { return; }
                 if let Some(name) = get_item_name(cx, expr) {
                     let name = name.as_str();
                     if name == "eq" || name == "ne" || name == "is_nan" ||
@@ -141,6 +140,13 @@ fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
     }
 }
 
+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 {
     if let ty::TyFloat(_) = walk_ptrs_ty(cx.tcx.expr_ty(expr)).sty {
         true
index da3dba5e4d4a6d2669710ebd84dcb16fc57f7bec..27cde245f686a47c9c94603ddc09342827c181a8 100644 (file)
@@ -35,8 +35,10 @@ fn eq(&self, o: &X) -> bool {
 
 fn main() {
     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 + 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 == (1.0 + 0.0); //~ERROR ==-comparison of f32 or f64