Skip to content

Commit b1f5b1b

Browse files
committed
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`.
2 parents baa649e + f929a49 commit b1f5b1b

File tree

2 files changed

+43
-1
lines changed

2 files changed

+43
-1
lines changed

src/librustc/middle/check_match.rs

+22-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111

1212
use middle::const_eval::{compare_const_vals, lookup_const_by_id};
13-
use middle::const_eval::{eval_const_expr, const_val, const_bool};
13+
use middle::const_eval::{eval_const_expr, const_val, const_bool, const_float};
1414
use middle::pat_util::*;
1515
use middle::ty::*;
1616
use middle::ty;
@@ -102,6 +102,27 @@ pub fn check_arms(cx: &MatchCheckCtxt, arms: &[arm]) {
102102
let mut seen = ~[];
103103
for arms.iter().advance |arm| {
104104
for arm.pats.iter().advance |pat| {
105+
106+
// Check that we do not match against a static NaN (#6804)
107+
let pat_matches_nan: &fn(@pat) -> bool = |p| {
108+
match cx.tcx.def_map.find(&p.id) {
109+
Some(&def_static(did, false)) => {
110+
let const_expr = lookup_const_by_id(cx.tcx, did).get();
111+
match eval_const_expr(cx.tcx, const_expr) {
112+
const_float(f) if f.is_NaN() => true,
113+
_ => false
114+
}
115+
}
116+
_ => false
117+
}
118+
};
119+
for walk_pat(*pat) |p| {
120+
if pat_matches_nan(p) {
121+
cx.tcx.sess.span_warn(p.span, "unmatchable NaN in pattern, \
122+
use the is_NaN method in a guard instead");
123+
}
124+
}
125+
105126
let v = ~[*pat];
106127
match is_useful(cx, &seen, v) {
107128
not_useful => {

src/test/compile-fail/issue-6804.rs

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Matching against NaN should result in a warning
2+
3+
use std::float::NaN;
4+
5+
fn main() {
6+
let x = NaN;
7+
match x {
8+
NaN => {},
9+
_ => {},
10+
};
11+
//~^^^ WARNING unmatchable NaN in pattern, use the is_NaN method in a guard instead
12+
match [x, 1.0] {
13+
[NaN, _] => {},
14+
_ => {},
15+
};
16+
//~^^^ WARNING unmatchable NaN in pattern, use the is_NaN method in a guard instead
17+
}
18+
19+
// At least one error is needed so that compilation fails
20+
#[static_assert]
21+
static b: bool = false; //~ ERROR static assertion failed

0 commit comments

Comments
 (0)