diff options
| author | bors <bors@rust-lang.org> | 2013-07-25 10:55:47 -0700 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2013-07-25 10:55:47 -0700 |
| commit | b1f5b1ba5fd12a058d153e9da8f11cd1bc597bf0 (patch) | |
| tree | d50a42ff7c3d172e21157325a1cbae7d33361f40 | |
| parent | baa649ede6df96f645a9e28acfdc0b66b63e48b5 (diff) | |
| parent | f929a49d9c07115124a168bcc9651956683b4c22 (diff) | |
| download | rust-b1f5b1ba5fd12a058d153e9da8f11cd1bc597bf0.tar.gz rust-b1f5b1ba5fd12a058d153e9da8f11cd1bc597bf0.zip | |
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`.
| -rw-r--r-- | src/librustc/middle/check_match.rs | 23 | ||||
| -rw-r--r-- | src/test/compile-fail/issue-6804.rs | 21 |
2 files changed, 43 insertions, 1 deletions
diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index 36edb567a50..793cd374718 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,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 => { diff --git a/src/test/compile-fail/issue-6804.rs b/src/test/compile-fail/issue-6804.rs new file mode 100644 index 00000000000..0a62e889d09 --- /dev/null +++ b/src/test/compile-fail/issue-6804.rs @@ -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 |
