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
This commit is contained in:
Etienne Millon 2013-07-24 18:00:33 +02:00
parent 766eb950c6
commit 5c729c0dca
2 changed files with 33 additions and 1 deletions

View file

@ -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 => {

View file

@ -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