Skip to content

Check for comparisons to NaN in patterns #8029

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion src/librustc/middle/check_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 => {
Expand Down
21 changes: 21 additions & 0 deletions src/test/compile-fail/issue-6804.rs
Original file line number Diff line number Diff line change
@@ -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