auto merge of #8029 : emillon/rust/issue-6804, r=cmr

Hi,

As noted in #6804, a pattern that contains `NaN` will never match because `NaN != NaN`. This adds a warning for such a case. The first commit handles the basic case and the second one generalizes it to more complex patterns using `walk_pat`.
This commit is contained in:
bors 2013-07-25 10:55:47 -07:00
commit b1f5b1ba5f
2 changed files with 43 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,27 @@ 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)
let pat_matches_nan: &fn(@pat) -> bool = |p| {
match cx.tcx.def_map.find(&p.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() => true,
_ => false
}
}
_ => false
}
};
for walk_pat(*pat) |p| {
if pat_matches_nan(p) {
cx.tcx.sess.span_warn(p.span, "unmatchable NaN in pattern, \
use the is_NaN method in a guard instead");
}
}
let v = ~[*pat];
match is_useful(cx, &seen, v) {
not_useful => {

View File

@ -0,0 +1,21 @@
// 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 the is_NaN method in a guard instead
match [x, 1.0] {
[NaN, _] => {},
_ => {},
};
//~^^^ WARNING unmatchable NaN in pattern, use the is_NaN method in a guard instead
}
// At least one error is needed so that compilation fails
#[static_assert]
static b: bool = false; //~ ERROR static assertion failed