about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorEtienne Millon <me@emillon.org>2013-07-24 18:00:33 +0200
committerEtienne Millon <me@emillon.org>2013-07-24 23:20:57 +0200
commit5c729c0dca65a014b6dec10cfd5259c6d0687d72 (patch)
tree1c60903581a094e90cc8c3ab4a3626e4de6a5706 /src
parent766eb950c6e7cdbab89e15200d0bd2dfee58e25e (diff)
downloadrust-5c729c0dca65a014b6dec10cfd5259c6d0687d72.tar.gz
rust-5c729c0dca65a014b6dec10cfd5259c6d0687d72.zip
Check for comparisons to NaN in patterns
For every pattern that refers to a static value, evaluate it and emit a warning
if it is a NaN.

Fixes #6804
Diffstat (limited to 'src')
-rw-r--r--src/librustc/middle/check_match.rs18
-rw-r--r--src/test/compile-fail/issue-6804.rs16
2 files changed, 33 insertions, 1 deletions
diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs
index 36edb567a50..18bf3859f07 100644
--- a/src/librustc/middle/check_match.rs
+++ b/src/librustc/middle/check_match.rs
@@ -10,7 +10,7 @@
 
 
 use middle::const_eval::{compare_const_vals, lookup_const_by_id};
-use middle::const_eval::{eval_const_expr, const_val, const_bool};
+use middle::const_eval::{eval_const_expr, const_val, const_bool, const_float};
 use middle::pat_util::*;
 use middle::ty::*;
 use middle::ty;
@@ -102,6 +102,22 @@ pub fn check_arms(cx: &MatchCheckCtxt, arms: &[arm]) {
     let mut seen = ~[];
     for arms.iter().advance |arm| {
         for arm.pats.iter().advance |pat| {
+
+            // Check that we do not match against a static NaN (#6804)
+            match cx.tcx.def_map.find(&pat.id) {
+                Some(&def_static(did, false)) => {
+                    let const_expr = lookup_const_by_id(cx.tcx, did).get();
+                    match eval_const_expr(cx.tcx, const_expr) {
+                        const_float(f) if f.is_NaN() => {
+                            let msg = "unmatchable NaN in pattern, use is_NaN() in a guard instead";
+                            cx.tcx.sess.span_warn(pat.span, msg);
+                        }
+                        _ => {}
+                    }
+                }
+                _ => {}
+            }
+
             let v = ~[*pat];
             match is_useful(cx, &seen, v) {
               not_useful => {
diff --git a/src/test/compile-fail/issue-6804.rs b/src/test/compile-fail/issue-6804.rs
new file mode 100644
index 00000000000..85e09a777d1
--- /dev/null
+++ b/src/test/compile-fail/issue-6804.rs
@@ -0,0 +1,16 @@
+// Matching against NaN should result in a warning
+
+use std::float::NaN;
+
+fn main() {
+    let x = NaN;
+    match x {
+        NaN => {},
+        _ => {},
+    };
+    //~^^^ WARNING unmatchable NaN in pattern, use is_NaN() in a guard instead
+}
+
+// At least one error is needed so that compilation fails
+#[static_assert]
+static b: bool = false; //~ ERROR static assertion failed