about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2015-09-29 17:08:05 -0400
committerNiko Matsakis <niko@alum.mit.edu>2015-10-04 21:19:45 -0400
commit7e1e830a6f6f32b053b71ac628c0fbf8698ad888 (patch)
treeb058531f3e2ac045d38bf53d8d1fa021815d3ea9
parent0197f982b2c2d4dbf7d95fc28e0e47bce39ea944 (diff)
downloadrust-7e1e830a6f6f32b053b71ac628c0fbf8698ad888.tar.gz
rust-7e1e830a6f6f32b053b71ac628c0fbf8698ad888.zip
change PartialEq impl for ConstVal so that two constants are `==`
if they represent the same constant; otherwise the match algorithm
goes into infinite recursion when a pattern contains `NaN`
-rw-r--r--src/librustc/middle/const_eval.rs24
-rw-r--r--src/librustc_mir/repr.rs5
2 files changed, 28 insertions, 1 deletions
diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs
index 78acff0ada3..acda0fe2f0e 100644
--- a/src/librustc/middle/const_eval.rs
+++ b/src/librustc/middle/const_eval.rs
@@ -38,6 +38,7 @@ use std::borrow::{Cow, IntoCow};
 use std::num::wrapping::OverflowingOps;
 use std::cmp::Ordering;
 use std::collections::hash_map::Entry::Vacant;
+use std::mem::transmute;
 use std::{i8, i16, i32, i64, u8, u16, u32, u64};
 use std::rc::Rc;
 
@@ -242,7 +243,7 @@ pub fn lookup_const_fn_by_id<'tcx>(tcx: &ty::ctxt<'tcx>, def_id: DefId)
     }
 }
 
-#[derive(Clone, Debug, PartialEq)]
+#[derive(Clone, Debug)]
 pub enum ConstVal {
     Float(f64),
     Int(i64),
@@ -254,6 +255,27 @@ pub enum ConstVal {
     Tuple(ast::NodeId),
 }
 
+/// Note that equality for `ConstVal` means that the it is the same
+/// constant, not that the rust values are equal. In particular, `NaN
+/// == NaN` (at least if it's the same NaN; distinct encodings for NaN
+/// are considering unequal).
+impl PartialEq for ConstVal {
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn eq(&self, other: &ConstVal) -> bool {
+        match (self, other) {
+            (&Float(a), &Float(b)) => unsafe{transmute::<_,u64>(a) == transmute::<_,u64>(b)},
+            (&Int(a), &Int(b)) => a == b,
+            (&Uint(a), &Uint(b)) => a == b,
+            (&Str(ref a), &Str(ref b)) => a == b,
+            (&ByteStr(ref a), &ByteStr(ref b)) => a == b,
+            (&Bool(a), &Bool(b)) => a == b,
+            (&Struct(a), &Struct(b)) => a == b,
+            (&Tuple(a), &Tuple(b)) => a == b,
+            _ => false,
+        }
+    }
+}
+
 impl ConstVal {
     pub fn description(&self) -> &'static str {
         match *self {
diff --git a/src/librustc_mir/repr.rs b/src/librustc_mir/repr.rs
index e5a03cbb586..d522518a3d4 100644
--- a/src/librustc_mir/repr.rs
+++ b/src/librustc_mir/repr.rs
@@ -642,6 +642,10 @@ impl<H:Hair> Debug for Rvalue<H> {
 
 ///////////////////////////////////////////////////////////////////////////
 // Constants
+//
+// Two constants are equal if they are the same constant. Note that
+// this does not necessarily mean that they are "==" in Rust -- in
+// particular one must be wary of `NaN`!
 
 #[derive(Clone, Debug, PartialEq)]
 pub struct Constant<H:Hair> {
@@ -655,3 +659,4 @@ pub enum Literal<H:Hair> {
     Item { def_id: H::DefId, substs: H::Substs },
     Value { value: H::ConstVal },
 }
+